diff options
author | Kotagiri, Ramprasad (rp5662) <rp5662@att.com> | 2020-08-07 15:54:10 -0400 |
---|---|---|
committer | Kotagiri, Ramprasad (rp5662) <rp5662@att.com> | 2020-08-12 12:38:26 -0400 |
commit | 09762dc92a06fb885f7055796db390a3a1baa535 (patch) | |
tree | e377c24a2cccb0a7d90b7b8560a7d8eef048a610 | |
parent | f796af3a840d0fd9319e3dfe45ef0e548cd90171 (diff) |
CCSDK DCAE dashboard feature changes
Issue-ID: DCAEGEN2-1857
Issue-ID: DCAEGEN2-2074
Issue-ID: DCAEGEN2-2364
Change-Id: I97f5ec4599512ed848136971b11d4c2a137a4999
Signed-off-by: Kotagiri, Ramprasad (rp5662) <rp5662@att.com>
182 files changed, 20738 insertions, 14340 deletions
diff --git a/ccsdk-app-common/pom.xml b/ccsdk-app-common/pom.xml index 2c3297b..875d9ea 100644 --- a/ccsdk-app-common/pom.xml +++ b/ccsdk-app-common/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-parent</artifactId> - <version>1.3.2-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-common</artifactId> - <version>1.3.2-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>jar</packaging> <name>ONAP Operations Manager Dashboard common</name> <description>CCSDK Dashboard common Java code</description> @@ -76,7 +76,6 @@ <build> <plugins> - <!-- Compile to Java 1.8 class output format --> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -87,7 +86,6 @@ <target>1.8</target> </configuration> </plugin> - <!-- Put version into jar also --> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -101,8 +99,8 @@ </archive> </configuration> </plugin> - <!-- Generate javadoc jar; see profile for Java 8 --> + <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> @@ -116,8 +114,9 @@ </execution> </executions> </plugin> - + --> <!-- Generate source jar --> + <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> @@ -131,6 +130,7 @@ </execution> </executions> </plugin> + --> <!-- jacoco --> <plugin> <groupId>org.jacoco</groupId> diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/ApiBaseController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/ApiBaseController.java new file mode 100644 index 0000000..ec30b92 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/ApiBaseController.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.api.controller; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.onap.ccsdk.dashboard.util.DashboardProperties; +import org.onap.portalsdk.core.controller.UnRestrictedBaseController; +import org.springframework.beans.factory.annotation.Autowired; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; + +public class ApiBaseController extends UnRestrictedBaseController { + + /** + * Application name + */ + protected static final String APP_NAME = "ecd-app"; + + /** + * EELF-approved format + */ + protected static final DateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + /** + * Query parameter for desired page number + */ + protected static final String PAGE_NUM_QUERY_PARAM = "page"; + + /** + * Query parameter for desired items per page + */ + protected static final String PAGE_SIZE_QUERY_PARAM = "size"; + + /** + * For general use in these methods and subclasses + */ + protected final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * Application properties - NOT available to constructor. + */ + @Autowired + protected DashboardProperties appProperties; + + + /** + * Hello Spring, here's your no-arg constructor. + */ + public ApiBaseController() { + // Do not serialize null values + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + // Register Jdk8Module() for Stream and Optional types + objectMapper.registerModule(new Jdk8Module()); + } + + /** + * Access method for subclasses. + * + * @return DbcappProperties object that was autowired by Spring. + */ + protected DashboardProperties getAppProperties() { + return appProperties; + } + + /** + * Gets the requested page number from a query parameter in the + * HttpServletRequest. Defaults to 1, which is useful to allow manual testing of + * endpoints without supplying those pesky parameters. + * + * @param request HttpServletRequest + * @return Value of query parameter {@link #PAGE_NUM_QUERY_PARAM}; 1 if not + * found. + */ + protected int getRequestPageNumber(HttpServletRequest request) { + int pageNum = 1; + String param = request.getParameter(PAGE_NUM_QUERY_PARAM); + if (param != null) + pageNum = Integer.parseInt(param); + return pageNum; + } + + /** + * Gets the requested page size from a query parameter in the + * HttpServletRequest. Defaults to 50, which is useful to allow manual testing + * of endpoints without supplying those pesky parameters. + * + * @param request HttpServletRequest + * @return Value of query parameter {@link #PAGE_SIZE_QUERY_PARAM}; 50 if not + * found. + */ + protected int getRequestPageSize(HttpServletRequest request) { + int pageSize = 25; + String param = request.getParameter(PAGE_SIZE_QUERY_PARAM); + if (param != null) + pageSize = Integer.parseInt(param); + return pageSize; + } + + /** + * Gets the items for the specified page from the specified list. + * + * @param pageNum Page number requested by user, indexed from 1 + * @param pageSize Number of items per page + * @param itemList List of items to adjust + * @return List of items; empty list if from==to + */ + @SuppressWarnings("rawtypes") + protected static List getPageOfList(final int pageNum, final int pageSize, final List itemList) { + int firstIndexOnThisPage = pageSize * (pageNum - 1); + int firstIndexOnNextPage = pageSize * pageNum; + int fromIndex = firstIndexOnThisPage < itemList.size() ? firstIndexOnThisPage : itemList.size(); + int toIndex = firstIndexOnNextPage < itemList.size() ? firstIndexOnNextPage : itemList.size(); + return itemList.subList(fromIndex, toIndex); + } + + @Override + public boolean isRESTfulCall() { + return true; + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/NbApiController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/NbApiController.java new file mode 100644 index 0000000..525711d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/NbApiController.java @@ -0,0 +1,1394 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.ccsdk.api.controller; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.HttpStatus; +import org.json.JSONObject; +import org.onap.aaf.cadi.CadiWrap; +import org.onap.ccsdk.dashboard.exceptions.BadRequestException; +import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException; +import org.onap.ccsdk.dashboard.exceptions.DownstreamException; +import org.onap.ccsdk.dashboard.exceptions.ServerErrorException; +import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException; +import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException; +import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException; +import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException; +import org.onap.ccsdk.dashboard.model.ECTransportModel; +import org.onap.ccsdk.dashboard.model.RestResponseError; +import org.onap.ccsdk.dashboard.model.RestResponsePage; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResource; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResourceLinks; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks; +import org.onap.ccsdk.dashboard.model.inventory.Blueprint; +import org.onap.ccsdk.dashboard.model.inventory.BlueprintInput; +import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRef; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; +import org.onap.ccsdk.dashboard.model.inventory.ServiceType; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest; +import org.onap.ccsdk.dashboard.rest.CloudifyClient; +import org.onap.ccsdk.dashboard.rest.ConsulClient; +import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient; +import org.onap.ccsdk.dashboard.rest.InventoryClient; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.objectcache.AbstractCacheManager; +import org.onap.portalsdk.core.util.SystemProperties; +import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; + +@RestController +@RequestMapping("/nb-api/v2") +public class NbApiController extends ApiBaseController { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(NbApiController.class); + + private static final String DEPLOYMENTS_PATH = "deployments"; + private static final String SERVICE_TYPES_PATH = "blueprints"; + private static final String EXECUTIONS_PATH = "executions"; + private static final String TENANTS_PATH = "tenants"; + private static final String SERVICE_HEALTH_PATH = "health"; + + @Autowired + InventoryClient inventoryClient; + + @Autowired + DeploymentHandlerClient deploymentHandlerClient; + + @Autowired + CloudifyClient cloudifyClient; + + @Autowired + ConsulClient consulClient; + + @Autowired + ApplicationEventPublisher eventPub; + + private AbstractCacheManager cacheManager; + + @Autowired + public void setCacheManager(AbstractCacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + public AbstractCacheManager getCacheManager() { + return cacheManager; + } + + /** + * Enum for selecting an item type. + */ + public enum InventoryDataItem { + DEPLOYMENTS, BLUEPRINTS, SERVICES_GROUPBY; + } + + private static Date begin, end; + + /** + * get the tenants list + * + * @param request HttpServletRequest + * @return List of CloudifyDeployment objects + */ + @SuppressWarnings("rawtypes") + @RequestMapping( + value = {TENANTS_PATH}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getTenants(HttpServletRequest request) throws Exception { + preLogAudit(request); + List itemList = cloudifyClient.getTenants().items; + final int totalItems = itemList.size(); + final int pageSize = 20; + final int pageNum = 1; + final int pageCount = (int) Math.ceil((double) totalItems / pageSize); + if (totalItems > pageSize) + itemList = getPageOfList(pageNum, pageSize, itemList); + RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); + String outboundJson = objectMapper.writeValueAsString(model); + return outboundJson; + } + + private boolean isAuthorized(HttpServletRequest request, String component) { + boolean auth = true; + return auth; + } + + @RequestMapping( + value = {SERVICE_TYPES_PATH}, + method = RequestMethod.POST, + produces = "application/json") + public String createBlueprint(HttpServletRequest request, HttpServletResponse response, + @RequestBody ServiceTypeUploadRequest serviceTypeUplReq, + ServletUriComponentsBuilder uriBuilder) throws Exception { + preLogAudit(request); + String json = null; + try { + Blueprint.parse(serviceTypeUplReq.getBlueprintTemplate()); + + if (serviceTypeUplReq.component == null || serviceTypeUplReq.component.isEmpty()) { + json = objectMapper.writeValueAsString( + new RestResponseError("Component name missing in blueprint request body")); + logger.error(EELFLoggerDelegate.errorLogger, + "Component name missing in blueprint request body"); + return json; + } + + if (!isAuthorized(request, serviceTypeUplReq.component)) { + response.setStatus(HttpStatus.SC_FORBIDDEN); + json = objectMapper.writeValueAsString( + new RestResponseError("Un-authorized to perform this operation")); + return json; + } + + Collection<String> serviceIds = new ArrayList<String>(); + Collection<String> vnfTypes = new ArrayList<String>(); + Collection<String> serviceLocations = new ArrayList<String>(); + Optional<String> asdcServiceId = null; + Optional<String> asdcResourceId = null; + Optional<String> asdcServiceURL = null; + + ServiceTypeRequest invSrvcTypeReq = + new ServiceTypeRequest(serviceTypeUplReq.owner, serviceTypeUplReq.typeName, + serviceTypeUplReq.typeVersion, serviceTypeUplReq.blueprintTemplate, + serviceTypeUplReq.application, serviceTypeUplReq.component, serviceIds, + vnfTypes, serviceLocations, asdcServiceId, asdcResourceId, asdcServiceURL); + ServiceType apiResponse = inventoryClient.addServiceType(invSrvcTypeReq); + json = objectMapper.writeValueAsString(apiResponse); + String uri = request.getRequestURI(); + if (uri != null) { + String uri_all = uriBuilder.replacePath(uri).build().toUriString(); + String uri_self = + uriBuilder.path("/" + apiResponse.getTypeId().get()).build().toUriString(); + StringBuffer linkHeader = new StringBuffer(); + String linkStr_all = "<" + uri_all + ">; rel=\"" + "current" + "\""; + String linkStr_self = "<" + uri_self + ">; rel=\"" + "self" + "\""; + linkHeader.append(linkStr_self); + if (linkHeader.length() > 0) { + linkHeader.append(", "); + } + linkHeader.append(linkStr_all); + response.addHeader("Link", linkHeader.toString()); + } + } catch (BlueprintParseException e) { + response.setStatus(HttpStatus.SC_BAD_REQUEST); + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "DCAE Inventory"); + MDC.put("TargetServiceName", "DCAE Inventory"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Updating service type failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "updateServiceTypeBlueprint caught exception"); + json = objectMapper + .writeValueAsString(new RestResponseError("Invalid blueprint format.", e)); + } catch (HttpStatusCodeException e) { + response.setStatus(HttpStatus.SC_BAD_GATEWAY); + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "DCAE Inventory"); + MDC.put("TargetServiceName", "DCAE Inventory"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Updating service type failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "updateServiceTypeBlueprint caught exception"); + json = + objectMapper.writeValueAsString(new RestResponseError(e.getResponseBodyAsString())); + } catch (Throwable t) { + response.setStatus(HttpStatus.SC_BAD_REQUEST); + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "DCAE Inventory"); + MDC.put("TargetServiceName", "DCAE Inventory"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Updating service type failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "updateServiceTypeBlueprint caught exception"); + json = objectMapper + .writeValueAsString(new RestResponseError("updateServiceTypeBlueprint failed", t)); + } finally { + postLogAudit(request); + } + return json; + } + + @SuppressWarnings("unchecked") + @RequestMapping( + value = {SERVICE_TYPES_PATH}, + method = RequestMethod.GET, + produces = "application/json") + public String getBlueprintsByPage(HttpServletRequest request, + @RequestParam(value = "page", required = false) Integer page, + @RequestParam(value = "size", required = false) Integer size, + ServletUriComponentsBuilder uriBuilder, HttpServletResponse response) { + preLogAudit(request); + String json = null; + if (page == null || page == 0) { + page = 1; + } + if (size == null) { + size = 25; + } + int pageNum = page; + int totalItems = 0; + List itemList = null; + try { + itemList = getItemListForPageWrapper(request, InventoryDataItem.BLUEPRINTS); + // Shrink if needed + if (itemList != null) { + totalItems = itemList.size(); + } + final int pageCount = (int) Math.ceil((double) totalItems / size); + if (totalItems > size) + itemList = getPageOfList(pageNum, size, itemList); + + RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); + json = objectMapper.writeValueAsString(model); + + try { + uriBuilder = ServletUriComponentsBuilder.fromCurrentRequest(); + eventPub.publishEvent(new PaginatedResultsRetrievedEvent<String>(String.class, + uriBuilder, response, page, pageCount, size)); + } catch (Exception e) { + // skip exception + } + } catch (Exception e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting page of blueprints items failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getBlueprintsByPage caught exception"); + RestResponseError result = null; + if (e instanceof HttpStatusCodeException) + result = + new RestResponseError(((HttpStatusCodeException) e).getResponseBodyAsString()); + else + result = new RestResponseError("Failed to get blueprints", e); + try { + json = objectMapper.writeValueAsString(result); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + json = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + return json; + } finally { + postLogAudit(request); + } + return json; + } + + private List getItemListForPageWrapper(HttpServletRequest request, InventoryDataItem option) { + Set<String> userRoleSet = (Set<String>) request.getAttribute("userRoles"); + Set<String> userApps = (Set<String>) request.getAttribute("userApps"); + String sort = request.getParameter("sort"); + + Predicate<String> adminPred = + p -> p.contains("System_Administrator") || p.contains("Write_Access"); + + Predicate<String> ecompSuperPred = + p -> p.contains("ECOMPC_WRITE") || p.contains("ECOMPC_READ"); + + ReadWriteLock lock = new ReentrantReadWriteLock(); + List itemList = null; + try { + lock.readLock().lock(); + itemList = (List<ServiceTypeSummary>) getCacheManager().getObject("dcae-service-types"); + lock.readLock().unlock(); + if (itemList == null) { + ServiceTypeQueryParams serviceQueryParams = null; + itemList = inventoryClient.getServiceTypes().collect(Collectors.toList()); + } + if (userRoleSet != null) { + if (userRoleSet.stream().noneMatch(adminPred)) { + if (userRoleSet.stream().noneMatch(ecompSuperPred)) { + itemList = (List<ServiceTypeSummary>) itemList.stream() + .filter(s -> userApps.stream() + .anyMatch(appFilter -> (((ServiceTypeSummary) s).getComponent() != null + && ((ServiceTypeSummary) s).getComponent() + .equalsIgnoreCase(appFilter)))) + .collect(Collectors.<ServiceTypeSummary>toList()); + } else { + Predicate<ServiceTypeSummary> appFilter = + p -> p.getComponent() != null && !p.getComponent().equalsIgnoreCase("dcae"); + itemList = (List<ServiceTypeSummary>) itemList.stream().filter(appFilter) + .collect(Collectors.toList()); + } + } + } + // Handle request filter object + String filters = request.getParameter("filters"); + if (filters != null) { + JSONObject filterJson = new JSONObject(filters); + + if (filterJson.has("owner")) { + String ownFilter = filterJson.getString("owner"); + Predicate<ServiceTypeSummary> ownPred = + p -> p.getOwner() != null && p.getOwner().contains(ownFilter); + itemList = (List<ServiceTypeSummary>) itemList.stream().filter(ownPred) + .collect(Collectors.toList()); + } + + if (filterJson.has("name")) { + String bpNameFilter = filterJson.getString("name"); + Predicate<ServiceTypeSummary> bpNamePred = + p -> p.getTypeName() != null && p.getTypeName().contains(bpNameFilter); + itemList = (List<ServiceTypeSummary>) itemList.stream().filter(bpNamePred) + .collect(Collectors.toList()); + } + + if (filterJson.has("id")) { + String bpIdFilter = filterJson.getString("id"); + Predicate<ServiceTypeSummary> bpIdPred = + p -> p.getTypeId().get().contains(bpIdFilter); + itemList = (List<ServiceTypeSummary>) itemList.stream().filter(bpIdPred) + .collect(Collectors.toList()); + } + } + if (sort != null) { + if (sort.equals("owner")) { + ((List<ServiceTypeSummary>) itemList).sort((ServiceTypeSummary o1, + ServiceTypeSummary o2) -> o1.getOwner().compareTo(o2.getOwner())); + } else if (sort.equals("typeId")) { + ((List<ServiceTypeSummary>) itemList) + .sort((ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeId().get() + .compareTo(o2.getTypeId().get())); + } else if (sort.equals("typeName")) { + ((List<ServiceTypeSummary>) itemList).sort((ServiceTypeSummary o1, + ServiceTypeSummary o2) -> o1.getTypeName().compareTo(o2.getTypeName())); + } else if (sort.equals("typeVersion")) { + ((List<ServiceTypeSummary>) itemList) + .sort((ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeVersion() + .compareTo(o2.getTypeVersion())); + } else if (sort.equals("created")) { + ((List<ServiceTypeSummary>) itemList) + .sort((ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getCreated() + .get().compareTo(o2.getCreated().get())); + } + } + } catch (Exception e) { + throw e; + } finally { + postLogAudit(request); + } + return itemList; + } + + @RequestMapping( + value = {DEPLOYMENTS_PATH + "/{deploymentId}"}, + method = RequestMethod.GET, + produces = "application/json") + public String getDeployment(@PathVariable("deploymentId") String deploymentId, + HttpServletRequest request) { + preLogAudit(request); + String json = null; + try { + List<CloudifyDeployment> items = cloudifyClient.getDeployment(deploymentId).items; + json = objectMapper.writeValueAsString(items); + } catch (Exception gen) { + logger.error(EELFLoggerDelegate.errorLogger, "getDeployment caught exception"); + RestResponseError result = null; + if (gen instanceof HttpStatusCodeException) + result = new RestResponseError( + ((HttpStatusCodeException) gen).getResponseBodyAsString()); + else + result = new RestResponseError("Failed to get deployment", gen); + try { + json = objectMapper.writeValueAsString(result); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + json = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + } finally { + postLogAudit(request); + } + return json; + } + + @SuppressWarnings("unchecked") + @RequestMapping( + value = {DEPLOYMENTS_PATH}, + method = RequestMethod.GET, + produces = "application/json") + public String getDeploymentsByPage(HttpServletRequest request, + @RequestParam(value = "page", required = false) Integer page, + @RequestParam(value = "size", required = false) Integer size, + ServletUriComponentsBuilder uriBuilder, HttpServletResponse response) { + preLogAudit(request); + String outboundJson = null; + if (page == null || page == 0) { + page = 1; + } + if (size == null) { + size = 25; + } + int pageNum = page; + int totalItems = 0; + List<CloudifyDeployment> itemList = null; + try { + itemList = cloudifyClient.getDeploymentsWithFilter(request); + + // Shrink if needed + if (itemList != null) { + totalItems = itemList.size(); + } + final int pageCount = (int) Math.ceil((double) totalItems / size); + if (totalItems > size) { + itemList = getPageOfList(pageNum, size, itemList); + } + RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); + outboundJson = objectMapper.writeValueAsString(model); + try { + uriBuilder = ServletUriComponentsBuilder.fromCurrentRequest(); + eventPub.publishEvent(new PaginatedResultsRetrievedEvent<String>(String.class, + uriBuilder, response, page, pageCount, size)); + } catch (Exception e) { + // skip the pagination links logic + } + return outboundJson; + } catch (Exception e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting page of deployments items failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getAllDeploymentsByPage caught exception"); + RestResponseError result = null; + if (e instanceof HttpStatusCodeException) + result = + new RestResponseError(((HttpStatusCodeException) e).getResponseBodyAsString()); + else + result = new RestResponseError("Failed to get deployments", e); + try { + outboundJson = objectMapper.writeValueAsString(result); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + return outboundJson; + } finally { + postLogAudit(request); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private ServiceTypeSummary getBlueprintItem(String searchBy, Optional<Integer> version, + String typeId) throws Exception { + ServiceTypeQueryParams serviceQueryParams = null; + ServiceTypeSummary item = null; + if (version.isPresent()) { + serviceQueryParams = + new ServiceTypeQueryParams.Builder().typeName(searchBy).onlyLatest(false).build(); + } else { + serviceQueryParams = new ServiceTypeQueryParams.Builder().typeName(searchBy).build(); + } + + List itemList = + inventoryClient.getServiceTypes(serviceQueryParams).collect(Collectors.toList()); + + if (version.isPresent()) { + itemList = (List) itemList.stream() + .filter(s -> ((ServiceTypeSummary) s).contains(version.get().toString())) + .collect(Collectors.toList()); + } + if (typeId != null && typeId.equals("typeId")) { + item = (ServiceTypeSummary) ((List) itemList).get(0); + } + return item; + } + + /** + * Query inputs used to create a deployment + * + * @param deploymentId + * @param tenant + * @param request + * @return + * @throws Exception + */ + @RequestMapping( + value = {DEPLOYMENTS_PATH + "/{deploymentId}/inputs"}, + method = RequestMethod.GET, + produces = "application/json") + public String getDeploymentInputs(@PathVariable("deploymentId") String deploymentId, + @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request) + throws Exception { + preLogAudit(request); + ECTransportModel result = null; + String json = ""; + try { + if (tenant == null) { + throw new Exception("tenant name is missing"); + } + List<CloudifyDeployment> response = + cloudifyClient.getDeploymentInputs(deploymentId, tenant).items; + json = objectMapper.writeValueAsString(response); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", + "Getting executions for deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getExecutionByIdAndDeploymentId caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + json = objectMapper.writeValueAsString(result); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", + "Getting executions for deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getExecutionByIdAndDeploymentId caught exception"); + result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); + json = objectMapper.writeValueAsString(result); + } finally { + postLogAudit(request); + } + return json; + } + + /** + * Create an upgrade/rollback workflow execution for a deployment. + * + * @param request HttpServletRequest + * @param execution Execution model + * @return Information about the execution + * @throws Exception on serialization failure + */ + @RequestMapping( + value = {DEPLOYMENTS_PATH + "/{deploymentId}"}, + method = RequestMethod.PUT, + produces = "application/json") + public String modifyDeployment(@PathVariable("deploymentId") String deploymentId, + HttpServletRequest request, InputStream upgParams) throws Exception { + preLogAudit(request); + ECTransportModel result = null; + try { + String nodeInstId = ""; + Map<String, Object> parameters = + objectMapper.readValue(upgParams, new TypeReference<Map<String, Object>>() {}); + String tenant = (String) parameters.get("tenant"); + String workflow = (String) parameters.get("workflow"); + parameters.remove("tenant"); + parameters.remove("workflow"); + // get the node instance ID for the deployment + CloudifyNodeInstanceIdList nodeInstList = + cloudifyClient.getNodeInstanceId(deploymentId, tenant); + if (nodeInstList != null) { + nodeInstId = nodeInstList.items.get(0).id; + } + parameters.put("node_instance_id", nodeInstId); + if (workflow.equals("upgrade")) { + String repo_user = cloudifyClient.getSecret("controller_helm_user", tenant).value; + String repo_user_password = + cloudifyClient.getSecret("controller_helm_password", tenant).value; + parameters.put("repo_user", repo_user); + parameters.put("repo_user_password", repo_user_password); + } + CloudifyExecutionRequest execution = new CloudifyExecutionRequest(deploymentId, + workflow, false, false, tenant, parameters); + result = cloudifyClient.startExecution(execution); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Updating deployment failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Updating Deployment failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception"); + result = new RestResponseError("updateDeployment failed", t); + } finally { + postLogAudit(request); + } + return objectMapper.writeValueAsString(result); + } + + @RequestMapping( + value = {SERVICE_TYPES_PATH + "/{typeid}" + "/deployments"}, + method = RequestMethod.GET, + produces = "application/json") + public String getServicesForType(HttpServletRequest request, + @PathVariable("typeid") String typeId) throws Exception { + preLogAudit(request); + List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>(); + ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build(); + ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); + ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, srvcRefs); + result.add(srvcMap); + return objectMapper.writeValueAsString(result); + } + + private static void mergeInputData(Map<String, Object> bpInputs, Map<String, Object> dataSet, + String key, Object val) { + Object keyVal = dataSet.get(key); + if (keyVal != null) { + bpInputs.put(key, keyVal); + } else { + Object bpInput = ((BlueprintInput) val).getDefaultValue(); + if (bpInput != null) { + bpInputs.put(key, bpInput); + } else { + bpInputs.put(key, ""); + } + } + } + + private static void translateInputData(Map<String, Object> dataSet, String key, Object val) { + try { + if (val instanceof java.lang.String) { + int numericVal = Integer.parseInt((String) val); + dataSet.put(key, numericVal); + } else { + dataSet.put(key, val); + } + } catch (NumberFormatException ne) { + dataSet.put(key, val); + } catch (Exception e) { + dataSet.put(key, val); + } + } + + @RequestMapping( + value = {DEPLOYMENTS_PATH}, + method = RequestMethod.POST, + produces = "application/json") + public String createDeployment(HttpServletRequest request, HttpServletResponse response, + @RequestBody DeploymentInput deploymentRequestObject) throws Exception { + preLogAudit(request); + String json = null; + StringBuffer status = new StringBuffer(); + Optional<Integer> bpVersion = null; + String srvcTypeId = null; + ServiceTypeSummary bpSummItem = null; + ServiceType bpItem = null; + String bpName = deploymentRequestObject.getBlueprintName(); + String cName = deploymentRequestObject.getComponent(); + String tag = deploymentRequestObject.getTag(); + String depName = cName + "_" + tag; + Map<String, BlueprintInput> bpInputDefs = null; + + if (cName == null || cName.isEmpty()) { + json = objectMapper.writeValueAsString( + new RestResponseError("Component name missing in deployment request body")); + logger.error(EELFLoggerDelegate.errorLogger, + "Component name missing in deployment request body"); + return json; + } + + if (!isAuthorized(request, cName)) { + response.setStatus(HttpStatus.SC_FORBIDDEN); + json = objectMapper.writeValueAsString( + new RestResponseError("Un-authorized to perform this operation")); + return json; + } + + if (deploymentRequestObject.getBlueprintVersion().isPresent()) { + bpVersion = deploymentRequestObject.getBlueprintVersion(); + } + if (deploymentRequestObject.getBlueprintId().isPresent()) { + srvcTypeId = deploymentRequestObject.getBlueprintId().get(); + } + if (srvcTypeId == null) { + // get the serviceTypeId from inventory using the blueprint name + try { + bpSummItem = getBlueprintItem(bpName, bpVersion, "typeId"); + srvcTypeId = bpSummItem.getTypeId().get(); + bpItem = inventoryClient.getServiceType(srvcTypeId).get(); + } catch (Exception ex) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting blueprint ID failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getItemListForPageWrapper caught exception"); + RestResponseError result = null; + if (ex instanceof HttpStatusCodeException) + result = new RestResponseError( + ((HttpStatusCodeException) ex).getResponseBodyAsString()); + else + result = new RestResponseError("Failed to get blueprint", ex); + try { + json = objectMapper.writeValueAsString(result); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + json = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + return json; + } finally { + postLogAudit(request); + } + } else { + try { + bpItem = inventoryClient.getServiceType(srvcTypeId).get(); + } catch (Exception ex) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting blueprint failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception"); + RestResponseError result = null; + if (ex instanceof HttpStatusCodeException) + result = new RestResponseError( + ((HttpStatusCodeException) ex).getResponseBodyAsString()); + else + result = new RestResponseError("Failed to get blueprint", ex); + try { + json = objectMapper.writeValueAsString(result); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + json = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + return json; + } finally { + postLogAudit(request); + } + } + try { + // process the JSON inputs + Map<String, Object> processedInputs = new HashMap<String, Object>(); + Map<String, Object> mergedInputs = new HashMap<String, Object>(); + deploymentRequestObject.getInputs() + .forEach((k, v) -> translateInputData(processedInputs, k, v)); + // merge the user inputs with BP input list + bpInputDefs = bpItem.getBlueprintInputs(); + bpInputDefs.forEach((k, v) -> mergeInputData(mergedInputs, processedInputs, k, v)); + DeploymentResponse resp = + deploymentHandlerClient.putDeployment(depName, deploymentRequestObject.getTenant(), + new DeploymentRequest(srvcTypeId, mergedInputs)); + DeploymentResponseLinks deplLinks = resp.getLinks(); + String deplStatus = deplLinks.getStatus(); + if (!deplStatus.contains("cfy_tenant")) { + deplStatus = deplStatus + "?cfy_tenant_name=" + deploymentRequestObject.getTenant(); + } + String self = request.getRequestURL().append("/").append(depName).toString(); + status.append(self).append("/executions?tenant=") + .append(deploymentRequestObject.getTenant()); + DeploymentResource deplRsrc = new DeploymentResource(depName, + new DeploymentResourceLinks(self, deplStatus, status.toString())); + JSONObject statObj = new JSONObject(deplRsrc); + json = statObj.toString(); + response.setStatus(HttpStatus.SC_ACCEPTED); + } catch (BadRequestException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deployment failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (ServiceAlreadyExistsException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deployment failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (ServerErrorException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deployment failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (DownstreamException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deployment failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API controller"); + MDC.put("TargetServiceName", "API controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deployment failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception"); + json = + objectMapper.writeValueAsString(new RestResponseError("putDeployment failed", t)); + } finally { + postLogAudit(request); + } + return json; + } + + /** + * Get the executions for one deployment. + * + * + * @param deployment_id Deployment ID (query parameter) + * @param request HttpServletRequest + * @return CloudifyExecutionList + * @throws Exception on serialization failure + */ + @RequestMapping( + value = {DEPLOYMENTS_PATH + "/{deploymentId}" + "/" + EXECUTIONS_PATH}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getExecutionByDeploymentId(@PathVariable("deploymentId") String deploymentId, + @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request) + throws Exception { + preLogAudit(request); + ECTransportModel result = null; + try { + if (tenant == null) { + throw new Exception("tenant name is missing"); + } + result = cloudifyClient.getExecutionsSummary(deploymentId, tenant); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", + "Getting executions for deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getExecutionByIdAndDeploymentId caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", + "Getting executions for deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getExecutionByIdAndDeploymentId caught exception"); + result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); + } finally { + postLogAudit(request); + } + return objectMapper.writeValueAsString(result); + } + + /** + * Gets the service health for a deployment + * + * + * @param deployment_id Deployment ID (query parameter) + * @param request HttpServletRequest + * @return String + * @throws Exception on serialization failure + */ + @RequestMapping( + value = {DEPLOYMENTS_PATH + "/{deploymentId}" + "/" + SERVICE_HEALTH_PATH}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getServiceHealthByDeploymentId(@PathVariable("deploymentId") String deploymentId, + HttpServletRequest request) throws Exception { + preLogAudit(request); + Object result = null; + try { + result = consulClient.getServiceHealthByDeploymentId(deploymentId); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", + "Getting executions for deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getExecutionByIdAndDeploymentId caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", + "Getting executions for deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, + "getExecutionByIdAndDeploymentId caught exception"); + result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); + } finally { + postLogAudit(request); + } + return objectMapper.writeValueAsString(result); + } + + /** + * Query the specified blueprint. + * + * @param id Blueprint ID + * @param request HttpServletRequest + * @param response HttpServletResponse + * @return status code on success; error on failure. + * @throws Exception On serialization failure + */ + @SuppressWarnings("unchecked") + @RequestMapping( + value = {SERVICE_TYPES_PATH + "/{typeid}"}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String queryBlueprint(@PathVariable("typeid") String typeId, HttpServletRequest request, + HttpServletResponse response, ServletUriComponentsBuilder uriBuilder) throws Exception { + String json = ""; + Optional<ServiceType> resultItem = null; + try { + resultItem = inventoryClient.getServiceType(typeId); + if (resultItem.isPresent()) { + json = objectMapper.writeValueAsString(resultItem.get()); + } + String uri = request.getRequestURI(); + if (uri != null && !uri.isEmpty()) { + String uri_depl = + uriBuilder.replacePath(uri).path("/deployments").build().toUriString(); + StringBuffer linkHeader = new StringBuffer(); + String linkStr_depl = "<" + uri_depl + ">; rel=\"" + "deployments" + "\""; + linkHeader.append(linkStr_depl); + response.addHeader("Link", linkHeader.toString()); + } + } catch (Exception e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting page of blueprints items failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getBlueprintsByPage caught exception"); + RestResponseError result = null; + if (e instanceof HttpStatusCodeException) + result = + new RestResponseError(((HttpStatusCodeException) e).getResponseBodyAsString()); + else + result = new RestResponseError("Failed to get blueprints", e); + try { + json = objectMapper.writeValueAsString(result); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + json = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + } + return json; + } + + /** + * Deletes the specified blueprint. + * + * @param id Blueprint ID + * @param request HttpServletRequest + * @param response HttpServletResponse + * @return status code on success; error on failure. + * @throws Exception On serialization failure + */ + @SuppressWarnings("unchecked") + @RequestMapping( + value = {SERVICE_TYPES_PATH + "/{typeid}"}, + method = RequestMethod.DELETE, + produces = "application/json") + @ResponseBody + public String deleteBlueprint(@PathVariable("typeid") String typeId, HttpServletRequest request, + HttpServletResponse response, ServletUriComponentsBuilder uriBuilder) throws Exception { + preLogAudit(request); + String json = "{\"204\": \"Blueprint deleted\"}"; + String bpComp = ""; + boolean allow = true; + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + @SuppressWarnings("unchecked") + List itemList = + (List<ServiceTypeSummary>) getCacheManager().getObject("dcae-service-types"); + lock.readLock().unlock(); + try { + if (itemList != null) { + Predicate<ServiceTypeSummary> idFilter = p -> p.getTypeId().get().equals(typeId); + + itemList = (List<ServiceTypeSummary>) itemList.stream().filter(idFilter) + .collect(Collectors.toList()); + bpComp = ((ServiceTypeSummary) itemList.get(0)).getComponent(); + } else { + try { + ServiceType item = inventoryClient.getServiceType(typeId).get(); + bpComp = ((ServiceType) item).getComponent(); + } catch (NoSuchElementException nse) { + throw new ServiceTypeNotFoundException("invalid blueprint ID given in query"); + } + } + if (!isAuthorized(request, bpComp)) { + response.setStatus(HttpStatus.SC_FORBIDDEN); + json = objectMapper.writeValueAsString( + new RestResponseError("Un-authorized to perform this operation")); + return json; + } + /* + ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build(); + ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); + if (srvcRefs != null && srvcRefs.totalCount > 0) { + throw new Exception( + "Services exist for the service type template, delete not permitted"); + } + */ + + // check if these dep_ids exist in cloudify + List<CloudifyDeployedTenant> deplForBp = + cloudifyClient.getDeploymentForBlueprint("TID-"+typeId); + if (deplForBp.size() > 0 ) { + allow = false; + } else { + ServiceQueryParams qryParams = + new ServiceQueryParams.Builder().typeId(typeId).build(); + ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); + Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet()); + if (dep_ids.size() > 0) { + // now check again if these dep_ids still exist in cloudify + List<String> allDepNames = cloudifyClient.getDeploymentNamesWithFilter(request); + for (String str: dep_ids) { + if (allDepNames.stream().anyMatch(s->s.equalsIgnoreCase(str))) { + allow = false; + break; + } + } + } + } + if (!allow) { + response.setStatus(HttpStatus.SC_BAD_REQUEST); + json = objectMapper.writeValueAsString( + new RestResponseError("ERROR: Deployments exist for this blueprint")); + /* + PrintWriter out = response.getWriter(); + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + out.print(json); + out.flush(); + */ + return json; + } else { + inventoryClient.deleteServiceType(typeId); + String uri = request.getRequestURI(); + if (uri != null && !uri.isEmpty()) { + String uri_str = uri.substring(0, uri.lastIndexOf("/")); + String uri_all = uriBuilder.replacePath(uri_str).build().toUriString(); + StringBuffer linkHeader = new StringBuffer(); + String linkStr = "<" + uri_all + ">; rel=\"" + "current" + "\""; + linkHeader.append(linkStr); + response.addHeader("Link", linkHeader.toString()); + } + } + } catch (ServiceTypeNotFoundException e) { + response.setStatus(HttpStatus.SC_GONE); + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (ServiceTypeAlreadyDeactivatedException e) { + response.setStatus(HttpStatus.SC_GONE); + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (Throwable t) { + response.setStatus(HttpStatus.SC_BAD_GATEWAY); + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); + json = + objectMapper.writeValueAsString(new RestResponseError("deleteBlueprint failed", t)); + } finally { + postLogAudit(request); + } + return json; + } + + /** + * Un-deploy an application or service + * + * @param deploymentId + * @param request + * @param tenant + * @param response + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + @RequestMapping( + value = {DEPLOYMENTS_PATH + "/{deploymentId}"}, + method = RequestMethod.DELETE, + produces = "application/json") + public String deleteDeployment(@PathVariable("deploymentId") String deploymentId, + HttpServletRequest request, @RequestParam(value = "tenant", required = true) String tenant, + HttpServletResponse response) throws Exception { + preLogAudit(request); + String json = null; + StringBuffer status = new StringBuffer(); + try { + if (tenant == null) { + throw new Exception("tenant name is missing"); + } + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + @SuppressWarnings("unchecked") + List itemList = (List<CloudifyDeployment>) getCacheManager() + .getObject("service-list" + ":" + tenant); + lock.readLock().unlock(); + if (itemList != null) { + Predicate<CloudifyDeployment> idFilter = p -> p.id.equals(deploymentId); + itemList = (List<CloudifyDeployment>) itemList.stream().filter(idFilter) + .collect(Collectors.toList()); + } else { + CloudifyDeploymentList cfyDeplList = + cloudifyClient.getDeployment(deploymentId, tenant); + if (cfyDeplList != null && !cfyDeplList.items.isEmpty()) { + itemList = cfyDeplList.items; + } + } + if (itemList != null && !itemList.isEmpty()) { + String depItem = ((CloudifyDeployment) itemList.get(0)).id; + if (depItem.contains("_")) { + String depComp = depItem.split("_")[0]; + if (!isAuthorized(request, depComp)) { + response.setStatus(HttpStatus.SC_FORBIDDEN); + json = objectMapper.writeValueAsString( + new RestResponseError("Un-authorized to perform this operation")); + return json; + } + deploymentHandlerClient.deleteDeployment(deploymentId, tenant); + String self = request.getRequestURL().toString().split("\\?")[0]; + status.append(self).append("/executions?tenant=").append(tenant); + DeploymentResource deplRsrc = new DeploymentResource(deploymentId, + new DeploymentResourceLinks(self, "", status.toString())); + JSONObject statObj = new JSONObject(deplRsrc); + json = statObj.toString(); + } + } + } catch (BadRequestException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (ServerErrorException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (DownstreamException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (DeploymentNotFoundException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); + json = objectMapper + .writeValueAsString(new RestResponseError("deleteDeployment failed", t)); + } finally { + postLogAudit(request); + } + return json; + } + + /** + * Cancels an execution. + * + * @param id Execution ID + * @param deploymentId Deployment ID (not clear why this is needed) + * @param action Action to perform (not clear why this is needed) + * @param request HttpServletRequest + * @param response HttpServletRequest + * @return Passes thru HTTP status code from remote endpoint; no body on success + * @throws Exception on serialization failure + */ + @RequestMapping( + value = {EXECUTIONS_PATH + "/{id}"}, + method = RequestMethod.POST, + produces = "application/json") + @ResponseBody + public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id, + @RequestBody Map<String, String> parameters, HttpServletRequest request, + HttpServletResponse response) throws Exception { + preLogAudit(request); + ECTransportModel result = null; + List<String> tenant = null; + try { + tenant = headers.get("tenant"); + result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0)); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); + result = new RestResponseError("cancelExecution failed on ID " + id, t); + } finally { + postLogAudit(request); + } + if (result == null) + return null; + else + return objectMapper.writeValueAsString(result); + } + + private void preLogAudit(HttpServletRequest request) { + begin = new Date(); + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin)); + MDC.put(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin)); + MDC.put(SystemProperties.STATUS_CODE, "COMPLETE"); + String user = null; + if (request instanceof CadiWrap) { + user = ((CadiWrap) request).getUser(); + } + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME, user, user); + } + + private void postLogAudit(HttpServletRequest request) { + end = new Date(); + MDC.put("AlertSeverity", "0"); + MDC.put("TargetEntity", "API Controller"); + MDC.put("TargetServiceName", "API Controller"); + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(end)); + MDC.put(SystemProperties.METRICSLOG_END_TIMESTAMP, logDateFormat.format(end)); + // MDC.put(SystemProperties.MDC_TIMER, Long.toString((end.getTime() - begin.getTime()))); + logger.info(EELFLoggerDelegate.auditLogger, + request.getMethod() + " " + request.getRequestURI()); + logger.info(EELFLoggerDelegate.metricsLogger, + request.getMethod() + " " + request.getRequestURI()); + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PaginatedResultsRetrievedEvent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PaginatedResultsRetrievedEvent.java new file mode 100644 index 0000000..051f6e6 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PaginatedResultsRetrievedEvent.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.api.controller; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.ApplicationEvent; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +public class PaginatedResultsRetrievedEvent<T> extends ApplicationEvent { + + /** + * + */ + private static final long serialVersionUID = 1513813910132068908L; + private Class clazz; + private ServletUriComponentsBuilder uriBuilder; + private HttpServletResponse response; + private int page; + private int maxPages; + private int pageSize; + + public PaginatedResultsRetrievedEvent(Class clazz, + ServletUriComponentsBuilder uriBuilder, HttpServletResponse response, + int page, int maxPages, int pageSize) { + super(clazz); + this.clazz = clazz; + this.uriBuilder = uriBuilder; + this.response = response; + this.page = page; + this.maxPages = maxPages; + this.pageSize = pageSize; + } + + public Class getClazz() { + return clazz; + } + + public ServletUriComponentsBuilder getUriBuilder() { + return uriBuilder; + } + + public HttpServletResponse getResponse() { + return response; + } + + public int getPage() { + return page; + } + + public int getPageSize() { + return pageSize; + } + + public int getMaxPages() { + return maxPages; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PagingEventListener.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PagingEventListener.java new file mode 100644 index 0000000..7b310c6 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PagingEventListener.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.api.controller; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import org.springframework.web.util.UriComponentsBuilder; + +@Component +public class PagingEventListener implements + ApplicationListener<PaginatedResultsRetrievedEvent> { + + + public static final String REL_COLLECTION = "collection"; + public static final String REL_NEXT = "next"; + public static final String REL_PREV = "prev"; + public static final String REL_FIRST = "first"; + public static final String REL_LAST = "last"; + private static final String PAGE = "page"; + + @Override + public void onApplicationEvent(PaginatedResultsRetrievedEvent event) { + addLinkHeaderOnPagedResourceRetrieval(event.getUriBuilder(), + event.getResponse(), event.getClazz(), event.getPage(), + event.getMaxPages(), event.getPageSize()); + } + + void addLinkHeaderOnPagedResourceRetrieval(ServletUriComponentsBuilder uriBuilder, + HttpServletResponse response, Class clazz, int page, + int totalPages, int size) { + + StringBuilder linkHeader = new StringBuilder(); + if (hasNextPage(page, totalPages)) { + String uriNextPage = constructNextPageUri(uriBuilder, page, size); + linkHeader.append(createLinkHeader(uriNextPage, "next")); + } + if (hasPreviousPage(page)) { + String uriPrevPage = constructPrevPageUri(uriBuilder, page, size); + appendCommaIfNecessary(linkHeader); + linkHeader.append(createLinkHeader(uriPrevPage, "prev")); + } + if (hasFirstPage(page)) { + String uriFirstPage = constructFirstPageUri(uriBuilder, size); + appendCommaIfNecessary(linkHeader); + linkHeader.append(createLinkHeader(uriFirstPage, "first")); + } + if (hasLastPage(page, totalPages)) { + String uriLastPage = constructLastPageUri(uriBuilder, totalPages, + size); + appendCommaIfNecessary(linkHeader); + linkHeader.append(createLinkHeader(uriLastPage, "last")); + } + response.addHeader("Link", linkHeader.toString()); + + } + + final String constructNextPageUri(final UriComponentsBuilder uriBuilder, + final int page, final int size) { + return uriBuilder.replaceQueryParam(PAGE, page + 1) + .replaceQueryParam("size", size).build().toUriString(); + } + + final String constructPrevPageUri(final UriComponentsBuilder uriBuilder, + final int page, final int size) { + return uriBuilder.replaceQueryParam(PAGE, page - 1) + .replaceQueryParam("size", size).build().toUriString(); + } + + final String constructFirstPageUri(final UriComponentsBuilder uriBuilder, + final int size) { + return uriBuilder.replaceQueryParam(PAGE, 1) + .replaceQueryParam("size", size).build().toUriString(); + } + + final String constructLastPageUri(final UriComponentsBuilder uriBuilder, + final int totalPages, final int size) { + return uriBuilder.replaceQueryParam(PAGE, totalPages) + .replaceQueryParam("size", size).build().toUriString(); + } + + final boolean hasNextPage(final int page, final int totalPages) { + return page < totalPages - 1; + } + + final boolean hasPreviousPage(final int page) { + return page > 1; + } + + final boolean hasFirstPage(final int page) { + return hasPreviousPage(page); + } + + final boolean hasLastPage(final int page, final int totalPages) { + return totalPages > 1 && hasNextPage(page, totalPages); + } + + final void appendCommaIfNecessary(final StringBuilder linkHeader) { + if (linkHeader.length() > 0) { + linkHeader.append(", "); + } + } + + // template + + protected void plural(final UriComponentsBuilder uriBuilder, + final Class clazz) { + final String resourceName = clazz.getSimpleName().toString().toLowerCase() + "s"; + //uriMapper.getUriBase(clazz); + uriBuilder.path("/" + resourceName); + } + + public static String createLinkHeader(final String uri, final String rel) { + return "<" + uri + ">; rel=\"" + rel + "\""; + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CloudifyController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CloudifyController.java index 93748f3..ae0e849 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CloudifyController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CloudifyController.java @@ -2,7 +2,7 @@ * =============LICENSE_START========================================================= * * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,41 +22,63 @@ package org.onap.ccsdk.dashboard.controller; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; - +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; -import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployment; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest; -import org.onap.ccsdk.dashboard.model.CloudifyEvent; -import org.onap.ccsdk.dashboard.model.CloudifyEventList; -import org.onap.ccsdk.dashboard.model.CloudifyExecution; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList; -import org.onap.ccsdk.dashboard.model.CloudifyTenant; import org.onap.ccsdk.dashboard.model.ECTransportModel; import org.onap.ccsdk.dashboard.model.RestResponseError; import org.onap.ccsdk.dashboard.model.RestResponsePage; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEvent; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPlugin; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenant; +import org.onap.ccsdk.dashboard.model.cloudify.ServiceRefCfyList; +import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth; +import org.onap.ccsdk.dashboard.model.inventory.Service; +import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRef; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; import org.onap.ccsdk.dashboard.rest.CloudifyClient; +import org.onap.ccsdk.dashboard.rest.ConsulClient; +import org.onap.ccsdk.dashboard.rest.InventoryClient; import org.onap.portalsdk.core.domain.User; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.objectcache.AbstractCacheManager; import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.portalsdk.core.web.support.AppUtils; import org.onap.portalsdk.core.web.support.UserUtils; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -66,7 +88,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.client.HttpStatusCodeException; - import com.fasterxml.jackson.core.JsonProcessingException; /** @@ -83,12 +104,16 @@ public class CloudifyController extends DashboardRestrictedBaseController { @Autowired CloudifyClient cloudifyClient; + @Autowired + InventoryClient inventoryClient; + @Autowired + ConsulClient consulClient; /** * Enum for selecting an item type. */ public enum CloudifyDataItem { - BLUEPRINT, DEPLOYMENT, EXECUTION, TENANT; + BLUEPRINT, DEPLOYMENT, EXECUTION, TENANT, SERVICE_ID, SERVICE_ID_COUNT; } private static Date begin; @@ -98,10 +123,24 @@ public class CloudifyController extends DashboardRestrictedBaseController { private static final String EXECUTIONS_PATH = "executions"; private static final String TENANTS_PATH = "tenants"; private static final String NODE_INSTANCES_PATH = "node-instances"; - private static final String UPDATE_DEPLOYMENT_PATH = "update-deployment"; private static final String EVENTS_PATH = "events"; - private static final String DEP_TENANT_STATUS = "deployment-status"; + private static final String SERVICE_ID = "service-list"; + private static final String SERVICE_ID_COUNT = "service-list-count"; + private static final String PLUGINS_PATH = "plugins"; + private static final String PLUGIN_COUNT = "plugins-count"; + private static final String SERVICE_TYPES = "dcae-service-types"; + + private AbstractCacheManager cacheManager; + + @Autowired + public void setCacheManager(AbstractCacheManager cacheManager) { + this.cacheManager = cacheManager; + } + public AbstractCacheManager getCacheManager() { + return cacheManager; + } + /** * Supports sorting events by timestamp */ @@ -122,6 +161,58 @@ public class CloudifyController extends DashboardRestrictedBaseController { } }; + private void updateBpOwnerId(List<CloudifyDeployment> itemList, + Map<String, List<CloudifyDeployedTenant>> ownerDepMap) { + for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) { + for (Map.Entry<String, List<CloudifyDeployedTenant>> entry : + ownerDepMap.entrySet()) { + List<CloudifyDeployedTenant> deplExtItems = + entry.getValue().stream().filter((Predicate<? super CloudifyDeployedTenant>) s->s.id.equals(srvc.id)). + collect(Collectors.toList()); + if (deplExtItems != null && deplExtItems.size() > 0) { + srvc.owner = entry.getKey(); + break; + } + } + } + } + + private void updateWorkflowHelmStatus(List<CloudifyDeployment> itemList, + List<CloudifyDeploymentExt> cfyDeplExt, + List<CloudifyDeploymentHelm> cfyDeplHelm) { + for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) { + // correlate the cached data for deployments and deployment extensions + List<CloudifyDeploymentExt> deplExtItems = + cfyDeplExt.stream().filter((Predicate<? super CloudifyDeploymentExt>) s->s.id.equals(srvc.id)). + collect(Collectors.toList()); + if (deplExtItems != null && deplExtItems.size() > 0) { + srvc.lastExecution = deplExtItems.get(0).lastExecution; + } + } + for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) { + // correlate the cached data for deployments and deployment helm info + List<CloudifyDeploymentHelm> deplHelmItems = + cfyDeplHelm.stream().filter((Predicate<? super CloudifyDeploymentHelm>) s->s.id.equals(srvc.id)). + collect(Collectors.toList()); + if (deplHelmItems != null && deplHelmItems.size() > 0) { + srvc.helmStatus = deplHelmItems.get(0).helmStatus; + srvc.isHelm = deplHelmItems.get(0).isHelm; + } + } + } + + private void updateHelmInfo(List<CloudifyDeployment> itemList, + List<CloudifyDeploymentExt> cfyDeplExt) { + for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) { + // correlate the cached data for deployments and deployment extensions + List<CloudifyDeploymentExt> deplExtItems = + cfyDeplExt.stream().filter((Predicate<? super CloudifyDeploymentExt>) s->s.id.equals(srvc.id)). + collect(Collectors.toList()); + srvc.helmStatus = deplExtItems.get(0).helmStatus; + srvc.isHelm = deplExtItems.get(0).isHelm; + } + } + /** * Gets one page of objects and supporting information via the REST client. On * success, returns a PaginatedRestResponse object as String. @@ -132,23 +223,300 @@ public class CloudifyController extends DashboardRestrictedBaseController { * @return JSON block as String, see above. * @throws Exception On any error; e.g., Network failure. */ - @SuppressWarnings({"rawtypes"}) - private String getItemListForPage(long userId, CloudifyDataItem option, int pageNum, - int pageSize) throws Exception { - /* - * if (this.restClient == null) { this.restClient = - * getCloudifyRestClient(userId); } - */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private String getItemListForPage(HttpServletRequest request, long userId, + CloudifyDataItem option, int pageNum, int pageSize, String sortBy, String searchBy) + throws Exception { + HttpSession session = AppUtils.getSession(request); + String user = UserUtils.getUserSession(request).getLoginId(); + HashMap<String, Boolean> comp_deploy_tab = + (HashMap<String, Boolean>) session.getAttribute("comp_access"); + String roleLevel = (String) session.getAttribute("role_level"); + String roleAuth = (String) session.getAttribute("auth_role"); + if (roleAuth == null) { + roleAuth = "READ"; + } + if (roleLevel == null) { + roleLevel = "dev"; + } + if (comp_deploy_tab == null) { + comp_deploy_tab = new HashMap<String, Boolean>(); + } + Set<String> userApps = (Set<String>) session.getAttribute("authComponents"); + if (userApps == null) { + userApps = new TreeSet<String>(); + } List itemList = null; + new ArrayList<Service>(); + int totalItems = 0; + int deplPgSize = 500; + int deplPgOffset = 0; + String tenantFilterStr = ""; + String cacheFilterStr = "true"; + String userFilterStr = "false"; + String svcRefFilterStr = ""; + String statusFilterStr = ""; + String helmFilterStr = ""; + String ownerFilterStr = ""; + ReadWriteLock lock = new ReentrantReadWriteLock(); + List<CloudifyDeploymentExt> cfyDeplExt = null; + List<CloudifyDeploymentExt> cfyDepExList = new ArrayList<CloudifyDeploymentExt>(); + List<CloudifyDeploymentHelm> cfyDeplHelm = null; + List<CloudifyDeploymentHelm> cfyDeplHelmList = new ArrayList<CloudifyDeploymentHelm>(); + boolean useCache = true; + boolean userLevel = false; + List<CloudifyTenant> cfyTenantList = null; + // apply tenant search filter + if (searchBy != null && !searchBy.isEmpty()) { + // parse the search filters string + List<String> searchFilters = + new ArrayList<String>(Arrays.asList(searchBy.split(";"))); + if (searchFilters.stream().anyMatch(s->s.startsWith("tenant"))) { + List<String> tenantsList = searchFilters.stream().filter(s->s.startsWith("tenant")). + collect(Collectors.toList()); + if (tenantsList.get(0).split(":").length > 1) { + tenantFilterStr = tenantsList.get(0).split(":")[1]; + } + } + if (searchFilters.stream().anyMatch(s->s.startsWith("cache"))) { + List<String> cacheStr = searchFilters.stream().filter(s->s.startsWith("cache")). + collect(Collectors.toList()); + cacheFilterStr = cacheStr.get(0).split(":")[1]; + useCache = Boolean.parseBoolean(cacheFilterStr); + } + if (searchFilters.stream().anyMatch(s->s.startsWith("user"))) { + List<String> userStr = searchFilters.stream().filter(s->s.startsWith("user")). + collect(Collectors.toList()); + userFilterStr = userStr.get(0).split(":")[1]; + userLevel = Boolean.parseBoolean(userFilterStr); + } + if (searchFilters.stream().anyMatch(s->s.startsWith("owner"))) { + List<String> ownerList = searchFilters.stream().filter(s->s.startsWith("owner")). + collect(Collectors.toList()); + ownerFilterStr = ownerList.get(0).split(":")[1]; + } + } + lock.readLock().lock(); + Map<String, List<CloudifyDeployedTenant>> deplPerOwner = + (Map<String, List<CloudifyDeployedTenant>>) getCacheManager().getObject("owner_deploy_map"); + lock.readLock().unlock(); switch (option) { - /* - * case BLUEPRINT: itemList = restClient.getBlueprints().items; - * Collections.sort(itemList, blueprintComparator); break; case DEPLOYMENT: - * itemList = restClient.getDeployments().items; Collections.sort(itemList, - * deploymentComparator); break; - */ + case SERVICE_ID_COUNT: + List items = null; + if (!ownerFilterStr.isEmpty()) { + if (deplPerOwner != null) { + List<CloudifyDeployedTenant> ownerDeplList = deplPerOwner.get(user); + items = ownerDeplList; + } + } else { + List<CloudifyDeployment> itemsList = + cloudifyClient.getDeploymentsWithFilter(request); + items = itemsList; + } + if (items == null) { + items = new ArrayList<CloudifyDeployment>(); + } + totalItems = items.size(); + RestResponsePage<List> model = + new RestResponsePage<>(totalItems, 1, items); + String outboundJson = objectMapper.writeValueAsString(model); + return outboundJson; + case SERVICE_ID: + final String svcIdTenant = tenantFilterStr; + if (useCache) { + lock.readLock().lock(); + itemList = + (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + svcIdTenant); + lock.readLock().unlock(); + } + if (itemList == null) { + itemList = cloudifyClient.getDeployments(tenantFilterStr, deplPgSize, deplPgOffset, true); + } + Set<String> svcIdList = new HashSet<String>(); + if (itemList != null) { + svcIdList = + (Set) itemList.stream().map(x -> ((CloudifyDeployment)x).id).collect(Collectors.toSet()); + // apply role based filtering + if (roleLevel.equals("app")) { + @SuppressWarnings("unchecked") + List<String> myApps = new ArrayList(userApps); + svcIdList = svcIdList.stream().filter(s -> myApps.stream() + .anyMatch(roleFilter -> ((String)s).toLowerCase().startsWith(roleFilter))) + .collect(Collectors.toSet()); + } + } + return objectMapper.writeValueAsString(svcIdList); + case DEPLOYMENT: + itemList = new ArrayList<CloudifyDeployment>(); + List<CloudifyDeployment> cfyDepPerTntList = null; + List<CloudifyDeployment> cfyDepList = null; + try { + if (tenantFilterStr.isEmpty()) { + cfyDepList = new ArrayList<CloudifyDeployment>(); + if (useCache) { + lock.readLock().lock(); + cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH); + for (CloudifyTenant cfyTenObj: cfyTenantList) { + cfyDepPerTntList = (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + cfyTenObj.name); + cfyDepList.addAll(cfyDepPerTntList); + } + lock.readLock().unlock(); + } else { + cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items; + for (CloudifyTenant cfyTenObj: cfyTenantList) { + cfyDepPerTntList = cloudifyClient.getDeployments(cfyTenObj.name, deplPgSize, deplPgOffset, true, false); + cfyDepList.addAll(cfyDepPerTntList); + } + } + } else { + if (useCache) { + lock.readLock().lock(); + cfyDepList = (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenantFilterStr); + lock.readLock().unlock(); + } + if (cfyDepList == null) { + cfyDepList = cloudifyClient.getDeployments(tenantFilterStr, deplPgSize, deplPgOffset, true, false); + } + } + totalItems = cfyDepList.size(); + + if (useCache) { + lock.readLock().lock(); + cfyDeplExt = + (List<CloudifyDeploymentExt>)getCacheManager().getObject(SERVICE_ID + ":" + tenantFilterStr + ":ext"); + if (cfyDeplExt != null) { + cfyDepExList.addAll(cfyDeplExt); + } + cfyDeplHelm = + (List<CloudifyDeploymentHelm>)getCacheManager().getObject(SERVICE_ID + ":" + tenantFilterStr + ":helm"); + if (cfyDeplHelm != null) { + cfyDeplHelmList.addAll(cfyDeplHelm); + } + lock.readLock().unlock(); + } + + if (roleLevel.equals("app") && !userLevel) { + @SuppressWarnings("unchecked") + List<String> myApps = new ArrayList(userApps); + cfyDepList = (List) cfyDepList.stream().filter(s -> myApps.stream() + .anyMatch(roleFilter -> ((CloudifyDeployment)s).id.toLowerCase().startsWith(roleFilter))) + .collect(Collectors.toList()); + } + // apply user search filters + if (searchBy != null && !searchBy.isEmpty()) { + // parse the search filters string + // look for service name patterns + List<String> searchFilters = + new ArrayList<String>(Arrays.asList(searchBy.split(";"))); + if (searchFilters.stream().anyMatch(s->s.startsWith("serviceRef"))) { + List<String> svcRefsList = searchFilters.stream().filter(s->s.startsWith("serviceRef")). + collect(Collectors.toList()); + svcRefFilterStr = svcRefsList.get(0).split(":")[1]; + } + if (searchFilters.stream().anyMatch(s->s.startsWith("status"))) { + List<String> statusList = searchFilters.stream().filter(s->s.startsWith("status")). + collect(Collectors.toList()); + statusFilterStr = statusList.get(0).split(":")[1]; + } + if (searchFilters.stream().anyMatch(s->s.startsWith("helm"))) { + List<String> helmList = searchFilters.stream().filter(s->s.startsWith("helm")). + collect(Collectors.toList()); + helmFilterStr = helmList.get(0).split(":")[1]; + } + if (!ownerFilterStr.isEmpty()) { + List ownerFilterList = + new ArrayList<String>(Arrays.asList(ownerFilterStr.split(","))); + if (ownerFilterList.size() == 1 && ownerFilterList.get(0).equals("undefined")) { + ownerFilterList.clear(); + ownerFilterList.add(user); + } + if (deplPerOwner != null && cfyDepList != null) { + List<CloudifyDeployedTenant> ownerDeplList = new ArrayList<CloudifyDeployedTenant>(); + Stream<Map.Entry<String, List<CloudifyDeployedTenant>>> deplOwnerEntriesStream = + deplPerOwner.entrySet().stream(); + Set<Map.Entry<String, List<CloudifyDeployedTenant>>> deplOwnerSet = + deplOwnerEntriesStream.filter(m -> ownerFilterList.stream(). + anyMatch(ownFilter -> m.getKey().equalsIgnoreCase((String) ownFilter))).collect(Collectors.toSet()); + deplOwnerSet.stream().forEach(e -> ownerDeplList.addAll(e.getValue())); + if (ownerDeplList.size() > 0) { + Predicate<CloudifyDeployment> In2 = + s -> ownerDeplList.stream().anyMatch(mc -> s.id.equals(mc.id)); + cfyDepList = cfyDepList.stream().filter(In2).collect(Collectors.toList()); + } else { + cfyDepList = new ArrayList<CloudifyDeployment>(); + } + } + } + if (!svcRefFilterStr.isEmpty()) { + List<String> svcFilterList = + new ArrayList<String>(Arrays.asList(svcRefFilterStr.split(","))); + if (!svcFilterList.isEmpty()) { + cfyDepList = (List) cfyDepList.stream().filter(s -> svcFilterList.stream() + .anyMatch(svcFilter -> ((CloudifyDeployment) s).id.toLowerCase().contains(svcFilter.toLowerCase()))) + .collect(Collectors.toList()); + } + } + if (!statusFilterStr.isEmpty()) { + List<String> statusFilterList = + new ArrayList<String>(Arrays.asList(statusFilterStr.split(","))); + Predicate<CloudifyDeployment> srvcFilter = + p -> p.lastExecution.status != null; + Stream<CloudifyDeployment> svcStream = cfyDepList.stream(); + if (cfyDepExList == null || cfyDepExList.isEmpty()) { + cfyDepExList = cloudifyClient.updateWorkflowStatus(cfyDepList); + } + if (cfyDepExList != null) { + updateWorkflowHelmStatus(cfyDepList, cfyDepExList, cfyDeplHelmList); + cfyDepList = svcStream.filter( srvcFilter.and( + s -> statusFilterList.stream() + .anyMatch(statusFilter ->((CloudifyDeployment) s).lastExecution.status.equalsIgnoreCase(statusFilter)))) + .collect(Collectors.toList()); + } + } + if (!helmFilterStr.isEmpty()) { + Predicate<CloudifyDeployment> helmFilter = + p -> p.helmStatus != null; + boolean isHelm = Boolean.parseBoolean(helmFilterStr); + if (cfyDeplHelmList == null || cfyDeplHelmList.isEmpty()) { + cfyDeplHelmList = cloudifyClient.updateHelmInfo(cfyDepList); + } + if (cfyDeplHelmList != null && isHelm ) { + updateWorkflowHelmStatus(cfyDepList, cfyDepExList, cfyDeplHelmList); + cfyDepList = (List) cfyDepList.stream().filter(helmFilter.and( + s -> ((CloudifyDeployment) s).isHelm == true)) + .collect(Collectors.toList()); + } + } + } + itemList.addAll(cfyDepList); + } catch (Exception cfyDepErr) { + logger.error(EELFLoggerDelegate.errorLogger, cfyDepErr.getMessage()); + } + if (sortBy != null) { + if (sortBy.equals("id")) { + ((List<CloudifyDeployment>)itemList).sort( + (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.id.compareTo(o2.id)); + } else if (sortBy.equals("blueprint_id")) { + ((List<CloudifyDeployment>)itemList).sort( + (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.blueprint_id.compareTo(o2.blueprint_id)); + } else if (sortBy.equals("created_at")) { + ((List<CloudifyDeployment>)itemList).sort( + (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.created_at.compareTo(o2.created_at)); + } else if (sortBy.equals("updated_at")) { + ((List<CloudifyDeployment>)itemList).sort( + (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.updated_at.compareTo(o2.updated_at)); + } + } + break; case TENANT: - itemList = cloudifyClient.getTenants().items; + lock.readLock().lock(); + cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH); + lock.readLock().unlock(); + if (cfyTenantList == null || cfyTenantList.isEmpty()) { + cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items; + } + + itemList = cfyTenantList; break; default: MDC.put(SystemProperties.STATUS_CODE, "ERROR"); @@ -162,10 +530,78 @@ public class CloudifyController extends DashboardRestrictedBaseController { "getItemListForPage failed: unimplemented case: " + option.name()); } // Shrink if needed - final int totalItems = itemList.size(); + if (itemList != null) { + totalItems = itemList.size(); + } final int pageCount = (int) Math.ceil((double) totalItems / pageSize); - if (totalItems > pageSize) + if (totalItems > pageSize) { itemList = getPageOfList(pageNum, pageSize, itemList); + } + + if (option.equals(CloudifyDataItem.DEPLOYMENT)) { + // update blueprint owner for each deployment record + if (deplPerOwner != null ) { + updateBpOwnerId(itemList, deplPerOwner); + } + if (cfyDepExList == null || cfyDepExList.isEmpty()) { + cfyDepExList = cloudifyClient.updateWorkflowStatus(itemList); + } + if (cfyDeplHelmList == null || cfyDeplHelmList.isEmpty()) { + cfyDeplHelmList = cloudifyClient.updateHelmInfo(itemList); + } + for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) { + try { + ConsulDeploymentHealth serviceHealth = + consulClient.getServiceHealthByDeploymentId(srvc.id); + if (serviceHealth != null) { + srvc.healthStatus = serviceHealth.getStatus(); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "consul getServiceHealth caught exception"); + } + // correlate the cached data for deployments and deployment extensions + if (cfyDepExList != null) { + List<CloudifyDeploymentExt> deplExtItems = + cfyDepExList.stream().filter((Predicate<? super CloudifyDeploymentExt>) s->s.id.equals(srvc.id)). + collect(Collectors.toList()); + if (deplExtItems != null && !deplExtItems.isEmpty()) { + srvc.lastExecution = deplExtItems.get(0).lastExecution; + } + } + if (cfyDeplHelmList != null) { + List<CloudifyDeploymentHelm> deplHelmItems = + cfyDeplHelmList.stream().filter((Predicate<? super CloudifyDeploymentHelm>) s->s.id.equals(srvc.id)). + collect(Collectors.toList()); + if (deplHelmItems != null && !deplHelmItems.isEmpty()) { + srvc.helmStatus = deplHelmItems.get(0).helmStatus; + srvc.isHelm = deplHelmItems.get(0).isHelm; + } + } + } + // check for authorization to perform delete deployed blueprints + if (!roleLevel.equals("ops")) { + if (roleLevel.equals("dev") || roleLevel.equals("app_dev")) { + boolean deployFlag = roleAuth.equals("WRITE") ? true : false; + for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) { + srvc.canDeploy = deployFlag; + } + } else { + for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) { + String deplRef = srvc.id.split("_")[0].toLowerCase(); + if (comp_deploy_tab.containsKey(deplRef)) { + boolean enableDeploy = comp_deploy_tab.get(deplRef); + srvc.canDeploy = enableDeploy; + } else { + srvc.canDeploy = false; + } + } + } + } else { + for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) { + srvc.canDeploy = true; + } + } + } RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); String outboundJson = objectMapper.writeValueAsString(model); return outboundJson; @@ -177,9 +613,12 @@ public class CloudifyController extends DashboardRestrictedBaseController { * * @param request Inbound request * @param option Item type to get + * @param inputKey Input key to search for if using filters + * @param inputValue Input value to search for if using filters * @return JSON with one page of objects; or an error. */ - protected String getItemListForPageWrapper(HttpServletRequest request, CloudifyDataItem option) { + protected String getItemListForPageWrapper(HttpServletRequest request, CloudifyDataItem option, + String sortBy, String searchBy) { String outboundJson = null; try { User appUser = UserUtils.getUserSession(request); @@ -187,7 +626,8 @@ public class CloudifyController extends DashboardRestrictedBaseController { throw new Exception("getItemListForPageWrapper: Failed to get application user"); int pageNum = getRequestPageNumber(request); int pageSize = getRequestPageSize(request); - outboundJson = getItemListForPage(appUser.getId(), option, pageNum, pageSize); + outboundJson = getItemListForPage(request, appUser.getId(), option, pageNum, pageSize, + sortBy, searchBy); } catch (Exception ex) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); @@ -210,8 +650,163 @@ public class CloudifyController extends DashboardRestrictedBaseController { } return outboundJson; } + /** + * Serves one page of deployments + * + * @param request HttpServletRequest + * @return List of CloudifyDeployment objects + */ + @RequestMapping(value = { DEPLOYMENTS_PATH }, method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getDeploymentsByPage(HttpServletRequest request) + { + preLogAudit(request); + String json = getItemListForPageWrapper(request, + CloudifyDataItem.DEPLOYMENT,request.getParameter("sortBy"), request.getParameter("searchBy")); + postLogAudit(request); + return json; + } + + /** + * Gets the specified blueprint content for viewing. + * + * @param id + * Blueprint ID + * @param request + * HttpServletRequest + * @return Blueprint as YAML; or error. + * @throws Exception + * on serialization error + * + */ + @RequestMapping(value = { + BLUEPRINTS_PATH + "/{id:.+}" + "/archive" }, method = RequestMethod.GET, produces = "application/yaml") + @ResponseBody + public byte[] viewBlueprintContentById(@PathVariable("id") String id, @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request) throws Exception { + preLogAudit(request); + byte[] result = null; + try { + result = cloudifyClient.viewBlueprint(tenant, id); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Viewing blueprint " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "viewBlueprintContentById caught exception"); + //result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Viewing blueprint " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "viewBlueprintContentById caught exception"); + //result = new RestResponseError("getBlueprintContentById failed", t); + } finally { + postLogAudit(request); + } + return result; + //objectMapper.writeValueAsString(result); + } + + /** + * Serves the complete list of deployment IDs + * + * @param request HttpServletRequest + * + * @return list of cloudify deployment IDs + */ + @RequestMapping( + value = {SERVICE_ID}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getAllServiceNames(HttpServletRequest request) { + preLogAudit(request); + String json = null; + json = getItemListForPageWrapper(request, CloudifyDataItem.SERVICE_ID, + request.getParameter("sortBy"), request.getParameter("searchBy")); + postLogAudit(request); + return json; + } + + /** + * Serves the count of deployment IDs + * + * @param request HttpServletRequest + * + * @return list of cloudify deployment IDs + */ + @RequestMapping( + value = {SERVICE_ID_COUNT}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getDepCount(HttpServletRequest request) { + preLogAudit(request); + String json = null; + json = getItemListForPageWrapper(request, CloudifyDataItem.SERVICE_ID_COUNT, + request.getParameter("sortBy"), request.getParameter("searchBy")); + postLogAudit(request); + return json; + } + + /** + * Serves the count of plugins + * + * @param request HttpServletRequest + * + * @return count of cloudify plugins + * @throws JsonProcessingException + */ + @RequestMapping( + value = {PLUGIN_COUNT}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getPluginCount(HttpServletRequest request) + throws JsonProcessingException { + preLogAudit(request); + ECTransportModel result = null; + try { + int totalItems = + (int) cloudifyClient.getPlugins().metadata.pagination.total; + RestResponsePage<List> model = + new RestResponsePage<>(totalItems, 1, null); + String outboundJson = objectMapper.writeValueAsString(model); + return outboundJson; + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting plugins failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + return objectMapper.writeValueAsString(result); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting plugins failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception"); + result = new RestResponseError("getSecret failed", t); + return objectMapper.writeValueAsString(result); + } finally { + postLogAudit(request); + } + } + + /** * gets the tenants list * * @param request HttpServletRequest @@ -221,11 +816,12 @@ public class CloudifyController extends DashboardRestrictedBaseController { @ResponseBody public String getTenants(HttpServletRequest request) { preLogAudit(request); - String json = getItemListForPageWrapper(request, CloudifyDataItem.TENANT); + String json = getItemListForPageWrapper(request, CloudifyDataItem.TENANT, + request.getParameter("sortBy"), request.getParameter("searchBy")); postLogAudit(request); return json; } - + /** * Gets the specified blueprint metadata. * @@ -235,7 +831,7 @@ public class CloudifyController extends DashboardRestrictedBaseController { * @throws Exception on serialization error * */ - @RequestMapping(value = { BLUEPRINTS_PATH + "/{id}" }, method = RequestMethod.GET, produces = "application/json") + @RequestMapping(value = { BLUEPRINTS_PATH + "/{id:.+}" }, method = RequestMethod.GET, produces = "application/json") @ResponseBody public String getBlueprintById(@PathVariable("id") String id, @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request) @@ -269,161 +865,208 @@ public class CloudifyController extends DashboardRestrictedBaseController { } /** - * Gets the specified deployment. + * Deletes the specified blueprint. * - * @param id Deployment ID - * @param request HttpServletRequest - * @return Deployment for the specified ID; error on failure. + * @param id Blueprint ID + * @param request HttpServletRequest + * @param response HttpServletResponse + * @return No content on success; error on failure. * @throws Exception On serialization failure - * */ - @RequestMapping(value = { DEPLOYMENTS_PATH + "/{id}" }, method = RequestMethod.GET, produces = "application/json") - @ResponseBody - public String getDeploymentById(@PathVariable("id") String id, - @RequestParam(value = "tenant", required = false) String tenant, HttpServletRequest request) - throws Exception { + @RequestMapping(value = { BLUEPRINTS_PATH + "/{id}" }, method = RequestMethod.DELETE, produces = "application/json") + @ResponseBody + public String deleteBlueprint(@PathVariable("id") String id, + @RequestParam(value = "tenant", required = false) String tenant, + HttpServletRequest request, HttpServletResponse response) throws Exception { preLogAudit(request); - ECTransportModel result = null; + String json = "{\"202\": \"OK\"}"; try { - if (tenant != null && tenant.length() > 0) { - result = cloudifyClient.getDeployment(id, tenant); - } else { - result = cloudifyClient.getDeployment(id); - } + cloudifyClient.deleteBlueprint(id, tenant); + response.setStatus(202); } catch (HttpStatusCodeException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployment " + id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Exception t) { + MDC.put("ErrorDescription", "Deleting blueprint " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); + json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); + } catch (Throwable t) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployment " + id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception"); - result = new RestResponseError("getDeploymentById failed", t); + MDC.put("ErrorDescription", "Deleting blueprint " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); + json = objectMapper + .writeValueAsString(new RestResponseError("deleteBlueprint failed on ID " + id, t)); } finally { postLogAudit(request); } - return objectMapper.writeValueAsString(result); + return json; } + + /** + * + * Deployment IDs for the given list of blueprint IDs + * + */ + @RequestMapping( + value = {"deployment_blueprint_map"}, + method = RequestMethod.POST, + produces = "application/json") + @ResponseBody + public String getDeploymentsForType(HttpServletRequest request, @RequestBody String[] typeList) + throws Exception { + List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>(); + for (String typeId : typeList) { + List<CloudifyDeployedTenant> deplForBpAggr = new ArrayList<CloudifyDeployedTenant>(); + List<CloudifyDeployedTenant> deplForBp = + cloudifyClient.getDeploymentForBlueprint("TID-"+typeId); + deplForBpAggr.addAll(deplForBp); + + ServiceQueryParams qryParams = + new ServiceQueryParams.Builder().typeId(typeId).build(); + ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); + Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet()); + if (dep_ids.size() > 0) { + // lookup these dep_ids in cloudify for tenant mapping + for (String str: dep_ids) { + List<CloudifyDeployedTenant> deplForBpInv = + cloudifyClient.getDeploymentForBlueprint(str); + deplForBpAggr.addAll(deplForBpInv); + } + } + ServiceRefCfyList cfyDeplRefList = new ServiceRefCfyList(deplForBpAggr, deplForBpAggr.size()); + ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, cfyDeplRefList); + result.add(srvcMap); + } + String resultStr = objectMapper.writeValueAsString(result); + return resultStr; + } + + @SuppressWarnings("unchecked") + @Scheduled(fixedDelay=3600000, initialDelay=180000) + public void cacheOwnerDeployMap() { + logger.debug(EELFLoggerDelegate.debugLogger, "cacheOwnerDeployMap begin"); + Map<String, List<CloudifyDeployedTenant>> deplPerOwner = + new HashMap<String, List<CloudifyDeployedTenant>>(); + new HashMap<String, List<ServiceTypeSummary>>(); + List<ServiceTypeSummary> bpNoDeplItems = + new ArrayList<ServiceTypeSummary>(); + List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>(); + List<CloudifyDeployedTenant> deplForBpAggr = + new ArrayList<CloudifyDeployedTenant>(); + String typeId = ""; + String owner = ""; + + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + List<ServiceTypeSummary> bpItems = + (List<ServiceTypeSummary>) getCacheManager().getObject(SERVICE_TYPES); + lock.readLock().unlock(); + if (bpItems != null) { + for (ServiceTypeSummary item : bpItems) { + try { + typeId = item.getTypeId().get(); + owner = item.getOwner(); + List<CloudifyDeployedTenant> deplForBp = + cloudifyClient.getDeploymentForBlueprint("TID-"+typeId); + deplForBpAggr.clear(); + deplForBpAggr.addAll(deplForBp); + ServiceQueryParams qryParams = + new ServiceQueryParams.Builder().typeId(typeId).build(); + ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); + Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet()); + if (dep_ids.size() > 0) { + for (String str: dep_ids) { + List<CloudifyDeployedTenant> deplForBpInv = + cloudifyClient.getDeploymentForBlueprint(str); + deplForBpAggr.addAll(deplForBpInv); + } + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "cacheOwnerDeployMap: " + e.getMessage()); + } finally { + if (deplForBpAggr.isEmpty()) { + bpNoDeplItems.add(item); + } + List<CloudifyDeployedTenant> iterBpIdDepl = + new ArrayList<CloudifyDeployedTenant>(); + iterBpIdDepl.addAll(deplForBpAggr); + ServiceRefCfyList cfyDeplRefList = new ServiceRefCfyList(iterBpIdDepl, iterBpIdDepl.size()); + ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, cfyDeplRefList); + result.add(srvcMap); + + List<CloudifyDeployedTenant> iterDeplBpAggr = + new ArrayList<CloudifyDeployedTenant>(); + iterDeplBpAggr.addAll(deplForBpAggr); + if (deplPerOwner.containsKey(owner)) { + List<CloudifyDeployedTenant> currOwnerDepl = + deplPerOwner.get(owner); + iterDeplBpAggr.addAll(0, currOwnerDepl); + deplPerOwner.put(owner, iterDeplBpAggr); + } else { + deplPerOwner.putIfAbsent(owner, iterDeplBpAggr); + } + } + } + } + lock.writeLock().lock(); + getCacheManager().putObject("bp_deploy_map", result); + getCacheManager().putObject("owner_deploy_map", deplPerOwner); + lock.writeLock().unlock(); + } + /** - * Query status and tenant info for deployments + * Gets the specified deployment. + * + * @param id Deployment ID + * @param request HttpServletRequest + * @return Deployment for the specified ID; error on failure. + * @throws Exception On serialization failure * */ - @SuppressWarnings("unchecked") - @RequestMapping(value = { DEP_TENANT_STATUS }, method = RequestMethod.POST, produces = "application/json") + @RequestMapping(value = { DEPLOYMENTS_PATH + "/{id:.+}" }, method = RequestMethod.GET, produces = "application/json") @ResponseBody - public String getTenantStatusForService(HttpServletRequest request, @RequestBody String[] serviceList) + public String getDeploymentById(@PathVariable("id") String id, + @RequestParam(value = "tenant", required = false) String tenant, HttpServletRequest request) throws Exception { preLogAudit(request); - /* - * 1) Get all the tenant names 2) Get the deployment IDs per tenant for all the - * tenants, aggregate the deployments list 3) Get the input deployments list - * (screen input), filter the deployments list from step#2 4) For each item in - * the list from step#3, get the execution status info and generate the final - * response - */ - String outboundJson = ""; - CloudifyDeployedTenantList cfyTenantDeployMapList = null; - new HashMap<String, Object>(); - List<CloudifyDeployedTenant> tenantList = new ArrayList<CloudifyDeployedTenant>(); - List<CloudifyExecution> cfyExecList = new ArrayList<CloudifyExecution>(); + ECTransportModel result = null; try { - List<CloudifyTenant> cldfyTen = cloudifyClient.getTenants().items; - for (CloudifyTenant ct : (List<CloudifyTenant>) cldfyTen) { - cfyTenantDeployMapList = cloudifyClient.getTenantInfoFromDeploy(ct.name); - tenantList.addAll(((CloudifyDeployedTenantList) cfyTenantDeployMapList).items); - } - List<CloudifyDeployedTenant> currSrvcTenants = new ArrayList<CloudifyDeployedTenant>(); - - for (String serviceId : serviceList) { - for (CloudifyDeployedTenant deplTen : tenantList) { - if (serviceId.equals(deplTen.id)) { - currSrvcTenants.add(deplTen); - break; - } - } - } - // Get concise execution status for each of the tenant deployment items - boolean isHelmType = false; - boolean helmStatus = false; - for (CloudifyDeployedTenant deplItem : currSrvcTenants) { - CloudifyExecutionList execResults = - cloudifyClient.getExecutionsSummary(deplItem.id, deplItem.tenant_name); - isHelmType = false; - helmStatus = false; - CloudifyBlueprintList bpList = - cloudifyClient.getBlueprint(deplItem.id, deplItem.tenant_name); - Map<String, Object> bpPlan = bpList.items.get(0).plan; - Map<String, String> workflows = (Map<String, String>) bpPlan.get("workflows"); - Map<String, String> pluginInfo = - ((List<Map<String, String>>) bpPlan.get("deployment_plugins_to_install")) - .get(0); - if (pluginInfo.get("name").equals("helm-plugin")) { - isHelmType = true; - } - if (workflows.containsKey("status")) { - helmStatus = true; - } - for (CloudifyExecution cfyExec : execResults.items) { - if (cfyExec.workflow_id.equalsIgnoreCase("install")) { - cfyExec.is_helm = isHelmType; - cfyExec.helm_status = helmStatus; - cfyExecList.add(cfyExec); - } - } + if (tenant != null && tenant.length() > 0) { + result = cloudifyClient.getDeployment(id, tenant); + } else { + result = cloudifyClient.getDeployment(id); } - outboundJson = objectMapper.writeValueAsString(cfyExecList); } catch (HttpStatusCodeException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployments failed!"); - logger.error(EELFLoggerDelegate.errorLogger, - "getTenantStatusForService caught exception"); - RestResponseError result = null; - result = new RestResponseError( - "getTenantStatusForService failed" + e.getResponseBodyAsString()); - try { - outboundJson = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } - } catch (Throwable t) { + MDC.put("ErrorDescription", "Getting deployment " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployments failed!"); - logger.error(EELFLoggerDelegate.errorLogger, - "getTenantStatusForService caught exception"); - RestResponseError result = null; - result = new RestResponseError("getTenantStatusForService failed"); - try { - outboundJson = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } + MDC.put("ErrorDescription", "Getting deployment " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception"); + result = new RestResponseError("getDeploymentById failed", t); } finally { postLogAudit(request); } - - return outboundJson; + return objectMapper.writeValueAsString(result); } - + /** * Gets and serves one page of executions: * <OL> @@ -448,7 +1091,7 @@ public class CloudifyController extends DashboardRestrictedBaseController { @RequestMapping(value = { EXECUTIONS_PATH }, method = RequestMethod.GET, produces = "application/json") @ResponseBody public String getExecutionsByPage(HttpServletRequest request, - @RequestParam(value = "deployment_id", required = false) String deployment_id, + @RequestParam(value = "deployment_id", required = true) String deployment_id, @RequestParam(value = "status", required = false) String status, @RequestParam(value = "tenant", required = true) String tenant) throws Exception { preLogAudit(request); @@ -460,7 +1103,7 @@ public class CloudifyController extends DashboardRestrictedBaseController { List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>(); List<String> depIds = new ArrayList<>(); if (deployment_id == null) { - CloudifyDeploymentList depList = cloudifyClient.getDeployments(); + CloudifyDeploymentList depList = cloudifyClient.getDeployments(tenant, 100, 0); for (CloudifyDeployment cd : depList.items) depIds.add(cd.id); } else { @@ -505,50 +1148,175 @@ public class CloudifyController extends DashboardRestrictedBaseController { return objectMapper.writeValueAsString(result); } - /** - * Gets the specified execution for one deployment. - * - * It's not clear why the deployment ID is needed. - * - * @param execution_id Execution ID (path variable) - * @param deployment_id Deployment ID (query parameter) - * @param request HttpServletRequest - * @return CloudifyExecutionList - * @throws Exception on serialization failure - */ - @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.GET, produces = "application/json") + @SuppressWarnings("unchecked") + @RequestMapping(value = { EXECUTIONS_PATH + "/tenant" }, method = RequestMethod.GET, produces = "application/json") @ResponseBody - public String getExecutionByIdAndDeploymentId(@PathVariable("id") String execution_id, - @RequestParam("deployment_id") String deployment_id, - @RequestParam(value = "tenant", required = false) String tenant, HttpServletRequest request) - throws Exception { + public String getExecutionsPerTenant(HttpServletRequest request, + @RequestParam(value = "tenant", required = true) String tenant, + @RequestParam(value = "status", required = false) String status) throws Exception { preLogAudit(request); ECTransportModel result = null; + ReadWriteLock lock = new ReentrantReadWriteLock(); + List<CloudifyTenant> cfyTenantList = null; + List<CloudifyTenant> myTenantsList = null; try { + List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>(); if (tenant == null) { - throw new Exception("required tenant input missing"); + // process all tenants that are relevant + lock.readLock().lock(); + cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH); + lock.readLock().unlock(); + if (cfyTenantList == null || cfyTenantList.isEmpty()) { + cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items; + } + myTenantsList = cfyTenantList; + + for (CloudifyTenant tenItem : myTenantsList) { + CloudifyExecutionList exeList = + cloudifyClient.getExecutionsSummaryPerTenant(tenItem.name); + // Filter down to specified status as needed + if (status != null && !status.isEmpty()) { + Iterator<CloudifyExecution> exeIter = exeList.items.iterator(); + while (exeIter.hasNext()) { + CloudifyExecution ce = exeIter.next(); + if (!status.equals(ce.status)) + exeIter.remove(); + } + } + itemList.addAll(exeList.items); + } + } else { + CloudifyExecutionList exeList = cloudifyClient.getExecutionsSummaryPerTenant(tenant); + itemList.addAll(exeList.items); + + // Filter down to specified status as needed + if (status != null && !status.isEmpty()) { + Iterator<CloudifyExecution> exeIter = itemList.iterator(); + while (exeIter.hasNext()) { + CloudifyExecution ce = exeIter.next(); + if (!status.equals(ce.status)) + exeIter.remove(); + } + } } - result = cloudifyClient.getExecutions(deployment_id, tenant); - } catch (HttpStatusCodeException e) { + //Collections.sort(itemList, executionComparator); + + // Paginate + final int pageNum = getRequestPageNumber(request); + final int pageSize = getRequestPageSize(request); + final int totalItems = itemList.size(); + final int pageCount = (int) Math.ceil((double) totalItems / pageSize); + // Shrink if needed + if (totalItems > pageSize) + itemList = getPageOfList(pageNum, pageSize, itemList); + result = new RestResponsePage<>(totalItems, pageCount, itemList); + } catch (Exception t) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", - "Getting executions " + execution_id + " for deployment " + deployment_id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); + MDC.put("ErrorDescription", "Getting executions failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsByPage caught exception"); + result = new RestResponseError("getExecutionsByPage failed", t); + } finally { + postLogAudit(request); + } + return objectMapper.writeValueAsString(result); + } + + @SuppressWarnings("unchecked") + @RequestMapping(value = { EXECUTIONS_PATH + "/{id:.+}"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String queryExecution(@PathVariable("id") String id, @RequestParam(value = "tenant", required = true) + String tenant, HttpServletRequest request) throws Exception { + preLogAudit(request); + ECTransportModel result = null; + try { + List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>(); + CloudifyExecution cfyExecObj = cloudifyClient.getExecutionIdSummary(id, tenant); + itemList.add(cfyExecObj); + final int pageNum = getRequestPageNumber(request); + final int pageSize = getRequestPageSize(request); + final int totalItems = itemList.size(); + final int pageCount = (int) Math.ceil((double) totalItems / pageSize); + // Shrink if needed + if (totalItems > pageSize) + itemList = getPageOfList(pageNum, pageSize, itemList); + result = new RestResponsePage<>(totalItems, pageCount, itemList); } catch (Exception t) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", - "Getting executions " + execution_id + " for deployment " + deployment_id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); + MDC.put("ErrorDescription", "Getting executions failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsByPage caught exception"); + result = new RestResponseError("getExecutionsByPage failed", t); + } finally { + postLogAudit(request); + } + return objectMapper.writeValueAsString(result); + } + + @SuppressWarnings("unchecked") + @RequestMapping(value = { EXECUTIONS_PATH + "/active"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getActiveExecutions(HttpServletRequest request) throws Exception { + preLogAudit(request); + ECTransportModel result = null; + ReadWriteLock lock = new ReentrantReadWriteLock(); + List<CloudifyTenant> cfyTenantList = null; + List<CloudifyTenant> myTenantsList = null; + String status = "started"; + try { + List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>(); + // process all tenants that are relevant + lock.readLock().lock(); + cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH); + lock.readLock().unlock(); + if (cfyTenantList == null || cfyTenantList.isEmpty()) { + cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items; + } + myTenantsList = cfyTenantList; + + for (CloudifyTenant tenItem : myTenantsList) { + CloudifyExecutionList exeList = null; + try { + exeList = + cloudifyClient.getExecutionsSummaryPerTenant(tenItem.name); + } catch (Exception e) { + continue; + } + // Filter down to specified status as needed + Iterator<CloudifyExecution> exeIter = exeList.items.iterator(); + while (exeIter.hasNext()) { + CloudifyExecution ce = exeIter.next(); + if (!status.equals(ce.status)) + exeIter.remove(); + } + itemList.addAll(exeList.items); + } + //Collections.sort(itemList, executionComparator); + + // Paginate + final int pageNum = getRequestPageNumber(request); + final int pageSize = getRequestPageSize(request); + final int totalItems = itemList.size(); + final int pageCount = (int) Math.ceil((double) totalItems / pageSize); + // Shrink if needed + if (totalItems > pageSize) + itemList = getPageOfList(pageNum, pageSize, itemList); + result = new RestResponsePage<>(totalItems, pageCount, itemList); + } catch (Exception t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting executions failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsByPage caught exception"); + result = new RestResponseError("getExecutionsByPage failed", t); } finally { postLogAudit(request); } @@ -641,7 +1409,7 @@ public class CloudifyController extends DashboardRestrictedBaseController { preLogAudit(request); ECTransportModel result = null; try { - if (!execution.workflow_id.equals("status") + if (!(execution.workflow_id.equals("status") || execution.workflow_id.equals("execute_operation")) && !execution.getParameters().containsKey("node_instance_id")) { // get the node instance ID for the deployment String nodeInstId = ""; @@ -654,6 +1422,14 @@ public class CloudifyController extends DashboardRestrictedBaseController { inParms.put("node_instance_id", nodeInstId); execution.setParameters(inParms); } + if (execution.workflow_id.equals("upgrade")) { + String repo_user = + cloudifyClient.getSecret("controller_helm_user", execution.getTenant()).value; + String repo_user_password = + cloudifyClient.getSecret("controller_helm_password", execution.getTenant()).value; + execution.getParameters().put("repo_user", repo_user); + execution.getParameters().put("repo_user_password", repo_user_password); + } result = cloudifyClient.startExecution(execution); } catch (HttpStatusCodeException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); @@ -680,29 +1456,35 @@ public class CloudifyController extends DashboardRestrictedBaseController { } /** - * Processes request to create an execution based on a deployment. + * Cancels an execution. * - * @param request HttpServletRequest - * @param execution Execution model - * @return Information about the execution + * @param id Execution ID + * @param deploymentId Deployment ID (not clear why this is needed) + * @param action Action to perform (not clear why this is needed) + * @param request HttpServletRequest + * @param response HttpServletRequest + * @return Passes thru HTTP status code from remote endpoint; no body on success * @throws Exception on serialization failure */ - @RequestMapping(value = { UPDATE_DEPLOYMENT_PATH }, method = RequestMethod.POST, produces = "application/json") + @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.POST, produces = "application/json") @ResponseBody - public String updateDeployment(HttpServletRequest request, @RequestBody CloudifyDeploymentUpdateRequest execution) + public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id, + @RequestBody Map<String, String> parameters, HttpServletRequest request, HttpServletResponse response) throws Exception { preLogAudit(request); ECTransportModel result = null; + List<String> tenant = null; try { - result = cloudifyClient.updateDeployment(execution); + tenant = headers.get("tenant"); + result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0)); } catch (HttpStatusCodeException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Updating deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception"); + MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); result = new RestResponseError(e.getResponseBodyAsString()); } catch (Exception t) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); @@ -710,45 +1492,48 @@ public class CloudifyController extends DashboardRestrictedBaseController { MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Updating Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception"); - result = new RestResponseError("updateDeployment failed", t); + MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); + result = new RestResponseError("cancelExecution failed on ID " + id, t); } finally { postLogAudit(request); } - return objectMapper.writeValueAsString(result); + if (result == null) + return null; + else + return objectMapper.writeValueAsString(result); } /** - * Cancels an execution. + * Gets the specified node-instances details + * + * @query param deployment deployment ID + * @query param tenant tenant name + * @param request HttpServletRequest + * @return node instances as a string; or error. + * @throws Exception on serialization error * - * @param id Execution ID - * @param deploymentId Deployment ID (not clear why this is needed) - * @param action Action to perform (not clear why this is needed) - * @param request HttpServletRequest - * @param response HttpServletRequest - * @return Passes thru HTTP status code from remote endpoint; no body on success - * @throws Exception on serialization failure */ - @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.POST, produces = "application/json") + @RequestMapping(value = {"node-instances-data"}, + method = RequestMethod.GET, produces = "application/json") @ResponseBody - public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id, - @RequestBody Map<String, String> parameters, HttpServletRequest request, HttpServletResponse response) - throws Exception { + public String getNodeInstanceDetails( + @RequestParam(value = "deployment", required = true) String deployment, + @RequestParam(value = "tenant", required = true) String tenant, + HttpServletRequest request) throws Exception { preLogAudit(request); ECTransportModel result = null; - List<String> tenant = null; try { - tenant = headers.get("tenant"); - result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0)); + result = cloudifyClient.getNodeInstanceDetails(deployment, tenant); } catch (HttpStatusCodeException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Cloudify Manager"); MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); + MDC.put("ErrorDescription", "Getting node-instance with deploymentId " + deployment + + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstance caught exception"); result = new RestResponseError(e.getResponseBodyAsString()); } catch (Exception t) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); @@ -756,16 +1541,62 @@ public class CloudifyController extends DashboardRestrictedBaseController { MDC.put("TargetServiceName", "Cloudify Manager"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); - result = new RestResponseError("cancelExecution failed on ID " + id, t); + MDC.put("ErrorDescription", "Getting node-instance with deploymentId " + deployment + + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstance caught exception"); + result = new RestResponseError("getNodeInstance failed", t); } finally { postLogAudit(request); } - if (result == null) - return null; - else - return objectMapper.writeValueAsString(result); + return objectMapper.writeValueAsString(result); + } + + /** + * Gets the specified node-instances for viewing. + * + * @param id deployment ID + * @param request HttpServletRequest + * @return node instances as a string; or error. + * @throws Exception on serialization error + * + */ + @RequestMapping(value = { NODE_INSTANCES_PATH + + "/{deploymentId:.+}" }, method = RequestMethod.GET, produces = "application/yaml") + @ResponseBody + public String getNodeInstances(@PathVariable("deploymentId") String deploymentId, + @RequestParam(value = "tenant", required = true) String tenant, + HttpServletRequest request) throws Exception { + preLogAudit(request); + ECTransportModel result = null; + try { + if (tenant == null) { + throw new Exception("required tenant input missing"); + } + result = cloudifyClient.getNodeInstances(deploymentId, tenant); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting node-instance-id with deploymentId " + deploymentId + + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstanceId caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting node-instance-id with deploymentId " + deploymentId + + " failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstanceId caught exception"); + result = new RestResponseError("getNodeInstanceId failed", t); + } finally { + postLogAudit(request); + } + return objectMapper.writeValueAsString(result); } /** @@ -779,7 +1610,7 @@ public class CloudifyController extends DashboardRestrictedBaseController { * */ @RequestMapping(value = { NODE_INSTANCES_PATH - + "/{deploymentId}/{nodeId}" }, method = RequestMethod.GET, produces = "application/yaml") + + "/{deploymentId:.+}/{nodeId}" }, method = RequestMethod.GET, produces = "application/yaml") @ResponseBody public String getNodeInstanceId(@PathVariable("deploymentId") String deploymentId, @RequestParam(value = "tenant", required = true) String tenant, @PathVariable("nodeId") String nodeId, @@ -818,7 +1649,7 @@ public class CloudifyController extends DashboardRestrictedBaseController { } @RequestMapping(value = { - DEPLOYMENTS_PATH + "/{deploymentId}/revisions" }, method = RequestMethod.GET, produces = "application/json") + DEPLOYMENTS_PATH + "/{deploymentId:.+}/revisions" }, method = RequestMethod.GET, produces = "application/json") @ResponseBody public String getDeploymentRevisions(@PathVariable("deploymentId") String deploymentId, @RequestParam(value = "tenant") String tenant, HttpServletRequest request) throws Exception { @@ -853,6 +1684,51 @@ public class CloudifyController extends DashboardRestrictedBaseController { return objectMapper.writeValueAsString(result); } + /** + * Gets the cloudify plugins list + * + * + * @param request + * HttpServletRequest + * @return list of CloudifyPlugin + * @throws Exception + * on serialization failure + */ + @SuppressWarnings("unchecked") + @RequestMapping(value = { PLUGINS_PATH }, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getPlugins( + HttpServletRequest request) throws Exception { + preLogAudit(request); + ECTransportModel result = null; + try { + List<CloudifyPlugin> resultsArr = cloudifyClient.getPlugins().items; + return objectMapper.writeValueAsString(resultsArr); + } catch (HttpStatusCodeException e) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting plugins failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception"); + result = new RestResponseError(e.getResponseBodyAsString()); + return objectMapper.writeValueAsString(result); + } catch (Throwable t) { + MDC.put(SystemProperties.STATUS_CODE, "ERROR"); + MDC.put("TargetEntity", "Cloudify Manager"); + MDC.put("TargetServiceName", "Cloudify Manager"); + MDC.put("ErrorCode", "300"); + MDC.put("ErrorCategory", "ERROR"); + MDC.put("ErrorDescription", "Getting plugins failed!"); + logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception"); + result = new RestResponseError("getSecret failed", t); + return objectMapper.writeValueAsString(result); + } finally { + postLogAudit(request); + } + } + public void preLogAudit(HttpServletRequest request) { begin = new Date(); MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin)); diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CommonApiController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CommonApiController.java deleted file mode 100644 index bd53145..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CommonApiController.java +++ /dev/null @@ -1,1182 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ - -package org.onap.ccsdk.dashboard.controller; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.json.JSONObject; -import org.onap.ccsdk.dashboard.domain.EcdComponent; -import org.onap.ccsdk.dashboard.exceptions.BadRequestException; -import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException; -import org.onap.ccsdk.dashboard.exceptions.DownstreamException; -import org.onap.ccsdk.dashboard.exceptions.ServerErrorException; -import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException; -import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException; -import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException; -import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList; -import org.onap.ccsdk.dashboard.model.CloudifyExecution; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList; -import org.onap.ccsdk.dashboard.model.CloudifyTenant; -import org.onap.ccsdk.dashboard.model.ECTransportModel; -import org.onap.ccsdk.dashboard.model.RestResponseError; -import org.onap.ccsdk.dashboard.model.RestResponsePage; -import org.onap.ccsdk.dashboard.model.RestResponseSuccess; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResource; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResourceLinks; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks; -import org.onap.ccsdk.dashboard.model.inventory.Blueprint; -import org.onap.ccsdk.dashboard.model.inventory.BlueprintResponse; -import org.onap.ccsdk.dashboard.model.inventory.Service; -import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; -import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; -import org.onap.ccsdk.dashboard.model.inventory.ServiceType; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest; -import org.onap.ccsdk.dashboard.rest.CloudifyClient; -import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient; -import org.onap.ccsdk.dashboard.rest.InventoryClient; -import org.onap.ccsdk.dashboard.service.ControllerEndpointService; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.portalsdk.core.util.SystemProperties; -import org.slf4j.MDC; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.http.HttpHeaders; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.HttpStatusCodeException; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; - -@RestController -@RequestMapping("/nb-api") -public class CommonApiController extends DashboardRestrictedBaseController { - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CommonApiController.class); - - private static final String COMPONENTS_PATH = "components"; - private static final String DEPLOYMENTS_PATH = "deployments"; - private static final String SERVICE_TYPES_PATH = "blueprints"; - private static final String EXECUTIONS_PATH = "executions"; - private static final String DEP_TENANT_STATUS = "deployment-status"; - private static final String TENANTS_PATH = "tenants"; - - @Autowired - private ControllerEndpointService controllerEndpointService; - - @Autowired - InventoryClient inventoryClient; - - @Autowired - DeploymentHandlerClient deploymentHandlerClient; - - @Autowired - CloudifyClient cloudifyClient; - - /** - * Enum for selecting an item type. - */ - public enum InventoryDataItem { - SERVICES, SERVICE_TYPES, SERVICES_GROUPBY; - } - - private static Date begin, end; - - @RequestMapping(value = "/api-docs", method = RequestMethod.GET, produces = "application/json") - public Resource apiDocs() { - return new ClassPathResource("swagger.json"); - } - - @RequestMapping(value = { COMPONENTS_PATH }, method = RequestMethod.POST, produces = "application/json") - public String insertComponent(HttpServletRequest request, @RequestBody EcdComponent newComponent) throws Exception { - String outboundJson = null; - controllerEndpointService.insertComponent(newComponent); - RestResponseSuccess success = new RestResponseSuccess( - "Inserted new component with name " + newComponent.getCname()); - outboundJson = objectMapper.writeValueAsString(success); - return outboundJson; - } - - @RequestMapping(value = { COMPONENTS_PATH }, method = RequestMethod.GET, produces = "application/json") - public String getComponents(HttpServletRequest request) throws Exception { - List<EcdComponent> result = controllerEndpointService.getComponents(); - return objectMapper.writeValueAsString(result); - - } - - /** - * gets the tenants list - * - * @param request HttpServletRequest - * @return List of CloudifyDeployment objects - */ - @SuppressWarnings("rawtypes") - @RequestMapping(value = { TENANTS_PATH }, method = RequestMethod.GET, produces = "application/json") - @ResponseBody - public String getTenants(HttpServletRequest request) throws Exception { - preLogAudit(request); - List itemList = cloudifyClient.getTenants().items; - final int totalItems = itemList.size(); - final int pageSize = 20; - final int pageNum = 1; - final int pageCount = (int) Math.ceil((double) totalItems / pageSize); - if (totalItems > pageSize) - itemList = getPageOfList(pageNum, pageSize, itemList); - RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); - String outboundJson = objectMapper.writeValueAsString(model); - return outboundJson; - } - - /** - * Query status and tenant info for deployments - * - */ - @RequestMapping(value = { DEP_TENANT_STATUS }, method = RequestMethod.POST, produces = "application/json") - @ResponseBody - public String getTenantStatusForService(HttpServletRequest request, @RequestBody String[] serviceList) - throws Exception { - preLogAudit(request); - /* - * 1) Get all the tenant names 2) Get the deployment IDs per tenant for all the - * tenants, aggregate the deployments list 3) Get the input deployments list - * (screen input), filter the deployments list from step#2 4) For each item in - * the list from step#3, get the execution status info and generate the final - * response - */ - String outboundJson = ""; - ECTransportModel result = null; - List<CloudifyDeployedTenant> tenantList = new ArrayList<CloudifyDeployedTenant>(); - List<CloudifyExecution> cfyExecList = new ArrayList<CloudifyExecution>(); - try { - List<CloudifyTenant> cldfyTen = cloudifyClient.getTenants().items; - for (CloudifyTenant ct : (List<CloudifyTenant>) cldfyTen) { - result = cloudifyClient.getTenantInfoFromDeploy(ct.name); - tenantList.addAll(((CloudifyDeployedTenantList) result).items); - } - result = null; - List<CloudifyDeployedTenant> currSrvcTenants = new ArrayList<CloudifyDeployedTenant>(); - - for (String serviceId : serviceList) { - for (CloudifyDeployedTenant deplTen : tenantList) { - if (serviceId.equals(deplTen.id)) { - currSrvcTenants.add(deplTen); - break; - } - } - } - // Get concise execution status for each of the tenant deployment items - for (CloudifyDeployedTenant deplItem : currSrvcTenants) { - CloudifyExecutionList execResults = - cloudifyClient.getExecutionsSummary(deplItem.id, deplItem.tenant_name); - for (CloudifyExecution cfyExec : execResults.items) { - if (cfyExec.workflow_id.equalsIgnoreCase("install")) { - cfyExecList.add(cfyExec); - } - } - } - outboundJson = objectMapper.writeValueAsString(cfyExecList); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployments failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getTenantStatusForService caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - try { - outboundJson = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } - } catch (Exception t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployments failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getTenantStatusForService caught exception"); - result = new RestResponseError("getTenantStatusForService failed", t); - try { - outboundJson = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } - } finally { - postLogAudit(request); - } - - return outboundJson; - } - - @RequestMapping(value = { SERVICE_TYPES_PATH }, method = RequestMethod.POST, produces = "application/json") - public String createBlueprint(HttpServletRequest request, @RequestBody ServiceTypeUploadRequest serviceTypeUplReq) - throws Exception { - String json = null; - try { - Blueprint.parse(serviceTypeUplReq.getBlueprintTemplate()); - // InventoryClient inventoryClient = getInventoryClient(); - Collection<String> serviceIds = new ArrayList<String>(); - Collection<String> vnfTypes = new ArrayList<String>(); - Collection<String> serviceLocations = new ArrayList<String>(); - Optional<String> asdcServiceId = null; - Optional<String> asdcResourceId = null; - Optional<String> asdcServiceURL = null; - - ServiceTypeRequest invSrvcTypeReq = new ServiceTypeRequest(serviceTypeUplReq.owner, - serviceTypeUplReq.typeName, serviceTypeUplReq.typeVersion, serviceTypeUplReq.blueprintTemplate, - serviceTypeUplReq.application, serviceTypeUplReq.component, serviceIds, vnfTypes, serviceLocations, - asdcServiceId, asdcResourceId, asdcServiceURL); - ServiceType response = inventoryClient.addServiceType(invSrvcTypeReq); - // RestResponseSuccess success = new RestResponseSuccess("Uploaded new blueprint - // with name " + serviceTypeUplReq.typeName); - json = objectMapper.writeValueAsString(response); - } catch (BlueprintParseException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Updating service type failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "updateServiceTypeBlueprint caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError("Invalid blueprint format.", e)); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Updating service type failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "updateServiceTypeBlueprint caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getResponseBodyAsString())); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Updating service type failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "updateServiceTypeBlueprint caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError("updateServiceTypeBlueprint failed", t)); - } finally { - postLogAudit(request); - } - return json; - } - - @RequestMapping(value = { SERVICE_TYPES_PATH }, method = RequestMethod.GET, produces = "application/json") - public String getBlueprintsByPage(HttpServletRequest request) { - preLogAudit(request); - String json = null; - json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPES, request.getParameter("name"), - request.getParameter("_include")); - postLogAudit(request); - return json; - } - - @RequestMapping(value = { - SERVICE_TYPES_PATH + "/findByName" }, method = RequestMethod.GET, produces = "application/json") - public String queryBlueprintFilter(HttpServletRequest request) { - preLogAudit(request); - String json = null; - json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPES, request.getParameter("name"), - request.getParameter("_include")); - postLogAudit(request); - return json; - } - - @RequestMapping(value = { - DEPLOYMENTS_PATH + "/{deploymentId}" }, method = RequestMethod.GET, produces = "application/json") - public String getDeploymentsByPage(@PathVariable("deploymentId") String deploymentId, HttpServletRequest request) { - preLogAudit(request); - String json = null; - json = getItemListForPageWrapper(request, InventoryDataItem.SERVICES, deploymentId, - request.getParameter("_include")); - postLogAudit(request); - return json; - } - - @RequestMapping(value = { DEPLOYMENTS_PATH }, method = RequestMethod.GET, produces = "application/json") - public String getAllDeploymentsByPage(HttpServletRequest request) { - preLogAudit(request); - String json = null; - json = getItemListForPageWrapper(request, InventoryDataItem.SERVICES, request.getParameter("deploymentId"), - request.getParameter("_include")); - postLogAudit(request); - return json; - } - - /** - * Gets one page of the specified items. This method traps exceptions and - * constructs an appropriate JSON block to report errors. - * - * @param request Inbound request - * @param option Item type to get - * @return JSON with one page of objects; or an error. - */ - protected String getItemListForPageWrapper(HttpServletRequest request, InventoryDataItem option, String searchBy, - String filters) { - preLogAudit(request); - - String outboundJson = null; - try { - int pageNum = getRequestPageNumber(request); - int pageSize = getRequestPageSize(request); - outboundJson = getItemListForPage(option, pageNum, pageSize, searchBy, filters); - } catch (Exception ex) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "ECOMP Inventory"); - MDC.put("TargetServiceName", "ECOMP Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting page of items failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception"); - RestResponseError result = null; - if (ex instanceof HttpStatusCodeException) - result = new RestResponseError(((HttpStatusCodeException) ex).getResponseBodyAsString()); - else - result = new RestResponseError("Failed to get " + option.name(), ex); - try { - outboundJson = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } - } finally { - postLogAudit(request); - } - return outboundJson; - } - - /** - * Gets one page of objects and supporting information via the REST client. On - * success, returns a PaginatedRestResponse object as String. - * - * @param option Specifies which item list type to get - * @param pageNum Page number of results - * @param pageSize Number of items per browser page - * @return JSON block as String, see above. - * @throws Exception On any error; e.g., Network failure. - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - private String getItemListForPage(InventoryDataItem option, int pageNum, int pageSize, String searchBy, - String filters) throws Exception { - String outboundJson = ""; - List itemList = null; - - switch (option) { - case SERVICES: - itemList = inventoryClient.getServices().collect(Collectors.toList()); - if (searchBy != null) { - itemList = (List) itemList.stream() - .filter(s -> ((Service) s).contains(searchBy)).collect(Collectors.toList()); - } - // Get the tenant names for all the deployments from Cloudify/API handler - ECTransportModel result = null; - List<CloudifyDeployedTenant> tenantList = new ArrayList<CloudifyDeployedTenant>(); - try { - List<CloudifyTenant> cldfyTen = cloudifyClient.getTenants().items; - for (CloudifyTenant ct : (List<CloudifyTenant>) cldfyTen) { - result = cloudifyClient.getTenantInfoFromDeploy(ct.name); - tenantList.addAll(((CloudifyDeployedTenantList) result).items); - } - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployments failed!"); - logger.error(EELFLoggerDelegate.errorLogger, - "getTenantInfoFromDeploy caught exception"); - //result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting deployments failed!"); - logger.error(EELFLoggerDelegate.errorLogger, - "getDeploymentById caught exception"); - //result = new RestResponseError("getTenantInfoFromDeploy failed", t); - } finally { - - } - - for (Service depl : (List<Service>) itemList) { - for (CloudifyDeployedTenant deplTen : tenantList) { - if (depl.getDeploymentRef().equals(deplTen.id)) { - depl.setTenant(deplTen.tenant_name); - break; - } - } - } - break; - case SERVICE_TYPES: - ServiceTypeQueryParams serviceQueryParams = null; - serviceQueryParams = new ServiceTypeQueryParams.Builder().onlyLatest(false).build(); - - itemList = inventoryClient.getServiceTypes(serviceQueryParams).collect(Collectors.toList()); - List<BlueprintResponse> filterList = new ArrayList<BlueprintResponse>(); - - if (searchBy != null && searchBy.length() > 1) { - itemList = (List) itemList.stream().filter(s -> ((ServiceType) s).contains(searchBy)) - .collect(Collectors.toList()); - } - if (filters != null && filters.length() > 0) { - String filterArr[] = filters.split(","); - for (ServiceType bp : (List<ServiceType>) itemList) { - BlueprintResponse bpOut = new BlueprintResponse(); - for (String fltr : filterArr) { - switch (fltr) { - case "typeName": - bpOut.setTypeName(bp.getTypeName()); - break; - case "typeId": - if (bp.getTypeId().isPresent()) { - bpOut.setTypeId(bp.getTypeId().get()); - } - break; - case "typeVersion": - bpOut.setTypeVersion(bp.getTypeVersion()); - break; - default: - break; - } - } - filterList.add(bpOut); - } - if (filterList.size() > 0) { - itemList.clear(); - itemList.addAll(filterList); - } - } - break; - default: - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting page of items failed!"); - throw new Exception("getItemListForPage failed: unimplemented case: " + option.name()); - } - // Shrink if needed - final int totalItems = itemList.size(); - final int pageCount = (int) Math.ceil((double) totalItems / pageSize); - if (totalItems > pageSize) - itemList = getPageOfList(pageNum, pageSize, itemList); - - RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); - outboundJson = objectMapper.writeValueAsString(model); - - return outboundJson; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private String getBlueprintTypeId(String searchBy, Optional<Integer> version, String typeId) throws Exception { - - // InventoryClient inventoryClient = getInventoryClient(); - ServiceTypeQueryParams serviceQueryParams = null; - - if (version.isPresent()) { - serviceQueryParams = new ServiceTypeQueryParams.Builder().typeName(searchBy).onlyLatest(false).build(); - } else { - serviceQueryParams = new ServiceTypeQueryParams.Builder().typeName(searchBy).build(); - } - - List itemList = inventoryClient.getServiceTypes(serviceQueryParams).collect(Collectors.toList()); - - if (version.isPresent()) { - itemList = (List) itemList.stream().filter(s -> ((ServiceType) s).contains(version.get().toString())) - .collect(Collectors.toList()); - } - Optional<String> bpId = Optional.of(""); - if (typeId != null && typeId.equals("typeId")) { - ServiceType item = (ServiceType) ((List) itemList).get(0); - bpId = item.getTypeId(); - } - return bpId.get(); - } - - /** - * Query the installed helm package revisions from cloudify - * - * @param deploymentId - * @param tenant - * @param request - * @return - * @throws Exception - */ - @RequestMapping(value = { - DEPLOYMENTS_PATH + "/{deploymentId}/revisions" }, method = RequestMethod.GET, produces = "application/json") - public String getDeploymentRevisions(@PathVariable("deploymentId") String deploymentId, - @RequestParam(value = "tenant") String tenant, HttpServletRequest request) throws Exception { - preLogAudit(request); - ECTransportModel result = null; - try { - if (tenant == null) { - throw new Exception("tenant name is missing"); - } - result = cloudifyClient.getNodeInstanceVersion(deploymentId, tenant); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); - } finally { - postLogAudit(request); - } - return objectMapper.writeValueAsString(result); - } - - /** - * Query inputs used to create a deployment - * - * @param deploymentId - * @param tenant - * @param request - * @return - * @throws Exception - */ - @RequestMapping(value = { - DEPLOYMENTS_PATH + "/{deploymentId}/inputs" }, method = RequestMethod.GET, produces = "application/json") - public String getDeploymentInputs(@PathVariable("deploymentId") String deploymentId, - @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request) - throws Exception { - preLogAudit(request); - ECTransportModel result = null; - try { - if (tenant == null) { - throw new Exception("tenant name is missing"); - } - result = cloudifyClient.getDeploymentInputs(deploymentId, tenant); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); - } finally { - postLogAudit(request); - } - return objectMapper.writeValueAsString(result); - } - - /** - * Create an upgrade/rollback workflow execution for a deployment. - * - * @param request HttpServletRequest - * @param execution Execution model - * @return Information about the execution - * @throws Exception on serialization failure - */ - @RequestMapping(value = { - DEPLOYMENTS_PATH + "/{deploymentId}" }, method = RequestMethod.PUT, produces = "application/json") - public String modifyDeployment(@PathVariable("deploymentId") String deploymentId, HttpServletRequest request, - InputStream upgParams) throws Exception { - preLogAudit(request); - ECTransportModel result = null; - try { - String nodeInstId = ""; - Map<String, Object> parameters = objectMapper.readValue(upgParams, - new TypeReference<Map<String, Object>>() { - }); - String tenant = (String) parameters.get("tenant"); - String workflow = (String) parameters.get("workflow"); - parameters.remove("tenant"); - parameters.remove("workflow"); - // get the node instance ID for the deployment - CloudifyNodeInstanceIdList nodeInstList = - cloudifyClient.getNodeInstanceId(deploymentId, tenant); - if (nodeInstList != null) { - nodeInstId = nodeInstList.items.get(0).id; - } - parameters.put("node_instance_id", nodeInstId); - CloudifyExecutionRequest execution = new CloudifyExecutionRequest(deploymentId, - workflow, false, false, tenant, parameters); - result = cloudifyClient.startExecution(execution); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Updating deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Updating Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception"); - result = new RestResponseError("updateDeployment failed", t); - } finally { - postLogAudit(request); - } - return objectMapper.writeValueAsString(result); - } - - @RequestMapping(value = { - SERVICE_TYPES_PATH + "/{typeid}" + "/services" }, method = RequestMethod.GET, produces = "application/json") - public String getServicesForType(HttpServletRequest request, @PathVariable("typeid") String typeId) - throws Exception { - preLogAudit(request); - List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>(); - // InventoryClient inventoryClient = getInventoryClient(); - ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build(); - ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); - ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, srvcRefs); - result.add(srvcMap); - return objectMapper.writeValueAsString(result); - } - - @RequestMapping(value = { DEPLOYMENTS_PATH }, method = RequestMethod.POST, produces = "application/json") - public String createDeployment(HttpServletRequest request, @RequestBody DeploymentInput deploymentRequestObject) - throws Exception { - preLogAudit(request); - String json = null; - StringBuffer status = new StringBuffer(); - // Optional<String> bpId = Optional.empty(); - Optional<Integer> bpVersion = null; - String srvcTypeId = null; - String bpName = deploymentRequestObject.getBlueprintName(); - String cName = deploymentRequestObject.getComponent(); - String tag = deploymentRequestObject.getTag(); - String depName = cName + "_" + tag; - - if (deploymentRequestObject.getBlueprintVersion().isPresent()) { - bpVersion = deploymentRequestObject.getBlueprintVersion(); - } - if (deploymentRequestObject.getBlueprintId().isPresent()) { - srvcTypeId = deploymentRequestObject.getBlueprintId().get(); - // srvcTypeId = bpId.get(); - } - if (srvcTypeId == null) { - // get the serviceTypeId from inventory using the blueprint name - try { - srvcTypeId = getBlueprintTypeId(bpName, bpVersion, "typeId"); - } catch (Exception ex) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "ECOMP Inventory"); - MDC.put("TargetServiceName", "ECOMP Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting blueprint ID failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception"); - RestResponseError result = null; - if (ex instanceof HttpStatusCodeException) - result = new RestResponseError(((HttpStatusCodeException) ex).getResponseBodyAsString()); - else - result = new RestResponseError("Failed to get blueprint", ex); - try { - json = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - json = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } - return json; - } finally { - postLogAudit(request); - } - } - try { - DeploymentResponse resp = - deploymentHandlerClient.putDeployment(depName, deploymentRequestObject.getTenant(), - new DeploymentRequest(srvcTypeId, deploymentRequestObject.getInputs())); - DeploymentResponseLinks deplLinks = resp.getLinks(); - String deplStatus = deplLinks.getStatus(); - if (!deplStatus.contains("cfy_tenant")) { - deplStatus = deplStatus + "?cfy_tenant_name=" + deploymentRequestObject.getTenant(); - } - String self = request.getRequestURL().append("/").append(depName).toString(); - status.append(self).append("/executions?tenant=").append(deploymentRequestObject.getTenant()); - DeploymentResource deplRsrc = new DeploymentResource(depName, - new DeploymentResourceLinks(self, deplStatus, status.toString())); - JSONObject statObj = new JSONObject(deplRsrc); - json = statObj.toString(); - } catch (BadRequestException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (ServiceAlreadyExistsException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (ServerErrorException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (DownstreamException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError("putDeployment failed", t)); - } finally { - postLogAudit(request); - } - return json; - } - - @RequestMapping(value = { - DEPLOYMENTS_PATH + "/{deploymentId}/update" }, method = RequestMethod.PUT, produces = "application/json") - public String updateDeployment(@PathVariable("deploymentId") String deploymentId, HttpServletRequest request, - @RequestBody DeploymentInput deploymentRequestObject) throws Exception { - preLogAudit(request); - String json = null; - String srvcTypeId = ""; - Optional<Integer> bpVersion = null; - String bpName = deploymentRequestObject.getBlueprintName(); - if (deploymentRequestObject.getBlueprintVersion().isPresent()) { - bpVersion = deploymentRequestObject.getBlueprintVersion(); - } - // get the serviceTypeId from inventory using the blueprint name - try { - srvcTypeId = getBlueprintTypeId(bpName, bpVersion, "typeId"); - } catch (Exception ex) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "ECOMP Inventory"); - MDC.put("TargetServiceName", "ECOMP Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting blueprint ID failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception"); - RestResponseError result = null; - if (ex instanceof HttpStatusCodeException) - result = new RestResponseError(((HttpStatusCodeException) ex).getResponseBodyAsString()); - else - result = new RestResponseError("Failed to get blueprint", ex); - try { - json = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - json = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } - return json; - } finally { - postLogAudit(request); - } - try { - json = objectMapper.writeValueAsString(deploymentHandlerClient.updateDeployment( - deploymentId, deploymentRequestObject.getTenant(), - new DeploymentRequest(srvcTypeId, deploymentRequestObject.getInputs()))); - } catch (BadRequestException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (ServiceAlreadyExistsException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (ServerErrorException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (DownstreamException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (JsonProcessingException jpe) { - // Should never, ever happen - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = "{ \"error\" : \"" + jpe.toString() + "\"}"; - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deployment failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError("putDeployment failed", t)); - } finally { - postLogAudit(request); - } - return json; - } - - /** - * Gets the executions for one deployment. - * - * - * @param deployment_id Deployment ID (query parameter) - * @param request HttpServletRequest - * @return CloudifyExecutionList - * @throws Exception on serialization failure - */ - @RequestMapping(value = { DEPLOYMENTS_PATH + "/{deploymentId}" + "/" - + EXECUTIONS_PATH }, method = RequestMethod.GET, produces = "application/json") - @ResponseBody - public String getExecutionByDeploymentId(@PathVariable("deploymentId") String deploymentId, - @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request) - throws Exception { - preLogAudit(request); - ECTransportModel result = null; - try { - if (tenant == null) { - throw new Exception("tenant name is missing"); - } - result = cloudifyClient.getExecutionsSummary(deploymentId, tenant); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception"); - result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); - } finally { - postLogAudit(request); - } - return objectMapper.writeValueAsString(result); - } - - /** - * Deletes the specified blueprint. - * - * @param id Blueprint ID - * @param request HttpServletRequest - * @param response HttpServletResponse - * @return status code on success; error on failure. - * @throws Exception On serialization failure - */ - @RequestMapping(value = { - SERVICE_TYPES_PATH + "/{typeid}" }, method = RequestMethod.DELETE, produces = "application/json") - @ResponseBody - public String deleteBlueprint(@PathVariable("typeid") String typeId, HttpServletRequest request, - HttpServletResponse response) throws Exception { - preLogAudit(request); - String json = "{\"202\": \"OK\"}"; - try { - // InventoryClient inventoryClient = getInventoryClient(); - ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build(); - ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); - if (srvcRefs != null && srvcRefs.totalCount > 0) { - throw new Exception("Services exist for the service type template, delete not permitted"); - } - inventoryClient.deleteServiceType(typeId); - } catch (ServiceTypeNotFoundException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (ServiceTypeAlreadyDeactivatedException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError("deleteBlueprint failed", t)); - } finally { - postLogAudit(request); - } - return json; - } - - /** - * Un-deploy an application or service - * - * @param deploymentId - * @param request - * @param tenant - * @param response - * @return - * @throws Exception - */ - @RequestMapping( - value = {DEPLOYMENTS_PATH + "/{deploymentId}"}, - method = RequestMethod.DELETE, - produces = "application/json") - public String deleteDeployment(@PathVariable("deploymentId") String deploymentId, - HttpServletRequest request, @RequestParam(value = "tenant", required = true) String tenant, - HttpServletResponse response) throws Exception { - preLogAudit(request); - String json = null; - StringBuffer status = new StringBuffer(); - try { - if (tenant == null) { - throw new Exception("tenant name is missing"); - } - deploymentHandlerClient.deleteDeployment(deploymentId, tenant); - String self = request.getRequestURL().toString().split("\\?")[0]; - status.append(self).append("/executions?tenant=").append(tenant); - DeploymentResource deplRsrc = new DeploymentResource(deploymentId, - new DeploymentResourceLinks(self, "", status.toString())); - JSONObject statObj = new JSONObject(deplRsrc); - json = statObj.toString(); - } catch (BadRequestException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (ServerErrorException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (DownstreamException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (DeploymentNotFoundException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError("deleteDeployment failed", t)); - } finally { - postLogAudit(request); - } - return json; - } - - /** - * Cancels an execution. - * - * @param id Execution ID - * @param deploymentId Deployment ID (not clear why this is needed) - * @param action Action to perform (not clear why this is needed) - * @param request HttpServletRequest - * @param response HttpServletRequest - * @return Passes thru HTTP status code from remote endpoint; no body on success - * @throws Exception on serialization failure - */ - @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.POST, produces = "application/json") - @ResponseBody - public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id, - @RequestBody Map<String, String> parameters, HttpServletRequest request, HttpServletResponse response) - throws Exception { - preLogAudit(request); - ECTransportModel result = null; - List<String> tenant = null; - try { - tenant = headers.get("tenant"); - result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0)); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Cloudify Manager"); - MDC.put("TargetServiceName", "Cloudify Manager"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception"); - result = new RestResponseError("cancelExecution failed on ID " + id, t); - } finally { - postLogAudit(request); - } - if (result == null) - return null; - else - return objectMapper.writeValueAsString(result); - } - - private void preLogAudit(HttpServletRequest request) { - begin = new Date(); - MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin)); - MDC.put(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin)); - MDC.put(SystemProperties.STATUS_CODE, "COMPLETE"); - } - - private void postLogAudit(HttpServletRequest request) { - end = new Date(); - MDC.put("AlertSeverity", "0"); - MDC.put("TargetEntity", "Deployment Handler"); - MDC.put("TargetServiceName", "Deployment Handler"); - MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(end)); - MDC.put(SystemProperties.METRICSLOG_END_TIMESTAMP, logDateFormat.format(end)); - //MDC.put(SystemProperties.MDC_TIMER, Long.toString((end.getTime() - begin.getTime()))); - logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); - logger.info(EELFLoggerDelegate.metricsLogger, request.getMethod() + request.getRequestURI()); - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ConsulController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ConsulController.java index 28f7520..25ab3fd 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ConsulController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ConsulController.java @@ -29,15 +29,15 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration; -import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration.EndpointCheck; -import org.onap.ccsdk.dashboard.model.ConsulNodeInfo; -import org.onap.ccsdk.dashboard.model.ConsulServiceHealth; -import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; import org.onap.ccsdk.dashboard.model.ECTransportModel; import org.onap.ccsdk.dashboard.model.RestResponseError; import org.onap.ccsdk.dashboard.model.RestResponsePage; import org.onap.ccsdk.dashboard.model.RestResponseSuccess; +import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration; +import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration.EndpointCheck; +import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo; import org.onap.ccsdk.dashboard.rest.ConsulClient; import org.onap.portalsdk.core.domain.User; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; @@ -333,105 +333,6 @@ public class ConsulController extends DashboardRestrictedBaseController { return json; } - /** - * Processes request to register a service for health checks. - * - * @param request HttpServletRequest - * @param registration Consul service registration - * @return URI of the newly registered resource - * @throws Exception on serialization error - */ - @RequestMapping(value = { "/register" }, method = RequestMethod.POST, produces = "application/json") - @ResponseBody - public String registerService(HttpServletRequest request, @RequestBody ConsulHealthServiceRegistration registration) - throws Exception { - preLogAudit(request); - ECTransportModel result = null; - try { - if (registration.services == null) { - throw new Exception("services[] tag is mandatory"); - } - - List<EndpointCheck> checks = registration.services.get(0).checks; - String service_name = registration.services.get(0).name; - String service_port = registration.services.get(0).port; - String service_address = registration.services.get(0).address; - - if (checks == null || service_port.isEmpty() || service_address.isEmpty() || service_name.isEmpty()) { - throw new Exception("fields : [checks[], port, address, name] are mandatory"); - } - for (EndpointCheck check : checks) { - if (check.endpoint.isEmpty() || check.interval.isEmpty()) { - throw new Exception("Required fields : [endpoint, interval] in checks"); - } - } - result = new RestResponseSuccess(consulClient.registerService(registration)); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Consul"); - MDC.put("TargetServiceName", "Consul"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Registering service failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "registerService caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Exception t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Consul"); - MDC.put("TargetServiceName", "Consul"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Registering service failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "registerService caught exception"); - result = new RestResponseError("registerService failed", t); - } finally { - postLogAudit(request); - } - return objectMapper.writeValueAsString(result); - } - - /** - * Processes request to deregister a service for health checks. - * - * @param request HttpServletRequest - * @param serviceName Consul service name to deregister - * @return Success or error indicator - * @throws Exception on serialization error - */ - @RequestMapping(value = { - "/deregister" + "/{serviceName}" }, method = RequestMethod.POST, produces = "application/json") - @ResponseBody - public String deregisterService(HttpServletRequest request, @PathVariable String serviceName) throws Exception { - preLogAudit(request); - ECTransportModel result = null; - try { - int code = consulClient.deregisterService(serviceName); - result = - new RestResponseSuccess("Deregistration yielded code " + Integer.toString(code)); - } catch (HttpStatusCodeException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Consul"); - MDC.put("TargetServiceName", "Consul"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "De-registering service " + serviceName + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deregisterService caught exception"); - result = new RestResponseError(e.getResponseBodyAsString()); - } catch (Throwable t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "Consul"); - MDC.put("TargetServiceName", "Consul"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "De-registering service " + serviceName + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deregisterService caught exception"); - result = new RestResponseError("deregisterService failed", t); - } finally { - postLogAudit(request); - } - return objectMapper.writeValueAsString(result); - } - public void preLogAudit(HttpServletRequest request) { begin = new Date(); MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin)); diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardHomeController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardHomeController.java index cccd8f6..263c3d0 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardHomeController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardHomeController.java @@ -21,28 +21,16 @@ *******************************************************************************/ package org.onap.ccsdk.dashboard.controller; -import java.util.ArrayList; import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.stream.Collectors; - import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import org.onap.ccsdk.dashboard.domain.EcdComponent; -import org.onap.ccsdk.dashboard.model.EcdAppComponent; -import org.onap.ccsdk.dashboard.model.RestResponseError; -import org.onap.ccsdk.dashboard.model.RestResponseSuccess; -import org.onap.ccsdk.dashboard.service.ControllerEndpointService; import org.onap.ccsdk.dashboard.util.DashboardProperties; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; import org.slf4j.MDC; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @@ -61,19 +49,14 @@ public class DashboardHomeController extends DashboardRestrictedBaseController { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DashboardHomeController.class); - @Autowired - private ControllerEndpointService controllerEndpointService; - /** * For general use in these methods */ private final ObjectMapper mapper; private static Date begin, end; - private static final String COMPONENTS_PATH = "components"; - private static final String USER_APPS_PATH = "user-apps"; private static final String APP_LABEL = "app-label"; - + /** * Never forget that Spring autowires fields AFTER the constructor is called. */ @@ -93,79 +76,10 @@ public class DashboardHomeController extends DashboardRestrictedBaseController { return new ModelAndView("ecd_home_tdkey"); } - /** - * Gets the available blueprint component names - * - * @param request HttpServletRequest - * @return List of component name strings, or an error on failure - */ - @RequestMapping( - value = {COMPONENTS_PATH}, - method = RequestMethod.GET, - produces = "application/json") + @RequestMapping(value = "/api-docs", method = RequestMethod.GET, produces = "application/json") @ResponseBody - public String getComponents(HttpServletRequest request) { - preLogAudit(request); - String outboundJson = ""; - try { - HttpSession session = request.getSession(true); - @SuppressWarnings("unchecked") - Set<String> userApps = (Set<String>) session.getAttribute("authComponents"); - if (userApps == null) { - userApps = new TreeSet<String>(); - } - List<EcdComponent> filterList = new ArrayList<EcdComponent>(); - List<EcdAppComponent> ecdApps = new ArrayList<EcdAppComponent>(); - - List<EcdComponent> dbResult = controllerEndpointService.getComponents(); - - List dcaeCompList = (List) dbResult.stream() - .filter(s -> ((EcdComponent) s).contains("dcae")).collect(Collectors.toList()); - - if (!userApps.isEmpty()) { // non-admin role level - for (String userRole : userApps) { - if (userRole.equalsIgnoreCase("dcae")) { - if (dcaeCompList != null && !dcaeCompList.isEmpty()) { - EcdAppComponent dcaeAppComponent = - new EcdAppComponent("DCAE", dcaeCompList); - ecdApps.add(dcaeAppComponent); - } - } else { - List tmpItemList = (List) dbResult.stream() - .filter(s -> ((EcdComponent) s).contains(userRole)) - .collect(Collectors.toList()); - if (tmpItemList != null) { - logger.debug(">>>> adding filtered items"); - filterList.addAll(tmpItemList); - } - } - } - if (!filterList.isEmpty()) { - EcdAppComponent ecdAppComponent = new EcdAppComponent("ECOMP", filterList); - ecdApps.add(ecdAppComponent); - } - } else { - // lookup "dcae" in the db component list - if (dcaeCompList != null && !dcaeCompList.isEmpty()) { - EcdAppComponent dcaeAppComponent = new EcdAppComponent("DCAE", dcaeCompList); - ecdApps.add(dcaeAppComponent); - } - } - outboundJson = mapper.writeValueAsString(ecdApps); - } catch (Exception ex) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DashboardHomeController"); - MDC.put("TargetServiceName", "DashboardHomeController"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Get components failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "Failed to get components list"); - RestResponseError response = new RestResponseError("Failed to get components list", ex); - outboundJson = response.toJson(); - } finally { - postLogAudit(request); - } - return outboundJson; + public Resource apiDocs() { + return new ClassPathResource("swagger.json"); } /** @@ -178,70 +92,7 @@ public class DashboardHomeController extends DashboardRestrictedBaseController { return mapper.writeValueAsString( DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_IN_ENV, "NA")); } - - /** - * Gets the application name(s) for the authenticated user - * - * @param request HttpServletRequest - * @return List of component name strings, or an error on failure - */ - @SuppressWarnings("unchecked") - @RequestMapping( - value = {USER_APPS_PATH}, - method = RequestMethod.GET, - produces = "application/json") - @ResponseBody - public String getUserApps(HttpServletRequest request) { - preLogAudit(request); - String outboundJson = ""; - try { - HttpSession session = request.getSession(true); - Set<String> userApps = (Set<String>) session.getAttribute("authComponents"); - if (userApps == null) { - userApps = new TreeSet<String>(); - } - outboundJson = mapper.writeValueAsString(userApps); - } catch (Exception ex) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DashboardHomeController"); - MDC.put("TargetServiceName", "DashboardHomeController"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Get User Apps failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "Failed to get apps list"); - RestResponseError response = new RestResponseError("Failed to get apps list", ex); - outboundJson = response.toJson(); - } finally { - postLogAudit(request); - } - return outboundJson; - } - - /** - * Sets the controller endpoint selection for the user. - * - * @param request HttpServletRequest - * @param endpoint Body with endpoint details - * @return Result indicating success or failure - * @throws Exception if application user is not found - */ - @RequestMapping( - value = {COMPONENTS_PATH}, - method = RequestMethod.POST, - produces = "application/json") - @ResponseBody - public String insertComponent(HttpServletRequest request, - @RequestBody EcdComponent newComponent) throws Exception { - preLogAudit(request); - String outboundJson = null; - controllerEndpointService.insertComponent(newComponent); - RestResponseSuccess success = - new RestResponseSuccess("Inserted new component with name " + newComponent.getCname()); - outboundJson = mapper.writeValueAsString(success); - postLogAudit(request); - return outboundJson; - } - + public void preLogAudit(HttpServletRequest request) { begin = new Date(); MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin)); diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardRestrictedBaseController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardRestrictedBaseController.java index f3b6147..cc1e9d8 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardRestrictedBaseController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardRestrictedBaseController.java @@ -27,7 +27,6 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.onap.ccsdk.dashboard.service.ControllerEndpointService; import org.onap.ccsdk.dashboard.util.DashboardProperties; import org.onap.portalsdk.core.controller.RestrictedBaseController; import org.springframework.beans.factory.annotation.Autowired; @@ -72,12 +71,7 @@ public class DashboardRestrictedBaseController extends RestrictedBaseController @Autowired protected DashboardProperties appProperties; - /** - * For getting selected controller - */ - @Autowired - private ControllerEndpointService controllerEndpointService; - + /** * Hello Spring, here's your no-arg constructor. */ diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerController.java index 0346ad7..d98c404 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerController.java @@ -22,7 +22,6 @@ package org.onap.ccsdk.dashboard.controller; import java.util.Date; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -50,8 +49,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; -import com.fasterxml.jackson.core.JsonProcessingException; - /** * Controller for Deployment Handler features: get/put/delete deployments * Methods serve Ajax requests made by Angular scripts on pages that show @@ -63,14 +60,15 @@ public class DeploymentHandlerController extends DashboardRestrictedBaseControll private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DeploymentHandlerController.class); - + @Autowired DeploymentHandlerClient deploymentHandlerClient; - + private static final String DEPLOYMENTS_PATH = "dcae-deployments"; private static Date begin, end; + @SuppressWarnings("unchecked") @RequestMapping(value = { DEPLOYMENTS_PATH + "/{deploymentId:.+}" }, method = RequestMethod.PUT, produces = "application/json") @ResponseBody @@ -83,13 +81,8 @@ public class DeploymentHandlerController extends DashboardRestrictedBaseControll json = objectMapper.writeValueAsString(deploymentHandlerClient.putDeployment( deploymentRequestObject.getDeploymentId(), deploymentRequestObject.getTenant(), new DeploymentRequest(deploymentRequestObject.getServiceTypeId(), - deploymentRequestObject.getInputs()))); - } else { - json = objectMapper.writeValueAsString(deploymentHandlerClient.updateDeployment( - deploymentRequestObject.getDeploymentId(), deploymentRequestObject.getTenant(), - new DeploymentRequest(deploymentRequestObject.getServiceTypeId(), - deploymentRequestObject.getInputs()))); - } + deploymentRequestObject.getInputs()), request)); + } } catch (BadRequestException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "Deployment Handler"); @@ -151,9 +144,7 @@ public class DeploymentHandlerController extends DashboardRestrictedBaseControll String json = null; StringBuffer status = new StringBuffer(); try { - // DeploymentHandlerClient deploymentHandlerClient = - // getDeploymentHandlerClient(request); - deploymentHandlerClient.deleteDeployment(deploymentId, tenant); + deploymentHandlerClient.deleteDeployment(deploymentId, tenant, request); String self = request.getRequestURL().toString().split("\\?")[0]; status.append(self).append("/executions?tenant=").append(tenant); DeploymentResource deplRsrc = new DeploymentResource(deploymentId, diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ECDSingleSignOnController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ECDSingleSignOnController.java index 49d5709..ad671ad 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ECDSingleSignOnController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ECDSingleSignOnController.java @@ -26,8 +26,6 @@ package org.onap.ccsdk.dashboard.controller; * ECOMP Portal SDK * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property - * - * Modifications Copyright (C) 2019 IBM. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +45,7 @@ import java.net.URLDecoder; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; +import java.util.TreeSet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @@ -56,12 +55,16 @@ import javax.servlet.http.HttpSession; import org.onap.portalsdk.core.auth.LoginStrategy; import org.onap.portalsdk.core.command.LoginBean; import org.onap.portalsdk.core.controller.UnRestrictedBaseController; +import org.onap.portalsdk.core.domain.Role; import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.domain.UserApp; +import org.onap.portalsdk.core.domain.FusionObject.Parameters; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.menu.MenuProperties; import org.onap.portalsdk.core.onboarding.listener.PortalTimeoutHandler; import org.onap.portalsdk.core.onboarding.util.PortalApiConstants; import org.onap.portalsdk.core.onboarding.util.PortalApiProperties; +import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.service.LoginService; import org.onap.portalsdk.core.service.RoleService; import org.onap.portalsdk.core.util.SystemProperties; @@ -98,9 +101,84 @@ public class ECDSingleSignOnController extends UnRestrictedBaseController { @Autowired private RoleService roleService; + @Autowired + private DataAccessService dataAccessService; + private String viewName; private String welcomeView; + @RequestMapping(value = { "signup.htm" }, method = RequestMethod.GET) + public ModelAndView externalLogin() { + Map<String, Object> model = new HashMap<>(); + return new ModelAndView("signup", "model", model); + } + + /** + * User sign up handler + * + * @param request + * @return + * @throws Exception + */ + @RequestMapping(value = { "/signup" }, method = RequestMethod.POST) + public ModelAndView userSignup(HttpServletRequest request, HttpServletResponse response) throws Exception { + LoginBean commandBean = new LoginBean(); + String loginId = request.getParameter("loginId"); + String password = request.getParameter("password"); + if (loginId.isEmpty() || password.isEmpty()) { + String loginErrorMessage = "User name and/or password missing"; + Map<String, String> model = new HashMap<>(); + model.put("error", loginErrorMessage); + return new ModelAndView("signup", "model", model); + } + commandBean.setLoginId(loginId); + commandBean.setLoginPwd(password); + commandBean.setUserid(loginId); + commandBean = loginService.findUser(commandBean, + (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap()); + + if (commandBean.getUser() == null) { + // add new user + User user = new User(); + user.setLoginId(loginId); + user.setLoginPwd(password); + user.setActive(true); + user.setOrgUserId(loginId); + user.setLastName(request.getParameter("last")); + user.setFirstName(request.getParameter("first")); + user.setEmail(request.getParameter("email")); + Role role = null; + HashMap additionalParams = new HashMap(); + additionalParams.put(Parameters.PARAM_HTTP_REQUEST, request); + user.setRoles(new TreeSet<Role>()); + user.setUserApps(new TreeSet<UserApp>()); + user.setPseudoRoles(new TreeSet<Role>()); + try { + dataAccessService.saveDomainObject(user, additionalParams); + role = (Role) dataAccessService.getDomainObject(Role.class, + Long.valueOf(SystemProperties.getProperty(SystemProperties.POST_DEFAULT_ROLE_ID)), + null); + if(role.getId() == null){ + logger.error(EELFLoggerDelegate.errorLogger, + "process failed: No Role Exsists in DB with requested RoleId :"+ Long.valueOf(SystemProperties.getProperty(SystemProperties.POST_DEFAULT_ROLE_ID))); + throw new Exception("user cannot be added"); + } + user.addRole(role); + //saveUserExtension(user); + dataAccessService.saveDomainObject(user, additionalParams); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "saveDomainObject failed on user " + user.getLoginId(), e); + String loginErrorMessage = (e.getMessage() != null) ? e.getMessage() + : "login.error.external.invalid - saveDomainObject failed on user " + user.getLoginId(); + Map<String, String> model = new HashMap<>(); + model.put("error", loginErrorMessage); + return new ModelAndView("signup", "model", model); + } + } + Map<String, Object> model = new HashMap<>(); + return new ModelAndView("login_external", "model", model); + } + /** * Handles requests directed to the single sign-on page by the session timeout * interceptor. @@ -225,6 +303,16 @@ public class ECDSingleSignOnController extends UnRestrictedBaseController { } } + @RequestMapping(value = { "logout.htm" }, method = RequestMethod.GET) + public ModelAndView appLogout(HttpServletRequest request) { + try { + request.getSession().invalidate(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "Logout failed", e); + } + return new ModelAndView("redirect:login.htm"); + } + /** * Discover if the portal is available by GET-ing a resource from the REST URL * specified in portal.properties, using a very short timeout. @@ -273,16 +361,14 @@ public class ECDSingleSignOnController extends UnRestrictedBaseController { return request.getSession().getId(); } - @Override public String getViewName() { return viewName; } - - @Override + public void setViewName(String viewName) { this.viewName = viewName; } - + public String getWelcomeView() { return welcomeView; } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/HealthCheckController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/HealthCheckController.java index 5087ad1..f8fd19e 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/HealthCheckController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/HealthCheckController.java @@ -2,22 +2,22 @@ * =============LICENSE_START========================================================= * * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * ============LICENSE_END========================================================= * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ package org.onap.ccsdk.dashboard.controller; @@ -25,30 +25,48 @@ package org.onap.ccsdk.dashboard.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.http.HttpStatus; import org.onap.ccsdk.dashboard.model.HealthStatus; +import org.onap.ccsdk.dashboard.rest.CloudifyClient; +import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient; +import org.onap.ccsdk.dashboard.rest.InventoryClient; +import org.onap.portalsdk.core.controller.FusionBaseController; import org.onap.portalsdk.core.util.SystemProperties; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * This controller responds to probes for application health, returning a JSON * body to indicate current status. */ @RestController -@Configuration -@EnableAspectJAutoProxy @RequestMapping("/") -public class HealthCheckController extends DashboardRestrictedBaseController { +public class HealthCheckController extends FusionBaseController { + @Autowired + InventoryClient inventoryClient; + + @Autowired + DeploymentHandlerClient deploymentHandlerClient; + + @Autowired + CloudifyClient cfyClient; + /** * Application name */ protected static final String APP_NAME = "ecd-app"; private static final String APP_HEALTH_CHECK_PATH = "/health"; + private static final String APP_SRVC_HEALTH_CHECK_PATH = "/health-info"; + + protected final ObjectMapper objectMapper = new ObjectMapper(); /** * application health by simply responding with a JSON object indicating status @@ -56,9 +74,13 @@ public class HealthCheckController extends DashboardRestrictedBaseController { * @param request HttpServletRequest * @return HealthStatus object always */ - @RequestMapping(value = { APP_HEALTH_CHECK_PATH }, method = RequestMethod.GET, produces = "application/json") + @RequestMapping( + value = {APP_HEALTH_CHECK_PATH}, + method = RequestMethod.GET, + produces = "application/json") public HealthStatus healthCheck(HttpServletRequest request, HttpServletResponse response) { return new HealthStatus(200, SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME) + " health check passed "); } + } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/InventoryController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/InventoryController.java index 4251212..3877dfc 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/InventoryController.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/InventoryController.java @@ -22,44 +22,55 @@ package org.onap.ccsdk.dashboard.controller; +import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.function.Predicate; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.apache.http.HttpStatus; import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException; -import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceAlreadyDeactivatedException; -import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceNotFoundException; import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException; import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException; import org.onap.ccsdk.dashboard.model.RestResponseError; import org.onap.ccsdk.dashboard.model.RestResponsePage; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.ServiceRefCfyList; import org.onap.ccsdk.dashboard.model.inventory.Blueprint; -import org.onap.ccsdk.dashboard.model.inventory.Service; +import org.onap.ccsdk.dashboard.model.inventory.BlueprintResponse; import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRef; import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; import org.onap.ccsdk.dashboard.model.inventory.ServiceType; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; +import org.onap.ccsdk.dashboard.rest.CloudifyClient; +import org.onap.ccsdk.dashboard.rest.ConsulClient; import org.onap.ccsdk.dashboard.rest.InventoryClient; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.objectcache.AbstractCacheManager; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.portalsdk.core.web.support.AppUtils; -import org.onap.ccsdk.dashboard.util.DashboardProperties; - +import org.onap.portalsdk.core.web.support.UserUtils; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -84,105 +95,40 @@ public class InventoryController extends DashboardRestrictedBaseController { @Autowired InventoryClient inventoryClient; + @Autowired + CloudifyClient cloudifyClient; + @Autowired + ConsulClient consulClient; + + /** + * For caching data + */ + private AbstractCacheManager cacheManager; + + @Autowired + public void setCacheManager(AbstractCacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + public AbstractCacheManager getCacheManager() { + return cacheManager; + } + /** * Enum for selecting an item type. */ public enum InventoryDataItem { - SERVICES, SERVICE_TYPES, SERVICES_GROUPBY; + SERVICE_TYPES, SERVICE_TYPE_NAME, OWNER, SERVICE_TYPE_ID; } private static Date begin, end; - private static final String SERVICES_PATH = "dcae-services"; + private static final String OWNERS = "owners"; private static final String SERVICE_TYPES_PATH = "dcae-service-types"; + private static final String SERVICE_TYPE_NAME = "service-type-list"; private static final String VIEW_SERVICE_TYPE_BLUEPRINT_PATH = "dcae-service-type-blueprint"; private static final String DEP_IDS_FOR_TYPE = "dcae-services/typeIds"; - - /** - * Gets one page of objects and supporting information via the REST client. On - * success, returns a PaginatedRestResponse object as String. - * - * @param option Specifies which item list type to get - * @param pageNum Page number of results - * @param pageSize Number of items per browser page - * @return JSON block as String, see above. - * @throws Exception On any error; e.g., Network failure. - */ - @SuppressWarnings({"rawtypes", "unchecked"}) - private String getItemListForPage(HttpServletRequest request, InventoryDataItem option, - int pageNum, int pageSize, String sortBy, String searchBy) throws Exception { - List itemList = null; - switch (option) { - case SERVICES: - itemList = inventoryClient.getServices().collect(Collectors.toList()); - if (searchBy != null) { - itemList = (List) itemList.stream() - .filter(s -> ((Service) s).contains(searchBy)).collect(Collectors.toList()); - } - for (Service bp : (List<Service>) itemList) { - bp.setCanDeploy(Optional.of(true)); - } - if (sortBy != null) { - if (sortBy.equals("deploymentRef")) { - Collections.sort(itemList, serviceDeploymentRefComparator); - } else if (sortBy.equals("serviceId")) { - Collections.sort(itemList, serviceIdComparator); - } else if (sortBy.equals("created")) { - Collections.sort(itemList, serviceCreatedComparator); - } else if (sortBy.equals("modified")) { - Collections.sort(itemList, serviceModifiedComparator); - } - } - break; - case SERVICE_TYPES: - itemList = inventoryClient.getServiceTypes().collect(Collectors.toList()); - if (searchBy != null) { - itemList = - (List) itemList.stream().filter(s -> ((ServiceType) s).contains(searchBy)) - .collect(Collectors.toList()); - } - for (ServiceType bp : (List<ServiceType>) itemList) { - bp.setCanDeploy(Optional.of(true)); - } - if (sortBy != null) { - if (sortBy.equals("owner")) { - Collections.sort(itemList, serviceTypeOwnerComparator); - } else if (sortBy.equals("typeId")) { - Collections.sort(itemList, serviceTypeIdComparator); - } else if (sortBy.equals("typeName")) { - Collections.sort(itemList, serviceTypeNameComparator); - } else if (sortBy.equals("typeVersion")) { - Collections.sort(itemList, serviceTypeVersionComparator); - } else if (sortBy.equals("created")) { - Collections.sort(itemList, serviceTypeCreatedComparator); - } else if (sortBy.equals("application")) { - Collections.sort(itemList, serviceTypeApplComparator); - } else if (sortBy.equals("component")) { - Collections.sort(itemList, serviceTypeCompComparator); - } - } - break; - default: - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Getting page of items failed!"); - throw new Exception( - "getItemListForPage failed: unimplemented case: " + option.name()); - } - - // Shrink if needed - final int totalItems = itemList.size(); - final int pageCount = (int) Math.ceil((double) totalItems / pageSize); - if (totalItems > pageSize) - itemList = getPageOfList(pageNum, pageSize, itemList); - - RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); - String outboundJson = objectMapper.writeValueAsString(model); - return outboundJson; - } + private static final String SERVICE_TYPE_ID = "service-type-id-list"; /** * version with user role auth Gets one page of objects and supporting @@ -202,171 +148,211 @@ public class InventoryController extends DashboardRestrictedBaseController { HashMap<String, Boolean> comp_deploy_tab = (HashMap<String, Boolean>) session.getAttribute("comp_access"); String roleLevel = (String) session.getAttribute("role_level"); - + String roleAuth = (String) session.getAttribute("auth_role"); + String user = UserUtils.getUserSession(request).getLoginId(); + if (roleLevel == null) { roleLevel = "dev"; } if (comp_deploy_tab == null) { comp_deploy_tab = new HashMap<String, Boolean>(); } - + if (roleAuth == null) { + roleAuth = "READ"; + } Set<String> userApps = (Set<String>) session.getAttribute("authComponents"); if (userApps == null) { userApps = new TreeSet<String>(); } - + ReadWriteLock lock = new ReentrantReadWriteLock(); List itemList = null; - List<ServiceType> filterList = new ArrayList<ServiceType>(); - List<Service> authDepList = new ArrayList<Service>(); - switch (option) { - case SERVICES: - itemList = inventoryClient.getServices().collect(Collectors.toList()); - if (roleLevel.equals("app")) { - for (String userRole : userApps) { - logger.debug(">>>> check component type from deployment: " + userRole); - for (Service cont : (List<Service>) itemList) { - String deplRef = cont.getDeploymentRef().toLowerCase(); - logger.debug(">>>> container deployment name: " + deplRef); - if (deplRef.contains(userRole)) { - logger.debug(">>>> adding deployment item to filtered subset"); - authDepList.add(cont); - } - } - } - } + List bpItemList = null; + int totalItems = 0; + + lock.readLock().lock(); + List<ServiceTypeSummary> bpList = + (List<ServiceTypeSummary>)getCacheManager().getObject(SERVICE_TYPES_PATH); + lock.readLock().unlock(); + if (bpList == null) { + bpList = inventoryClient.getServiceTypes().collect(Collectors.toList()); + } - if (searchBy != null) { - if (!roleLevel.equals("app")) { - itemList = - (List) itemList.stream().filter(s -> ((Service) s).contains(searchBy)) - .collect(Collectors.toList()); - } else { - if (!authDepList.isEmpty()) { - authDepList = (List) authDepList.stream() - .filter(s -> ((Service) s).contains(searchBy)) - .collect(Collectors.toList()); - } - } + String svcRefFilterStr = ""; + String appFilterStr = ""; + String compFilterStr = ""; + String ownerFilterStr = ""; + String containsFilterStr = ""; + // apply user search filters + if (searchBy != null && !searchBy.isEmpty()) { + // parse the search filters string + // look for service name patterns + List<String> searchFilters = + new ArrayList<String>(Arrays.asList(searchBy.split(";"))); + if (searchFilters.stream().anyMatch(s->s.startsWith("contains"))) { + List<String> containsList = searchFilters.stream().filter(s->s.startsWith("contains")). + collect(Collectors.toList()); + containsFilterStr = containsList.get(0).split(":")[1]; + } + if (searchFilters.stream().anyMatch(s->s.startsWith("serviceRef"))) { + List<String> svcRefsList = searchFilters.stream().filter(s->s.startsWith("serviceRef")). + collect(Collectors.toList()); + svcRefFilterStr = svcRefsList.get(0).split(":")[1]; + } + if (searchFilters.stream().anyMatch(s->s.startsWith("app"))) { + List<String> appsList = searchFilters.stream().filter(s->s.startsWith("app")). + collect(Collectors.toList()); + appFilterStr = appsList.get(0).split(":")[1]; + } + if (searchFilters.stream().anyMatch(s->s.startsWith("comp"))) { + List<String> compList = searchFilters.stream().filter(s->s.startsWith("comp")). + collect(Collectors.toList()); + compFilterStr = compList.get(0).split(":")[1]; + } + if (searchFilters.stream().anyMatch(s->s.startsWith("owner"))) { + List<String> ownerList = searchFilters.stream().filter(s->s.startsWith("owner")). + collect(Collectors.toList()); + ownerFilterStr = ownerList.get(0).split(":")[1]; + } + if (!ownerFilterStr.isEmpty()) { + List<ServiceTypeSummary> ownerBpList = new ArrayList<ServiceTypeSummary>(); + lock.readLock().lock(); + Map<String, List<ServiceTypeSummary>> bpPerOwner = + (Map<String, List<ServiceTypeSummary>>) getCacheManager().getObject("owner_bp_map"); + lock.readLock().unlock(); + + List<String> ownerFilterList = + new ArrayList<String>(Arrays.asList(ownerFilterStr.split(","))); + + if (ownerFilterList.size() == 1 && ownerFilterList.get(0).equals("undefined")) { + ownerFilterList.clear(); + ownerFilterList.add(user); } - if (roleLevel.equals("app")) { - logger.debug(">>>> update response with authorized content"); - itemList.clear(); - itemList.addAll(authDepList); + + if (bpPerOwner != null) { + Stream<Map.Entry<String, List<ServiceTypeSummary>>> bpOwnerEntriesStream = + bpPerOwner.entrySet().stream(); + + Set<Map.Entry<String, List<ServiceTypeSummary>>> bpOwnerSet = + bpOwnerEntriesStream.filter(m -> ownerFilterList.stream(). + anyMatch(ownFilter -> m.getKey().equalsIgnoreCase(ownFilter))).collect(Collectors.toSet()); + bpOwnerSet.stream().forEach(e -> ownerBpList.addAll(e.getValue())); + bpItemList = ownerBpList; } - - // check for authorization to perform delete deployed blueprints - - if (!roleLevel.equals("ops")) { - for (Service bp : (List<Service>) itemList) { - String deplRef = bp.getDeploymentRef().split("_")[0].toLowerCase(); - logger.debug(">>>> deployment reference: " + deplRef); - if (comp_deploy_tab.containsKey(deplRef)) { - boolean enableDeploy = comp_deploy_tab.get(deplRef); - logger.debug(">>>> enable deploy button: " + enableDeploy); - bp.setCanDeploy(Optional.of(enableDeploy)); - } else { - bp.setCanDeploy(Optional.of(false)); - } - } - } else { - for (Service bp : (List<Service>) itemList) { - bp.setCanDeploy(Optional.of(true)); - } - } - - if (sortBy != null) { - if (sortBy.equals("deploymentRef")) { - Collections.sort(itemList, serviceDeploymentRefComparator); - } else if (sortBy.equals("serviceId")) { - Collections.sort(itemList, serviceIdComparator); - } else if (sortBy.equals("created")) { - Collections.sort(itemList, serviceCreatedComparator); - } else if (sortBy.equals("modified")) { - Collections.sort(itemList, serviceModifiedComparator); - } + if (bpItemList == null) { + bpItemList = new ArrayList<ServiceTypeSummary>(); + bpItemList.addAll(bpList); } + } + } + if (bpItemList == null) { + bpItemList = new ArrayList<ServiceTypeSummary>(); + bpItemList.addAll(bpList); + } + // apply role based filtering + if (roleLevel.equals("app")) { + @SuppressWarnings("unchecked") + List<String> myApps = new ArrayList(userApps); + bpItemList = (List<ServiceTypeSummary>)bpItemList.stream().filter(s -> myApps.stream() + .anyMatch(appFilter -> (((ServiceTypeSummary)s).getComponent() != null && + ((ServiceTypeSummary)s).getComponent().equalsIgnoreCase(appFilter)))) + .collect(Collectors.<ServiceTypeSummary>toList()); + } else if (roleLevel.equals("app_dev")) { + Predicate<ServiceTypeSummary> appFilter = + p -> p.getComponent() != null && !p.getComponent().equalsIgnoreCase("dcae") + && !p.getComponent().equalsIgnoreCase("d2a"); + bpItemList = (List<ServiceTypeSummary>)bpItemList.stream().filter(appFilter). + collect(Collectors.toList()); + } + + switch (option) { + case OWNER: + Set<String> ownersList = + (Set) bpItemList.stream().map(x -> ((ServiceTypeSummary)x).getOwner()).collect(Collectors.toSet()); + return objectMapper.writeValueAsString(ownersList); + case SERVICE_TYPE_ID: + itemList = bpItemList; + totalItems = itemList.size(); + RestResponsePage<List> model = new RestResponsePage<>(totalItems, 1, itemList); + String outboundJson = objectMapper.writeValueAsString(model); + return outboundJson; + case SERVICE_TYPE_NAME: + Set<String> svcTypeList = + (Set) bpItemList.stream().map(x -> ((ServiceTypeSummary)x).getTypeName()).collect(Collectors.toSet()); + itemList = new ArrayList<String>(); + itemList.addAll(svcTypeList); break; case SERVICE_TYPES: - ServiceTypeQueryParams serviceQueryParams = - new ServiceTypeQueryParams.Builder().onlyLatest(false).build(); - itemList = inventoryClient.getServiceTypes(serviceQueryParams) - .collect(Collectors.toList()); - if (roleLevel.equals("app")) { - for (String userApp : userApps) { - logger.debug(">>>> check component type from BP: " + userApp); - for (ServiceType bp : (List<ServiceType>) itemList) { - String bpComp = bp.getComponent(); - String bpOwner = bp.getOwner(); // for backward compatibility - logger.debug(">>>> BP component name: " + bpComp); - if ((bpComp != null && bpComp.equalsIgnoreCase(userApp)) - || bpOwner.contains(userApp)) { - logger.debug(">>>> adding item to filtered subset"); - filterList.add(bp); - } - } - } + // apply response filters + itemList = bpItemList; + String outFilter = request.getParameter("_include"); + if (outFilter != null) { + List<String> svcSummaryList = + (List) itemList.stream().map(x -> extractBpSummary((ServiceTypeSummary)x)).collect(Collectors.toList()); + return objectMapper.writeValueAsString(svcSummaryList); } - if (searchBy != null) { - if (!roleLevel.equals("app")) { - itemList = (List) itemList.stream() - .filter(s -> ((ServiceType) s).contains(searchBy)) - .collect(Collectors.toList()); - } else { - if (!filterList.isEmpty()) { - filterList = (List) filterList.stream() - .filter(s -> ((ServiceType) s).contains(searchBy)) + // apply user search filters + if (searchBy != null && !searchBy.isEmpty()) { + if (!svcRefFilterStr.isEmpty()) { + List<String> svcFilterList = + new ArrayList<String>(Arrays.asList(svcRefFilterStr.split(","))); + if (!svcFilterList.isEmpty()) { + itemList = (List) itemList.stream().filter(s -> svcFilterList.stream() + .anyMatch(svcFilter -> ((ServiceTypeSummary) s).getTypeName().toLowerCase().contains(svcFilter.toLowerCase()))) .collect(Collectors.toList()); } + } + if (!appFilterStr.isEmpty()) { + List<String> appFilterList = + new ArrayList<String>(Arrays.asList(appFilterStr.split(","))); + Predicate<ServiceTypeSummary> srvcAppFilter = + p -> p.getApplication() != null; + Stream<ServiceTypeSummary> svcStream = itemList.stream(); + + itemList = svcStream.filter( srvcAppFilter.and( + s -> appFilterList.stream() + .anyMatch(appFilter ->((ServiceTypeSummary) s).getApplication().equalsIgnoreCase(appFilter)))) + .collect(Collectors.toList()); + } + if (!compFilterStr.isEmpty()) { + List<String> compFilterList = + new ArrayList<String>(Arrays.asList(compFilterStr.split(","))); + Predicate<ServiceTypeSummary> srvcCompFilter = + p -> p.getComponent() != null; + Stream<ServiceTypeSummary> svcStream = itemList.stream(); + itemList = svcStream.filter( srvcCompFilter.and( + s -> compFilterList.stream() + .anyMatch(compFilter ->((ServiceTypeSummary) s).getComponent().equalsIgnoreCase(compFilter)))) + .collect(Collectors.toList()); } - } - if (roleLevel.equals("app")) { - logger.debug(">>>> update response with authorized content"); - itemList.clear(); - itemList.addAll(filterList); - } - // check for authorization to perform update/delete/deploy blueprints - if (!roleLevel.equals("ops")) { - for (ServiceType bp : (List<ServiceType>) itemList) { - String bpComp = bp.getComponent(); - if (bpComp != null && bpComp.length() > 0) { - bpComp = bpComp.toLowerCase(); - } else { - String bpOwner = bp.getOwner(); // for backward compatibility - if (bpOwner != null && bpOwner.contains(":")) { - bpComp = bp.getOwner().split(":")[0].toLowerCase(); - } - } - logger.debug(">>>> BP component name: " + bpComp); - if (comp_deploy_tab.containsKey(bpComp)) { - boolean enableDeploy = comp_deploy_tab.get(bpComp); - logger.debug(">>>> enable deploy button: " + enableDeploy); - bp.setCanDeploy(Optional.of(enableDeploy)); - } else { - bp.setCanDeploy(Optional.of(false)); - } + if (!containsFilterStr.isEmpty()) { + final String simpleSrch = containsFilterStr.split(",")[0]; + itemList = (List<ServiceTypeSummary>) itemList.stream() + .filter(s -> ((ServiceTypeSummary) s).contains(simpleSrch)).collect(Collectors.toList()); } - } else { - for (ServiceType bp : (List<ServiceType>) itemList) { - bp.setCanDeploy(Optional.of(true)); - } - } - + } if (sortBy != null) { if (sortBy.equals("owner")) { - Collections.sort(itemList, serviceTypeOwnerComparator); + ((List<ServiceTypeSummary>)itemList).sort( + (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getOwner().compareTo(o2.getOwner())); } else if (sortBy.equals("typeId")) { - Collections.sort(itemList, serviceTypeIdComparator); + ((List<ServiceTypeSummary>)itemList).sort( + (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeId().get().compareTo(o2.getTypeId().get())); } else if (sortBy.equals("typeName")) { - Collections.sort(itemList, serviceTypeNameComparator); + ((List<ServiceTypeSummary>)itemList).sort( + (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeName().compareTo(o2.getTypeName())); } else if (sortBy.equals("typeVersion")) { - Collections.sort(itemList, serviceTypeVersionComparator); + ((List<ServiceTypeSummary>)itemList).sort( + (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeVersion().compareTo(o2.getTypeVersion())); } else if (sortBy.equals("created")) { - Collections.sort(itemList, serviceTypeCreatedComparator); + ((List<ServiceTypeSummary>)itemList).sort( + (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getCreated().get().compareTo(o2.getCreated().get())); } else if (sortBy.equals("application")) { - Collections.sort(itemList, serviceTypeApplComparator); + ((List<ServiceTypeSummary>)itemList).sort( + (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getApplication().compareTo(o2.getApplication())); } else if (sortBy.equals("component")) { - Collections.sort(itemList, serviceTypeCompComparator); + ((List<ServiceTypeSummary>)itemList).sort( + (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getComponent().compareTo(o2.getComponent())); } } break; @@ -380,18 +366,91 @@ public class InventoryController extends DashboardRestrictedBaseController { throw new Exception( "getItemListForPage failed: unimplemented case: " + option.name()); } - // Shrink if needed - final int totalItems = itemList.size(); + if (itemList != null) { + totalItems = itemList.size(); + } final int pageCount = (int) Math.ceil((double) totalItems / pageSize); - if (totalItems > pageSize) + if (totalItems > pageSize && option.equals(InventoryDataItem.SERVICE_TYPES)) { itemList = getPageOfList(pageNum, pageSize, itemList); - + } + if (option.equals(InventoryDataItem.SERVICE_TYPES)) { + if (!roleLevel.equals("ops")) { + if (roleLevel.equals("dev") || roleLevel.equals("app_dev")) { + boolean deployFlag = roleAuth.equals("WRITE") ? true : false; + for (ServiceTypeSummary bp : (List<ServiceTypeSummary>) itemList) { + bp.setCanDeploy(Optional.of(deployFlag)); + } + } else { + for (ServiceTypeSummary bp : (List<ServiceTypeSummary>) itemList) { + String bpComp = bp.getComponent(); + if (bpComp != null && bpComp.length() > 0) { + bpComp = bpComp.toLowerCase(); + } else { + String bpOwner = bp.getOwner(); // for backward compatibility + if (bpOwner != null && bpOwner.contains(":")) { + bpComp = bp.getOwner().split(":")[0].toLowerCase(); + } + } + if (comp_deploy_tab.containsKey(bpComp)) { + boolean enableDeploy = comp_deploy_tab.get(bpComp); + logger.debug(">>>> enable deploy button: " + enableDeploy); + bp.setCanDeploy(Optional.of(enableDeploy)); + } else { + bp.setCanDeploy(Optional.of(false)); + } + } + } + } else { + for (ServiceTypeSummary bp : (List<ServiceTypeSummary>) itemList) { + bp.setCanDeploy(Optional.of(true)); + } + } + // add the deployments mapping to the list + lock.readLock().lock(); + List<ServiceTypeServiceMap> cache_bp_map_arr = + (List<ServiceTypeServiceMap>) getCacheManager().getObject("bp_deploy_map"); + lock.readLock().unlock(); + if (cache_bp_map_arr != null) { + for (ServiceTypeSummary bpSum: (List<ServiceTypeSummary>)itemList) { + // correlate the cached data for deployments + List<ServiceTypeServiceMap> bp_depl_list = + cache_bp_map_arr.stream().filter( + (Predicate<? super ServiceTypeServiceMap>) + s->s.getServiceTypeId().equals(bpSum.getTypeId().get())). + collect(Collectors.toList()); + if (bp_depl_list != null && !bp_depl_list.isEmpty()) { + bpSum.setDeployments((ServiceRefCfyList)bp_depl_list.get(0).getServiceRefList()); + } + } + } + } RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList); String outboundJson = objectMapper.writeValueAsString(model); return outboundJson; } - + + @SuppressWarnings("unchecked") + @Scheduled(fixedDelay=600000, initialDelay=150000) + public void cacheOwnerToBpMap() { + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + List<ServiceTypeSummary> bpList = + (List<ServiceTypeSummary>)getCacheManager().getObject(SERVICE_TYPES_PATH); + lock.readLock().unlock(); + if (bpList != null) { + Map<String, List<ServiceTypeSummary>> bpPerOwner = bpList.stream() + .collect(Collectors.groupingBy(bp -> bp.getOwner())); + + lock.writeLock().lock(); + getCacheManager().putObject("owner_bp_map", bpPerOwner); + lock.writeLock().unlock(); + } + } + + private BlueprintResponse extractBpSummary(ServiceTypeSummary bp) { + return new BlueprintResponse(bp.getTypeName(), bp.getTypeVersion(), bp.getTypeId().get()); + } /** * Gets one page of the specified items. This method traps exceptions and * constructs an appropriate JSON block to report errors. @@ -407,16 +466,8 @@ public class InventoryController extends DashboardRestrictedBaseController { try { int pageNum = getRequestPageNumber(request); int pageSize = getRequestPageSize(request); - String appEnv = "os"; - appEnv = - DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"); - if (appEnv.equals("os")) { - outboundJson = - getItemListForPage(request, option, pageNum, pageSize, sortBy, searchBy); - } else { - outboundJson = - getItemListForPageAuth(request, option, pageNum, pageSize, sortBy, searchBy); - } + outboundJson = + getItemListForPageAuth(request, option, pageNum, pageSize, sortBy, searchBy); } catch (Exception ex) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "DCAE Inventory"); @@ -445,121 +496,24 @@ public class InventoryController extends DashboardRestrictedBaseController { } /** - * Supports sorting service types by owner - */ - private static Comparator<ServiceType> serviceTypeOwnerComparator = - new Comparator<ServiceType>() { - @Override - public int compare(ServiceType o1, ServiceType o2) { - return o1.getOwner().compareToIgnoreCase(o2.getOwner()); - } - }; - - /** - * Supports sorting service types by application - */ - private static Comparator<ServiceType> serviceTypeApplComparator = - new Comparator<ServiceType>() { - @Override - public int compare(ServiceType o1, ServiceType o2) { - return o1.getApplication().compareToIgnoreCase(o2.getApplication()); - } - }; - - /** - * Supports sorting service types by component - */ - private static Comparator<ServiceType> serviceTypeCompComparator = - new Comparator<ServiceType>() { - @Override - public int compare(ServiceType o1, ServiceType o2) { - return o1.getComponent().compareToIgnoreCase(o2.getComponent()); - } - }; - - /** - * Supports sorting service types by type id - */ - private static Comparator<ServiceType> serviceTypeIdComparator = new Comparator<ServiceType>() { - @Override - public int compare(ServiceType o1, ServiceType o2) { - return o1.getTypeId().get().compareToIgnoreCase(o2.getTypeId().get()); - } - }; - - /** - * Supports sorting service types by type name - */ - private static Comparator<ServiceType> serviceTypeNameComparator = - new Comparator<ServiceType>() { - @Override - public int compare(ServiceType o1, ServiceType o2) { - return o1.getTypeName().compareToIgnoreCase(o2.getTypeName()); - } - }; - - /** - * Supports sorting service types by type version - */ - private static Comparator<ServiceType> serviceTypeVersionComparator = - new Comparator<ServiceType>() { - @Override - public int compare(ServiceType o1, ServiceType o2) { - return o1.getTypeVersion().compareTo(o2.getTypeVersion()); - } - }; - - /** - * Supports sorting service types by created date - */ - private static Comparator<ServiceType> serviceTypeCreatedComparator = - new Comparator<ServiceType>() { - @Override - public int compare(ServiceType o1, ServiceType o2) { - return o1.getCreated().get().compareToIgnoreCase(o2.getCreated().get()); - } - }; - - /** - * Supports sorting services by deploymentRef - */ - private static Comparator<Service> serviceDeploymentRefComparator = new Comparator<Service>() { - @Override - public int compare(Service o1, Service o2) { - return o1.getDeploymentRef().compareToIgnoreCase(o2.getDeploymentRef()); - } - }; - - /** - * Supports sorting services by service id - */ - private static Comparator<Service> serviceIdComparator = new Comparator<Service>() { - @Override - public int compare(Service o1, Service o2) { - return o1.getServiceId().compareToIgnoreCase(o2.getServiceId()); - } - }; - - /** - * Supports sorting services by created date - */ - private static Comparator<Service> serviceCreatedComparator = new Comparator<Service>() { - @Override - public int compare(Service o1, Service o2) { - return o1.getCreated().compareToIgnoreCase(o2.getCreated()); - } - }; - - /** - * Supports sorting services by created date + * Serves one page of blueprint owners + * + * @param request HttpServletRequest + * @return List of ServiceTypes objects */ - private static Comparator<Service> serviceModifiedComparator = new Comparator<Service>() { - @Override - public int compare(Service o1, Service o2) { - return o1.getModified().compareToIgnoreCase(o2.getModified()); - } - }; - + @RequestMapping( + value = {OWNERS}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + public String getOwnersByPage(HttpServletRequest request) { + preLogAudit(request); + String json = getItemListForPageWrapper(request, InventoryDataItem.OWNER, + request.getParameter("sortBy"), request.getParameter("searchBy")); + postLogAudit(request); + return json; + } + /** * Serves one page of service types * @@ -600,27 +554,50 @@ public class InventoryController extends DashboardRestrictedBaseController { return objectMapper.writeValueAsString(result); } + /** - * Serves one page of services - * + * Serves the complete list of service type names + * * @param request HttpServletRequest - * - * @return List of Service objects + * + * @return list of service type names */ @RequestMapping( - value = {SERVICES_PATH}, + value = {SERVICE_TYPE_NAME}, method = RequestMethod.GET, produces = "application/json") @ResponseBody - public String getServicesByPage(HttpServletRequest request) { + @Cacheable + public String getAllServiceTypeNames(HttpServletRequest request) { // preLogAudit(request); String json = null; - json = getItemListForPageWrapper(request, InventoryDataItem.SERVICES, + json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPE_NAME, request.getParameter("sortBy"), request.getParameter("searchBy")); postLogAudit(request); return json; - } - + } + + /** + * Serves the aggregate count of service types + * + * @param request HttpServletRequest + * + * @return count of service types + */ + @RequestMapping( + value = {SERVICE_TYPE_ID}, + method = RequestMethod.GET, + produces = "application/json") + @ResponseBody + @Cacheable + public String getAllServiceTypeIds(HttpServletRequest request) { + String json = null; + json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPE_ID, + request.getParameter("sortBy"), request.getParameter("searchBy")); + postLogAudit(request); + return json; + } + /** * Gets the specified blueprint content for viewing. * @@ -679,68 +656,61 @@ public class InventoryController extends DashboardRestrictedBaseController { * @throws Exception On serialization failure */ @RequestMapping( - value = {SERVICE_TYPES_PATH + "/{typeid}"}, + value = {SERVICE_TYPES_PATH + "/{typeId}"}, method = RequestMethod.DELETE, produces = "application/json") @ResponseBody - public String deleteServiceType(@PathVariable("typeid") String typeid, - HttpServletRequest request, HttpServletResponse response) throws Exception { + public String deleteServiceType(@PathVariable("typeId") String typeId, + HttpServletRequest request, + HttpServletResponse response) throws Exception { preLogAudit(request); - String json = "{\"202\": \"OK\"}"; + String json = "{\"204\": \"Blueprint deleted\"}"; + boolean allow = true; try { - inventoryClient.deleteServiceType(typeid); + // check if these dep_ids exist in cloudify + List<CloudifyDeployedTenant> deplForBp = + cloudifyClient.getDeploymentForBlueprint("TID-"+typeId); + if (deplForBp.size() > 0 ) { + allow = false; + } else { + ServiceQueryParams qryParams = + new ServiceQueryParams.Builder().typeId(typeId).build(); + ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams); + Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet()); + if (dep_ids.size() > 0) { + // now check again if these dep_ids still exist in cloudify + List<String> allDepNames = cloudifyClient.getDeploymentNamesWithFilter(request); + for (String str: dep_ids) { + if (allDepNames.stream().anyMatch(s->s.equalsIgnoreCase(str))) { + allow = false; + break; + } + } + } + } + if (!allow) { + response.setStatus(HttpStatus.SC_BAD_REQUEST); + json = objectMapper.writeValueAsString( + new RestResponseError("Deployments exist for this blueprint")); + /* + PrintWriter out = response.getWriter(); + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + out.print(json); + out.flush(); + */ + return json; + } else { + inventoryClient.deleteServiceType(typeId); + this.cacheOwnerToBpMap(); + } } catch (ServiceTypeNotFoundException | ServiceTypeAlreadyDeactivatedException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "DCAE Inventory"); MDC.put("TargetServiceName", "DCAE Inventory"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting service type " + typeid + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception"); - json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); - } catch (Exception t) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting service type " + typeid + " failed!"); - logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception"); - json = objectMapper - .writeValueAsString(new RestResponseError("deleteDeployment failed", t)); - } finally { - postLogAudit(request); - } - return json; - } - - /** - * Deletes the specified service i.e. deployment from inventory - * - * @param id Service ID - * @param request HttpServletRequest - * @param response HttpServletResponse - * @return status code on success; error on failure. - * @throws Exception On serialization failure - */ - @RequestMapping( - value = {SERVICES_PATH + "/{serviceId}"}, - method = RequestMethod.DELETE, - produces = "application/json") - @ResponseBody - public String deleteService(@PathVariable("serviceId") String serviceId, - HttpServletRequest request, HttpServletResponse response) throws Exception { - preLogAudit(request); - String json = "{\"202\": \"OK\"}"; - try { - inventoryClient.deleteService(serviceId); - } catch (ServiceNotFoundException | ServiceAlreadyDeactivatedException e) { - MDC.put(SystemProperties.STATUS_CODE, "ERROR"); - MDC.put("TargetEntity", "DCAE Inventory"); - MDC.put("TargetServiceName", "DCAE Inventory"); - MDC.put("ErrorCode", "300"); - MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting service " + serviceId + " failed!"); + MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception"); json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage())); } catch (Exception t) { @@ -749,10 +719,10 @@ public class InventoryController extends DashboardRestrictedBaseController { MDC.put("TargetServiceName", "DCAE Inventory"); MDC.put("ErrorCode", "300"); MDC.put("ErrorCategory", "ERROR"); - MDC.put("ErrorDescription", "Deleting service " + serviceId + " failed!"); + MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!"); logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception"); json = objectMapper - .writeValueAsString(new RestResponseError("deleteDeployment failed", t)); + .writeValueAsString(new RestResponseError("delete blueprint failed", t)); } finally { postLogAudit(request); } @@ -778,8 +748,7 @@ public class InventoryController extends DashboardRestrictedBaseController { String json = "{\"201\": \"OK\"}"; try { // Verify that the Service Type can be parsed for inputs. - Blueprint.parse(serviceType.getBlueprintTemplate()); - // InventoryClient inventoryClient = getInventoryClient(request); + Blueprint.parse(serviceType.getBlueprintTemplate()); inventoryClient.addServiceType(serviceType); } catch (BlueprintParseException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); @@ -839,8 +808,8 @@ public class InventoryController extends DashboardRestrictedBaseController { String json = "{\"201\": \"OK\"}"; try { Blueprint.parse(serviceTypeRequest.getBlueprintTemplate()); - // InventoryClient inventoryClient = getInventoryClient(request); inventoryClient.addServiceType(serviceTypeRequest); + this.cacheOwnerToBpMap(); } catch (BlueprintParseException e) { MDC.put(SystemProperties.STATUS_CODE, "ERROR"); MDC.put("TargetEntity", "DCAE Inventory"); diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/ControllerEndpoint.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/ControllerEndpoint.java deleted file mode 100644 index 3e74ff4..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/ControllerEndpoint.java +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ - -package org.onap.ccsdk.dashboard.domain; - -import org.onap.portalsdk.core.domain.support.DomainVo; - -/** - * Model for controller endpoint information stored in database. A single row - * for a user represents a selected endpoint. - */ -public class ControllerEndpoint extends DomainVo { - - private static final long serialVersionUID = 8785223545128054402L; - - private long userId; - private String name; - private String url; - private String inventoryUrl; - private String dhandlerUrl; - - public ControllerEndpoint() { - } - - public ControllerEndpoint(long userId, String name, String url, String inventoryUrl, String dhandlerUrl) { - this.userId = userId; - this.name = name; - this.url = url; - this.inventoryUrl = inventoryUrl; - this.dhandlerUrl = dhandlerUrl; - } - - public long getUserId() { - return userId; - } - - public void setUserId(long userId) { - this.userId = userId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getInventoryUrl() { - return inventoryUrl; - } - - public void setInventoryUrl(String inventoryUrl) { - this.inventoryUrl = inventoryUrl; - } - - public String getDhandlerUrl() { - return dhandlerUrl; - } - - public void setDhandlerUrl(String dhandlerUrl) { - this.dhandlerUrl = dhandlerUrl; - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/EcdComponent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/EcdComponent.java deleted file mode 100644 index c62d7bc..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/EcdComponent.java +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ - -package org.onap.ccsdk.dashboard.domain; - -import org.apache.commons.lang3.StringUtils; -import org.onap.portalsdk.core.domain.support.DomainVo; - -public class EcdComponent extends DomainVo { - - private static final long serialVersionUID = 1L; - - private Long compId; - private String cname; // component name - private String dname; // component display name - - public Long getCompId() { - return compId; - } - - public void setCompId(Long compId) { - this.compId = compId; - } - - public String getCname() { - return cname; - } - - public void setCname(String cname) { - this.cname = cname; - } - - public String getDname() { - return dname; - } - - public void setDname(String dname) { - this.dname = dname; - } - - public boolean contains(String searchString) { - if (StringUtils.containsIgnoreCase(this.getCname(), searchString) - || StringUtils.containsIgnoreCase(this.getDname(), searchString)) { - return true; - } - return false; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployment.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployment.java deleted file mode 100644 index 60bf229..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployment.java +++ /dev/null @@ -1,165 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model with fields only for the top-level attributes. All complex child - * structures are represented simply as generic collections. - */ -public final class CloudifyDeployment extends ECTransportModel { - - /** A unique identifier for the deployment. */ - public final String id; - public final String description; - /** The id of the blueprint the deployment is based on. */ - public final String blueprint_id; - /** The time when the deployment was created. */ - public final String created_at; - /** The time the deployment was last updated at. */ - public final String updated_at; - /** - * A dictionary containing key value pairs which represents a deployment input - * and its provided value. - */ - public final Map<String, Object> inputs; - /** A dictionary containing policies of a deployment. */ - public final Map<String, Object> policy_types; - /** A dictionary containing policy triggers of a deployment. */ - public final Map<String, Object> policy_triggers; - /** A dictionary containing an outputs definition of a deployment. */ - public final Map<String, Object> outputs; - /** A dictionary containing the groups definition of deployment. */ - public final Map<String, Object> groups; - - public final Map<String, Object> scaling_groups; - /** A list of workflows that can be executed on a deployment. */ - public final List<Workflow> workflows; - - public final String tenant_name; - - @JsonCreator - public CloudifyDeployment(@JsonProperty("description") String description, - @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("created_at") String created_at, - @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id, - @JsonProperty("inputs") Map<String, Object> inputs, - @JsonProperty("policy_types") Map<String, Object> policy_types, - @JsonProperty("policy_triggers") Map<String, Object> policy_triggers, - @JsonProperty("outputs") Map<String, Object> outputs, @JsonProperty("groups") Map<String, Object> groups, - @JsonProperty("scaling_groups") Map<String, Object> scaling_groups, - @JsonProperty("workflows") List<Workflow> workflows, @JsonProperty("tenant_name") String tenant_name) { - this.description = description; - this.blueprint_id = blueprint_id; - this.created_at = created_at; - this.updated_at = updated_at; - this.id = id; - this.inputs = inputs; - this.policy_types = policy_types; - this.policy_triggers = policy_triggers; - this.outputs = outputs; - this.groups = groups; - this.scaling_groups = scaling_groups; - this.workflows = workflows; - this.tenant_name = tenant_name; - } - - public static final class Inputs { - public final String openstack_auth_url; - public final String external_network_name; - public final String openstack_username; - public final String instance_image; - public final String keypair_name; - public final String instance_name; - public final String keypair_private_key_path; - public final String openstack_tenant_name; - public final String subnet_name; - public final String openstack_region; - public final String openstack_password; - public final String ssh_username; - public final String instance_flavor; - public final String network_name; - - @JsonCreator - public Inputs(@JsonProperty("openstack_auth_url") String openstack_auth_url, - @JsonProperty("external_network_name") String external_network_name, - @JsonProperty("openstack_username") String openstack_username, - @JsonProperty("instance_image") String instance_image, - @JsonProperty("keypair_name") String keypair_name, @JsonProperty("instance_name") String instance_name, - @JsonProperty("keypair_private_key_path") String keypair_private_key_path, - @JsonProperty("openstack_tenant_name") String openstack_tenant_name, - @JsonProperty("subnet_name") String subnet_name, - @JsonProperty("openstack_region") String openstack_region, - @JsonProperty("openstack_password") String openstack_password, - @JsonProperty("ssh_username") String ssh_username, - @JsonProperty("instance_flavor") String instance_flavor, - @JsonProperty("network_name") String network_name) { - - this.openstack_auth_url = openstack_auth_url; - this.external_network_name = external_network_name; - this.openstack_username = openstack_username; - this.instance_image = instance_image; - this.keypair_name = keypair_name; - this.instance_name = instance_name; - this.keypair_private_key_path = keypair_private_key_path; - this.openstack_tenant_name = openstack_tenant_name; - this.subnet_name = subnet_name; - this.openstack_region = openstack_region; - this.openstack_password = openstack_password; - this.ssh_username = ssh_username; - this.instance_flavor = instance_flavor; - this.network_name = network_name; - } - } - - public static final class Workflow { - public final String name; - public final String created_at; - public final Map<String, Parameter> parameters; - - @JsonCreator - public Workflow(@JsonProperty("name") String name, @JsonProperty("created_at") String created_at, - @JsonProperty("parameters") Map<String, Parameter> parameters) { - this.name = name; - this.created_at = created_at; - this.parameters = parameters; - } - } - - public static final class Parameter { - - @JsonProperty("default") - public final Object xdefault; - public final String description; - - @JsonCreator - public Parameter(@JsonProperty("default") Object xdefault, @JsonProperty("description") String description) { - this.xdefault = xdefault; - this.description = description; - } - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentRequest.java deleted file mode 100644 index 2110111..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentRequest.java +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model for message POST-ed to controller to create a Cloudify Deployment: - * - * <pre> - { - "deployment_id" : "deployment-id", - "blueprint_id" : "blueprint-id", - "parameters" : - { - "p1" : "v1" - } - } - * </pre> - */ -public final class CloudifyDeploymentRequest extends ECTransportModel { - - /** A unique identifier for the deployment. */ - public final String deployment_id; - /** A unique identifier for the blueprint. */ - public final String blueprint_id; - /** - * These values are input for the deployment which can be retrieved from the GET - * /blueprint API this is :plan.input field in GET /blueprint - */ - public final Map<String, Object> parameters; - - @JsonCreator - public CloudifyDeploymentRequest(@JsonProperty("deployment_id") String deployment_id, - @JsonProperty("blueprint_id") String blueprint_id, - @JsonProperty("parameters") Map<String, Object> parameters) { - this.deployment_id = deployment_id; - this.blueprint_id = blueprint_id; - this.parameters = parameters; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateRequest.java deleted file mode 100644 index 16ac145..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateRequest.java +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model for message POST-ed to controller to update a Cloudify Deployment: - * - * NOTE: THIS IS NOT HOW THE REQUEST TO CLOUDIFY'S ENDPOINT LOOKS. THE REQUEST - * IS CONSTRUCTED IN PROPER FORMAT IN THE API HANDLER - * - * <pre> - * { - "deployment_id" : "deployment-id", - "workflow_name" : "workflow-name", - "allow_custom_parameter" : "true|false", - "force" : "true|false", - "node_instance_id": "node-instance-id", - "limits_cpu": limits_cpu, - "limits_mem": limits_mem, - "image": "image", - "replicas": replicas, - "container_name": "container_name" - } - * </pre> - */ -public final class CloudifyDeploymentUpdateRequest extends ECTransportModel { - - /** A unique identifier for the deployment. */ - public final String deployment_id; - /** A unique identifier for the workflow */ - public final String workflow_name; - public final Boolean allow_custom_parameter; - public final Boolean force; - /** Parameters: retrieve using the GET /deployments */ - // public final Map<String, Object> parameters; - public final String node_instance_id; - public final String limits_cpu; - public final String limits_mem; - public final String image; - public final Number replicas; - public final String container_name; - - @JsonCreator - public CloudifyDeploymentUpdateRequest(@JsonProperty("deployment_id") String deployment_id, - @JsonProperty("workflow_name") String workflow_name, - @JsonProperty("allow_custom_parameter") Boolean allowCustomParameter, @JsonProperty("force") Boolean force, - @JsonProperty("node_instance_id") String node_instance_id, @JsonProperty("limits_cpu") String limits_cpu, - @JsonProperty("limits_mem") String limits_mem, @JsonProperty("image") String image, - @JsonProperty("replicas") Number replicas, @JsonProperty("container_name") String container_name) { - - this.deployment_id = deployment_id; - this.workflow_name = workflow_name; - this.allow_custom_parameter = allowCustomParameter; - this.force = force; - // this.parameters = parameters; - this.node_instance_id = node_instance_id; - this.limits_cpu = limits_cpu; - this.limits_mem = limits_mem; - this.image = image; - this.replicas = replicas; - this.container_name = container_name; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateResponse.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateResponse.java deleted file mode 100644 index 65688bb..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateResponse.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model with fields only for the top-level attributes. All complex child - * structures are represented simply as generic collections. - */ -public final class CloudifyDeploymentUpdateResponse extends ECTransportModel { - - /** A unique identifier for the execution. */ - public final String id; - /** The executions status. */ - public final String status; - /** The time the execution was queued at. */ - public final String created_at; - /** The id/name of the workflow the execution is of. */ - public final String workflow_id; - /** true if the execution is of a system workflow. */ - public final Boolean is_system_workflow; - /** The id of the blueprint the execution is in the context of. */ - public final String blueprint_id; - /** The id of the deployment the execution is in the context of. */ - public final String deployment_id; - /** The execution’s error message on execution failure. */ - public final String error; - /** A dict of the workflow parameters passed when starting the execution. */ - public final Map<String, Object> parameters; - - public final String tenant_name; - - public final String created_by; - - public final Boolean private_resource; - - public final String resource_availability; - - @JsonCreator - public CloudifyDeploymentUpdateResponse(@JsonProperty("status") String status, - @JsonProperty("created_at") String created_at, @JsonProperty("workflow_id") String workflow_id, - @JsonProperty("is_system_workflow") Boolean is_system_workflow, - @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("deployment_id") String deployment_id, - @JsonProperty("error") String error, @JsonProperty("id") String id, - @JsonProperty("parameters") Map<String, Object> parameters, @JsonProperty("tenant_name") String tenant_name, - @JsonProperty("created_by") String created_by, @JsonProperty("private_resource") Boolean private_resource, - @JsonProperty("resource_availability") String resource_availability) { - - this.status = status; - this.created_at = created_at; - this.workflow_id = workflow_id; - this.is_system_workflow = is_system_workflow; - this.blueprint_id = blueprint_id; - this.deployment_id = deployment_id; - this.error = error; - this.id = id; - this.parameters = parameters; - this.tenant_name = tenant_name; - this.created_by = created_by; - this.private_resource = private_resource; - this.resource_availability = resource_availability; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpgradeRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpgradeRequest.java deleted file mode 100644 index 30d3d16..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpgradeRequest.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model for message POST-ed to controller to execute upgrade workflow on a - * Cloudify Deployment: - * - * NOTE: THIS IS NOT HOW THE REQUEST TO CLOUDIFY'S ENDPOINT LOOKS. THE REQUEST - * IS CONSTRUCTED IN PROPER FORMAT IN THE API HANDLER - * - * <pre> -* { - "config_url": config_url, - "config_format": config_format, - "chartRepo": chartRepo, - "chartVersion": chartVersion - }; - * </pre> - */ -public final class CloudifyDeploymentUpgradeRequest extends ECTransportModel { - - public final String config_url; - public final String config_format; - public final String chartRepo; - public final String chartVersion; - - @JsonCreator - public CloudifyDeploymentUpgradeRequest(@JsonProperty("config_url") String config_url, - @JsonProperty("config_format") String config_format, @JsonProperty("chartRepo") String chartRepo, - @JsonProperty("chartVersion") String chartVersion) { - - this.config_url = config_url; - this.config_format = config_format; - this.chartRepo = chartRepo; - this.chartVersion = chartVersion; - } - - public String getConfig_url() { - return config_url; - } - - public String getConfig_format() { - return config_format; - } - - public String getChartRepo() { - return chartRepo; - } - - public String getChartVersion() { - return chartVersion; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEvent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEvent.java deleted file mode 100644 index d95ff24..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEvent.java +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.LinkedList; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class CloudifyEvent extends ECTransportModel { - - /** The id of the blueprint the execution is in the context of. */ - public final String blueprint_id; - /** The id of the deployment the execution is in the context of. */ - public final String deployment_id; - /** List of errors that happened while executing a given task */ - public final List<CloudifyErrorCause> error_causes; - /** The executions status. */ - public final String event_type; - /** The time the execution was queued at. */ - public final String execution_id; - /** log level */ - public final String level; - /** logger id */ - public final String logger; - /** message text */ - public final String message; - /** node instance id */ - public final String node_instance_id; - /** node name */ - public final String node_name; - /** Operation path */ - public final String operation; - /** time at which the event occurred on the executing machine */ - public final String reported_timestamp; - /** time at which the event was logged on the management machine */ - public final String timestamp; - /** resource is a cloudify_event or a cloudify_log */ - public final String type; - /** The id/name of the workflow the execution is of. */ - public final String workflow_id; - - @JsonCreator - public CloudifyEvent(@JsonProperty("blueprint_id") String blueprint_id, - @JsonProperty("deployment_id") String deployment_id, - @JsonProperty("error_causes") List<CloudifyErrorCause> error_causes, - @JsonProperty("event_type") String event_type, @JsonProperty("execution_id") String execution_id, - @JsonProperty("level") String level, @JsonProperty("logger") String logger, - @JsonProperty("message") String message, @JsonProperty("node_instance_id") String node_instance_id, - @JsonProperty("node_name") String node_name, @JsonProperty("operation") String operation, - @JsonProperty("reported_timestamp") String reported_timestamp, @JsonProperty("timestamp") String timestamp, - @JsonProperty("type") String type, @JsonProperty("workflow_id") String workflow_id) { - - this.blueprint_id = blueprint_id; - this.deployment_id = deployment_id; - this.error_causes = (error_causes == null) ? new LinkedList<CloudifyErrorCause>() : error_causes; - this.event_type = event_type; - this.execution_id = execution_id; - this.level = level; - this.logger = logger; - this.message = message; - this.node_instance_id = node_instance_id; - this.node_name = node_name; - this.operation = operation; - this.reported_timestamp = reported_timestamp; - this.timestamp = timestamp; - this.type = type; - this.workflow_id = workflow_id; - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java deleted file mode 100644 index 3fe393d..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model with fields only for the top-level attributes. All complex child - * structures are represented simply as generic collections. - */ -public final class CloudifyExecution extends ECTransportModel { - - /** A unique identifier for the execution. */ - public final String id; - /** The executions status. */ - public final String status; - /** The time the execution was queued at. */ - public final String created_at; - /** The id/name of the workflow the execution is of. */ - public final String workflow_id; - /** true if the execution is of a system workflow. */ - public final Boolean is_system_workflow; - /** The id of the blueprint the execution is in the context of. */ - public final String blueprint_id; - /** The id of the deployment the execution is in the context of. */ - public final String deployment_id; - /** The tenant used to deploy */ - public final String tenant_name; - /** The execution’s error message on execution failure. */ - public final String error; - /** A dict of the workflow parameters passed when starting the execution. */ - public final Map<String, Object> parameters; - /** true if helm plugin is used */ - public Boolean is_helm; - /** true if helm status is enabled */ - public Boolean helm_status; - - @JsonCreator - public CloudifyExecution(@JsonProperty("status") String status, @JsonProperty("created_at") String created_at, - @JsonProperty("workflow_id") String workflow_id, - @JsonProperty("is_system_workflow") Boolean is_system_workflow, - @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("deployment_id") String deployment_id, - @JsonProperty("tenant_name") String tenant_name, @JsonProperty("error") String error, - @JsonProperty("id") String id, @JsonProperty("parameters") Map<String, Object> parameters, - @JsonProperty("is_helm") Boolean is_helm, @JsonProperty("helm_status") Boolean helm_status) { - - this.status = status; - this.created_at = created_at; - this.workflow_id = workflow_id; - this.is_system_workflow = is_system_workflow; - this.blueprint_id = blueprint_id; - this.deployment_id = deployment_id; - this.tenant_name = tenant_name; - this.error = error; - this.id = id; - this.parameters = parameters; - this.is_helm = is_helm; - this.helm_status = helm_status; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionRequest.java deleted file mode 100644 index a9bad02..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionRequest.java +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * - * Modifications Copyright (C) 2019 IBM - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class CloudifyExecutionRequest extends ECTransportModel { - - /** A unique identifier for the deployment. */ - public String deployment_id; - /** A unique identifier for the workflow */ - public String workflow_id; - public Boolean allow_custom_parameters; - public Boolean force; - public String tenant; - /** Parameters: retrieve using the GET /deployments */ - public Map<String, Object> parameters; - - @JsonCreator - public CloudifyExecutionRequest(@JsonProperty("deployment_id") String deployment_id, - @JsonProperty("workflow_id") String workflow_id, - @JsonProperty("allow_custom_parameters") Boolean allowCustomParameters, - @JsonProperty("force") Boolean force, @JsonProperty("tenant") String tenant, - @JsonProperty("parameters") Map<String, Object> parameters) { - this.deployment_id = deployment_id; - this.workflow_id = workflow_id; - this.allow_custom_parameters = allowCustomParameters; - this.force = force; - this.tenant = tenant; - this.parameters = parameters; - } - - public String getDeployment_id() { - return deployment_id; - } - - public String getWorkflow_id() { - return workflow_id; - } - - public Boolean getAllow_custom_parameters() { - return allow_custom_parameters; - } - - public Boolean getForce() { - return force; - } - - public String getTenant() { - return tenant; - } - - public Map<String, Object> getParameters() { - return parameters; - } - - public void setDeployment_id(String deployment_id) { - this.deployment_id = deployment_id; - } - - public void setWorkflow_id(String workflow_id) { - this.workflow_id = workflow_id; - } - - public void setAllow_custom_parameters(Boolean allow_custom_parameters) { - this.allow_custom_parameters = allow_custom_parameters; - } - - public void setForce(Boolean force) { - this.force = force; - } - - public void setTenant(String tenant) { - this.tenant = tenant; - } - - public void setParameters(Map<String, Object> parameters) { - this.parameters = parameters; - } - - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceId.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceId.java deleted file mode 100644 index abe25fc..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceId.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model with fields only for the top-level attributes. All complex child - * structures are represented as generic collections. - */ -public final class CloudifyNodeInstanceId extends ECTransportModel { - - /** The id of the node instance. */ - public final String id; - - /** The name of the user that created the node instance */ - // public final String created_by; - /** The id of the deployment the node instance belongs to. */ - // public final String deployment_id; - /** The Compute node instance id the node is contained within. */ - // public final String host_id; - /** The relationships the node has with other nodes. */ - // public final List relationships; - /** The runtime properties of the node instance. */ - // public final String runtime_properties; - /** The node instance state. */ - // public final String state; - /** The name of the tenant that owns the node instance. */ - - // public final String tenant_name; - /** - * A version attribute used for optimistic locking when updating the node - * instance. - */ - // public final String version; - - @JsonCreator - public CloudifyNodeInstanceId(@JsonProperty("id") String id) { - this.id = id; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecret.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecret.java deleted file mode 100644 index 594ebfa..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecret.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class CloudifySecret extends ECTransportModel { - - /** The time when the secret was created */ - public final String created_at; - /** The secret’s key, unique per tenant */ - public final String key; - /** The time the secret was last updated at */ - public final String updated_at; - /** The secret’s value */ - public final String value; - /** Defines who can see the secret. Can be private, tenant or global */ - public final String visibility; - /** Determines who can see the value of the secret. */ - public final String is_hidden_value; - - @JsonCreator - public CloudifySecret(@JsonProperty("created_at") String created_at, @JsonProperty("key") String key, - @JsonProperty("updated_at") String updated_at, @JsonProperty("value") String value, - @JsonProperty("visibility") String visibility, @JsonProperty("is_hidden_value") String is_hidden_value) { - this.created_at = created_at; - this.key = key; - this.updated_at = updated_at; - this.value = value; - this.visibility = visibility; - this.is_hidden_value = is_hidden_value; - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretUpload.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretUpload.java deleted file mode 100644 index 3026a7a..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretUpload.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class CloudifySecretUpload extends ECTransportModel { - - /** The secret's name */ - public final String name; - /** The secret’s value */ - public final String value; - /** Update value if secret already exists */ - public final boolean update_if_exists; - /** Defines who can see the secret. Can be private, tenant or global */ - public final String visibility; - /** Determines who can see the value of the secret. */ - public final boolean is_hidden_value; - /** The tenant name for this secret */ - public final String tenant; - - @JsonCreator - public CloudifySecretUpload(@JsonProperty("name") String name, @JsonProperty("value") String value, - @JsonProperty("update_if_exists") boolean update_if_exists, @JsonProperty("visibility") String visibility, - @JsonProperty("is_hidden_value") boolean is_hidden_value, @JsonProperty("tenant") String tenant) { - this.name = name; - this.value = value; - this.update_if_exists = update_if_exists; - this.visibility = visibility; - this.is_hidden_value = is_hidden_value; - this.tenant = tenant; - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointCredentials.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointCredentials.java deleted file mode 100644 index 03159c2..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointCredentials.java +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import org.onap.portalsdk.core.onboarding.util.CipherUtil; - -/** - * Model with Controller username and password for use only within the back end; - * never serialized as JSON. - */ -public class ControllerEndpointCredentials extends ControllerEndpointTransport { - - public String username; - public String password; - public boolean isEncryptedPass; - - public ControllerEndpointCredentials(boolean selected, String name, String url, String inventoryUrl, - String dhandlerUrl, String consulUrl, String username, String password, boolean isEncryptedPass) { - super(selected, name, url, inventoryUrl, dhandlerUrl, consulUrl); - this.username = username; - this.password = password; - this.isEncryptedPass = isEncryptedPass; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public boolean getEncryptedPassword() { - return isEncryptedPass; - } - - public void setEncryptedPassword(boolean isEncryptedPass) { - this.isEncryptedPass = isEncryptedPass; - } - - /** - * Convenience method to yield a ControllerEndpointTransport object. - * - * @return ControllerEndpoint with copy of the non-privileged data - */ - public ControllerEndpointTransport toControllerEndpointTransport() { - return new ControllerEndpointTransport(getSelected(), getName(), getUrl(), getInventoryUrl(), getDhandlerUrl(), - getConsulUrl()); - } - - /** - * Accepts clear text and stores an encrypted value; as a side effect, sets the - * encrypted flag to true. - * - * @param plainText Clear-text password - * @throws Exception If encryption fails - */ - public void encryptPassword(final String plainText) throws Exception { - this.password = CipherUtil.encrypt(plainText); - this.isEncryptedPass = true; - } - - /** - * Client should call this method if {@link #getEncryptedPassword()} returns - * true. - * - * @return Clear-text password. - * @throws Exception If decryption fails - */ - public String decryptPassword() throws Exception { - return CipherUtil.decrypt(password); - } -}
\ No newline at end of file diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointTransport.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointTransport.java deleted file mode 100644 index 56019c9..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointTransport.java +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -/** - * Model for message passed by backend to frontend about ECOMP-C Endpoints. - */ -public class ControllerEndpointTransport extends ECTransportModel { - - private boolean selected; - private String name; - private String url; - private String inventoryUrl; - private String dhandlerUrl; - private String consulUrl; - - public ControllerEndpointTransport() { - } - - public ControllerEndpointTransport(boolean selected, String name, String url, String inventoryUrl, - String dhandlerUrl, String consulUrl) { - this.selected = selected; - this.name = name; - this.url = url; - this.inventoryUrl = inventoryUrl; - this.dhandlerUrl = dhandlerUrl; - this.consulUrl = consulUrl; - } - - public boolean getSelected() { - return selected; - } - - public void setSelected(boolean selected) { - this.selected = selected; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getInventoryUrl() { - return inventoryUrl; - } - - public void setInventoryUrl(String inventoryUrl) { - this.inventoryUrl = inventoryUrl; - } - - public String getDhandlerUrl() { - return dhandlerUrl; - } - - public void setDhandlerUrl(String dhandlerUrl) { - this.dhandlerUrl = dhandlerUrl; - } - - public String getConsulUrl() { - return consulUrl; - } - - public void setConsulUrl(String consulUrl) { - this.consulUrl = consulUrl; - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerOpsTools.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerOpsTools.java deleted file mode 100644 index 1bc8702..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerOpsTools.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -/** - * Model for message passed by backend to frontend about OPS Tools URLs. - */ -public class ControllerOpsTools extends ECTransportModel { - - private String id; - private String url; - - public ControllerOpsTools() { - } - - public ControllerOpsTools(String id, String url) { - this.setId(id); - this.setUrl(url); - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprint.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyBlueprint.java index d9fa528..bdb920d 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprint.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyBlueprint.java @@ -19,10 +19,12 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.Map; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,30 +34,30 @@ import com.fasterxml.jackson.annotation.JsonProperty; */ public final class CloudifyBlueprint extends ECTransportModel { - /** A unique identifier for the blueprint. */ - public final String id; - /** The blueprint’s main file name. */ - public final String main_file_name; - /** The blueprint’s description. */ - public final String description; - /** The time the blueprint was uploaded to the manager. */ - public final String created_at; - /** The last time the blueprint was updated. */ - public final String updated_at; - /** The parsed result of the blueprint. */ - public final Map<String, Object> plan; + /** A unique identifier for the blueprint. */ + public final String id; + /** The blueprint’s main file name. */ + public final String main_file_name; + /** The blueprint’s description. */ + public final String description; + /** The time the blueprint was uploaded to the manager. */ + public final String created_at; + /** The last time the blueprint was updated. */ + public final String updated_at; + /** The parsed result of the blueprint. */ + public final Map<String, Object> plan; - @JsonCreator - public CloudifyBlueprint(@JsonProperty("main_file_name") String main_file_name, - @JsonProperty("description") String description, @JsonProperty("created_at") String created_at, - @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id, - @JsonProperty("plan") Map<String, Object> plan) { - this.main_file_name = main_file_name; - this.description = description; - this.created_at = created_at; - this.updated_at = updated_at; - this.id = id; - this.plan = plan; - } + @JsonCreator + public CloudifyBlueprint(@JsonProperty("main_file_name") String main_file_name, + @JsonProperty("description") String description, @JsonProperty("created_at") String created_at, + @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id, + @JsonProperty("plan") Map<String, Object> plan) { + this.main_file_name = main_file_name; + this.description = description; + this.created_at = created_at; + this.updated_at = updated_at; + this.id = id; + this.plan = plan; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyBlueprintList.java index 6238e22..faee797 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyBlueprintList.java @@ -1,4 +1,3 @@ - /******************************************************************************* * =============LICENSE_START========================================================= * @@ -20,46 +19,46 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyBlueprintList extends ECTransportModel { - - public final List<CloudifyBlueprint> items; - public final Metadata metadata; + + public final List<CloudifyBlueprint> items; + public final Metadata metadata; @JsonCreator - public CloudifyBlueprintList(@JsonProperty("items") List<CloudifyBlueprint> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } - - public static final class Metadata { - public final Pagination pagination; + public CloudifyBlueprintList(@JsonProperty("items") List<CloudifyBlueprint> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } + + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } - + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } + } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenant.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenant.java new file mode 100644 index 0000000..a895dd0 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenant.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.cloudify; + + +import org.onap.ccsdk.dashboard.model.ECTransportModel; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CloudifyDeployedTenant extends ECTransportModel { + + /** A unique identifier for the deployment. */ + public final String id; + /** tenant where the deployment was done */ + public final String tenant_name; + public final String created_at; + public final String updated_at; + + @JsonCreator + public CloudifyDeployedTenant(@JsonProperty("id") String id, + @JsonProperty("tenant_name") String tenant_name, + @JsonProperty("created_at") String created_at, + @JsonProperty("updated_at") String updated_at) { + this.id = id; + this.tenant_name = tenant_name; + this.created_at = created_at; + this.updated_at = updated_at; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((created_at == null) ? 0 : created_at.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((tenant_name == null) ? 0 : tenant_name.hashCode()); + result = prime * result + ((updated_at == null) ? 0 : updated_at.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CloudifyDeployedTenant other = (CloudifyDeployedTenant) obj; + if (created_at == null) { + if (other.created_at != null) + return false; + } else if (!created_at.equals(other.created_at)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (tenant_name == null) { + if (other.tenant_name != null) + return false; + } else if (!tenant_name.equals(other.tenant_name)) + return false; + if (updated_at == null) { + if (other.updated_at != null) + return false; + } else if (!updated_at.equals(other.updated_at)) + return false; + return true; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployedTenantList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenantList.java index 155f415..96a91b6 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployedTenantList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenantList.java @@ -19,44 +19,44 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyDeployedTenantList extends ECTransportModel { - public final List<CloudifyDeployedTenant> items; - public final Metadata metadata; + public final List<CloudifyDeployedTenant> items; + public final Metadata metadata; @JsonCreator - public CloudifyDeployedTenantList(@JsonProperty("items") List<CloudifyDeployedTenant> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } + public CloudifyDeployedTenantList(@JsonProperty("items") List<CloudifyDeployedTenant> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } - public static final class Metadata { - public final Pagination pagination; + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployment.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployment.java new file mode 100644 index 0000000..94ccf7d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployment.java @@ -0,0 +1,219 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.cloudify; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Model with fields only for the top-level attributes. All complex child + * structures are represented simply as generic collections. + */ +public final class CloudifyDeployment extends ECTransportModel { + + /** A unique identifier for the deployment. */ + public final String id; + public final String description; + /** The id of the blueprint the deployment is based on. */ + public final String blueprint_id; + /** The time when the deployment was created. */ + public final String created_at; + /** The time the deployment was last updated at. */ + public final String updated_at; + /** + * A dictionary containing key value pairs which represents a deployment + * input and its provided value. + */ + public final Map<String, Object> inputs; + /** A dictionary containing policies of a deployment. */ + public final Map<String, Object> policy_types; + /** A dictionary containing policy triggers of a deployment. */ + public final Map<String, Object> policy_triggers; + /** A dictionary containing an outputs definition of a deployment. */ + public final Map<String, Object> outputs; + /** A dictionary containing the groups definition of deployment. */ + public final Map<String, Object> groups; + + public final Map<String, Object> scaling_groups; + /** A list of workflows that can be executed on a deployment. */ + public final List<Workflow> workflows; + + public final String tenant_name; + + /** internal role based setting */ + public boolean canDeploy; + + /** latest execution object */ + public CloudifyExecution lastExecution; + /** install execution workflow status */ + //public String installStatus; + /** true if helm plugin is used */ + public Boolean isHelm; + /** true if helm status is enabled */ + public Boolean helmStatus; + /** Consul service health status */ + public String healthStatus; + /** blueprint owner */ + public String owner; + + @JsonCreator + public CloudifyDeployment(@JsonProperty("description") String description, + @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("created_at") String created_at, + @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id, + @JsonProperty("inputs") Map<String, Object> inputs, @JsonProperty("policy_types") Map<String, Object> policy_types, + @JsonProperty("policy_triggers") Map<String, Object> policy_triggers, + @JsonProperty("outputs") Map<String, Object> outputs, @JsonProperty("groups") Map<String, Object> groups, + @JsonProperty("scaling_groups") Map<String, Object> scaling_groups, + @JsonProperty("workflows") List<Workflow> workflows, @JsonProperty("tenant_name") String tenant_name) { + this.description = description; + this.blueprint_id = blueprint_id; + this.created_at = created_at; + this.updated_at = updated_at; + this.id = id; + this.inputs = inputs; + this.policy_types = policy_types; + this.policy_triggers = policy_triggers; + this.outputs = outputs; + this.groups = groups; + this.scaling_groups = scaling_groups; + this.workflows = workflows; + this.tenant_name = tenant_name; + } + + public static final class Inputs { + public final String openstack_auth_url; + public final String external_network_name; + public final String openstack_username; + public final String instance_image; + public final String keypair_name; + public final String instance_name; + public final String keypair_private_key_path; + public final String openstack_tenant_name; + public final String subnet_name; + public final String openstack_region; + public final String openstack_password; + public final String ssh_username; + public final String instance_flavor; + public final String network_name; + + @JsonCreator + public Inputs(@JsonProperty("openstack_auth_url") String openstack_auth_url, + @JsonProperty("external_network_name") String external_network_name, + @JsonProperty("openstack_username") String openstack_username, + @JsonProperty("instance_image") String instance_image, + @JsonProperty("keypair_name") String keypair_name, @JsonProperty("instance_name") String instance_name, + @JsonProperty("keypair_private_key_path") String keypair_private_key_path, + @JsonProperty("openstack_tenant_name") String openstack_tenant_name, + @JsonProperty("subnet_name") String subnet_name, + @JsonProperty("openstack_region") String openstack_region, + @JsonProperty("openstack_password") String openstack_password, + @JsonProperty("ssh_username") String ssh_username, + @JsonProperty("instance_flavor") String instance_flavor, + @JsonProperty("network_name") String network_name) { + + this.openstack_auth_url = openstack_auth_url; + this.external_network_name = external_network_name; + this.openstack_username = openstack_username; + this.instance_image = instance_image; + this.keypair_name = keypair_name; + this.instance_name = instance_name; + this.keypair_private_key_path = keypair_private_key_path; + this.openstack_tenant_name = openstack_tenant_name; + this.subnet_name = subnet_name; + this.openstack_region = openstack_region; + this.openstack_password = openstack_password; + this.ssh_username = ssh_username; + this.instance_flavor = instance_flavor; + this.network_name = network_name; + } + } + + public static final class Workflow { + public final String name; + public final String created_at; + public final Map<String,Parameter> parameters; + + @JsonCreator + public Workflow(@JsonProperty("name") String name, @JsonProperty("created_at") String created_at, + @JsonProperty("parameters") Map<String,Parameter> parameters) { + this.name = name; + this.created_at = created_at; + this.parameters = parameters; + } + } + + public static final class Parameter { + + @JsonProperty("default") + public final Object xdefault; + public final String description; + + @JsonCreator + public Parameter(@JsonProperty("default") Object xdefault, @JsonProperty("description") String description) { + this.xdefault = xdefault; + this.description = description; + } + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((tenant_name == null) ? 0 : tenant_name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CloudifyDeployment other = (CloudifyDeployment) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (tenant_name == null) { + if (other.tenant_name != null) + return false; + } else if (!tenant_name.equals(other.tenant_name)) + return false; + return true; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployedTenant.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentExt.java index 624c41a..3f906d1 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployedTenant.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentExt.java @@ -19,25 +19,28 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; +import org.onap.ccsdk.dashboard.model.ECTransportModel; -public class CloudifyDeployedTenant extends ECTransportModel { +public class CloudifyDeploymentExt extends ECTransportModel { /** A unique identifier for the deployment. */ - public final String id; - /** tenant where the deployment was done */ - public final String tenant_name; - /** The id of the blueprint the deployment is based on. */ - public final String blueprint_id; - - @JsonCreator - public CloudifyDeployedTenant(@JsonProperty("id") String id, @JsonProperty("blueprint_id") String blueprint_id, - @JsonProperty("tenant_name") String tenant_name) { + public String id; + /** blueprint ID for the deployment */ + public String bp_id; + public String tenant; + /** latest execution object */ + public CloudifyExecution lastExecution; + /** true if helm plugin is used */ + public Boolean isHelm; + /** true if helm status is enabled */ + public Boolean helmStatus; + + public CloudifyDeploymentExt(String id, String bp_id, String tenant) { + super(); this.id = id; - this.blueprint_id = blueprint_id; - this.tenant_name = tenant_name; + this.bp_id = bp_id; + this.tenant = tenant; } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/EcdAppComponent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentHelm.java index 28eb6f0..9e4d122 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/EcdAppComponent.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentHelm.java @@ -2,7 +2,7 @@ * =============LICENSE_START========================================================= * * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,25 +19,24 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; -import java.util.List; +package org.onap.ccsdk.dashboard.model.cloudify; -import org.onap.ccsdk.dashboard.domain.EcdComponent; +public class CloudifyDeploymentHelm { -public class EcdAppComponent { - - public String app; - - public List<EcdComponent> comps; - - /* - * @JsonCreator public EcdAppComponent(@JsonProperty("app") String app, - * - * @JsonProperty("comps") List<EcdComponent> comps) { this(app, comps); } - */ - public EcdAppComponent(String app, List<EcdComponent> comps) { - this.app = app; - this.comps = comps; + /** A unique identifier for the deployment. */ + public String id; + /** true if helm plugin is used */ + public Boolean isHelm; + /** true if helm status is enabled */ + public Boolean helmStatus; + + public CloudifyDeploymentHelm(String id, Boolean isHelm, Boolean helmStatus) { + super(); + this.id = id; + this.isHelm = isHelm; + this.helmStatus = helmStatus; } + + } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentList.java index 5a30163..4f83648 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentList.java @@ -19,44 +19,46 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -public class CloudifySecretList extends ECTransportModel { - public final List<CloudifySecret> items; - public final Metadata metadata; +public class CloudifyDeploymentList extends ECTransportModel { + + public final List<CloudifyDeployment> items; + public final Metadata metadata; @JsonCreator - public CloudifySecretList(@JsonProperty("items") List<CloudifySecret> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } + public CloudifyDeploymentList(@JsonProperty("items") List<CloudifyDeployment> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } - public static final class Metadata { - public final Pagination pagination; + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } + } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyErrorCause.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyErrorCause.java index bca8fb3..8f6599c 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyErrorCause.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyErrorCause.java @@ -19,33 +19,37 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyErrorCause extends ECTransportModel { - /** Error message */ - public final String message; - - /** Stack trace at the point where the exception was raised */ - public final String traceback; - - /** Exception type */ - public final String type; - - @JsonCreator - public CloudifyErrorCause(@JsonProperty("message") String message, @JsonProperty("traceback") String traceback, - @JsonProperty("type") String type) { - - this.message = message; - this.traceback = traceback; - this.type = type; - } - - @Override - public String toString() { - return "CloudifyErrorCause [message=" + message + ", traceback=" + traceback + ", type=" + type + "]"; - } + /** Error message */ + public final String message; + + /** Stack trace at the point where the exception was raised */ + public final String traceback; + + /** Exception type */ + public final String type; + + @JsonCreator + public CloudifyErrorCause( + @JsonProperty("message") String message, + @JsonProperty("traceback") String traceback, + @JsonProperty("type") String type) { + + this.message = message; + this.traceback = traceback; + this.type = type; + } + + @Override + public String toString() { + return "CloudifyErrorCause [message=" + message + ", traceback=" + traceback + ", type=" + type + "]"; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEvent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEvent.java new file mode 100644 index 0000000..a6593ab --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEvent.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.cloudify; + +import java.util.LinkedList; +import java.util.List; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CloudifyEvent extends ECTransportModel { + + /** The id of the blueprint the execution is in the context of. */ + public final String blueprint_id; + /** The id of the deployment the execution is in the context of. */ + public final String deployment_id; + /** List of errors that happened while executing a given task */ + public final List<CloudifyErrorCause> error_causes; + /** The executions status. */ + public final String event_type; + /** The time the execution was queued at. */ + public final String execution_id; + /** log level */ + public final String level; + /** logger id */ + public final String logger; + /** message text */ + public final String message; + /** node instance id */ + public final String node_instance_id; + /** node name */ + public final String node_name; + /** Operation path */ + public final String operation; + /** time at which the event occurred on the executing machine */ + public final String reported_timestamp; + /** time at which the event was logged on the management machine */ + public final String timestamp; + /** resource is a cloudify_event or a cloudify_log */ + public final String type; + /** The id/name of the workflow the execution is of. */ + public final String workflow_id; + + @JsonCreator + public CloudifyEvent( + @JsonProperty("blueprint_id") String blueprint_id, + @JsonProperty("deployment_id") String deployment_id, + @JsonProperty("error_causes") List<CloudifyErrorCause> error_causes, + @JsonProperty("event_type") String event_type, + @JsonProperty("execution_id") String execution_id, + @JsonProperty("level") String level, + @JsonProperty("logger") String logger, + @JsonProperty("message") String message, + @JsonProperty("node_instance_id") String node_instance_id, + @JsonProperty("node_name") String node_name, + @JsonProperty("operation") String operation, + @JsonProperty("reported_timestamp") String reported_timestamp, + @JsonProperty("timestamp") String timestamp, + @JsonProperty("type") String type, + @JsonProperty("workflow_id") String workflow_id) { + + this.blueprint_id = blueprint_id; + this.deployment_id = deployment_id; + this.error_causes = (error_causes == null) ? new LinkedList<CloudifyErrorCause> () : error_causes; + this.event_type = event_type; + this.execution_id = execution_id; + this.level = level; + this.logger = logger; + this.message = message; + this.node_instance_id = node_instance_id; + this.node_name = node_name; + this.operation = operation; + this.reported_timestamp = reported_timestamp; + this.timestamp = timestamp; + this.type = type; + this.workflow_id = workflow_id; + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEventList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEventList.java index f5d596f..dc0052b 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEventList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEventList.java @@ -19,45 +19,45 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyEventList extends ECTransportModel { - public final List<CloudifyEvent> items; - public final Metadata metadata; + public final List<CloudifyEvent> items; + public final Metadata metadata; @JsonCreator - public CloudifyEventList(@JsonProperty("items") List<CloudifyEvent> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } + public CloudifyEventList(@JsonProperty("items") List<CloudifyEvent> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } - public static final class Metadata { - public final Pagination pagination; + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecution.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecution.java new file mode 100644 index 0000000..366a43d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecution.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.cloudify; + +import java.util.Map; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Model with fields only for the top-level attributes. All complex child + * structures are represented simply as generic collections. + */ +public final class CloudifyExecution extends ECTransportModel { + + /** A unique identifier for the execution. */ + public final String id; + /** The executions status. */ + public final String status; + /** The time the execution was queued at. */ + public final String created_at; + /** The time the execution ended in successful, failed or cancelled state */ + public final String ended_at; + /** The id/name of the workflow the execution is of. */ + public final String workflow_id; + /** true if the execution is of a system workflow. */ + public final Boolean is_system_workflow; + /** The id of the blueprint the execution is in the context of. */ + public final String blueprint_id; + /** The id of the deployment the execution is in the context of. */ + public final String deployment_id; + /** The tenant used to deploy */ + public final String tenant_name; + /** The execution’s error message on execution failure. */ + public final String error; + /** A dict of the workflow parameters passed when starting the execution. */ + public final Map<String, Object> parameters; + + @JsonCreator + public CloudifyExecution(@JsonProperty("status") String status, + @JsonProperty("created_at") String created_at, + @JsonProperty("ended_at") String ended_at, + @JsonProperty("workflow_id") String workflow_id, + @JsonProperty("is_system_workflow") Boolean is_system_workflow, + @JsonProperty("blueprint_id") String blueprint_id, + @JsonProperty("deployment_id") String deployment_id, + @JsonProperty("tenant_name") String tenant_name, + @JsonProperty("error") String error, @JsonProperty("id") String id, + @JsonProperty("parameters") Map<String, Object> parameters) { + + this.status = status; + this.created_at = created_at; + this.ended_at = ended_at; + this.workflow_id = workflow_id; + this.is_system_workflow = is_system_workflow; + this.blueprint_id = blueprint_id; + this.deployment_id = deployment_id; + this.tenant_name = tenant_name; + this.error = error; + this.id = id; + this.parameters = parameters; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionList.java index c53b314..9592179 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionList.java @@ -19,46 +19,46 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyExecutionList extends ECTransportModel { - - public final List<CloudifyExecution> items; - public final Metadata metadata; + + public final List<CloudifyExecution> items; + public final Metadata metadata; @JsonCreator - public CloudifyExecutionList(@JsonProperty("items") List<CloudifyExecution> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } + public CloudifyExecutionList(@JsonProperty("items") List<CloudifyExecution> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } - public static final class Metadata { - public final Pagination pagination; + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } - + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } + } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionRequest.java new file mode 100644 index 0000000..41b034c --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionRequest.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.cloudify; + +import java.util.Map; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CloudifyExecutionRequest extends ECTransportModel { + + /** A unique identifier for the deployment. */ + public String deployment_id; + /** A unique identifier for the workflow */ + public String workflow_id; + public Boolean allow_custom_parameters; + public Boolean force; + public String tenant; + /** Parameters: retrieve using the GET /deployments */ + public Map<String, Object> parameters; + + public String getDeployment_id() { + return deployment_id; + } + + public String getWorkflow_id() { + return workflow_id; + } + + public Boolean getAllow_custom_parameters() { + return allow_custom_parameters; + } + + public Boolean getForce() { + return force; + } + + public String getTenant() { + return tenant; + } + + public Map<String, Object> getParameters() { + return parameters; + } + + public void setDeployment_id(String deployment_id) { + this.deployment_id = deployment_id; + } + + public void setWorkflow_id(String workflow_id) { + this.workflow_id = workflow_id; + } + + public void setAllow_custom_parameters(Boolean allow_custom_parameters) { + this.allow_custom_parameters = allow_custom_parameters; + } + + public void setForce(Boolean force) { + this.force = force; + } + + public void setTenant(String tenant) { + this.tenant = tenant; + } + + public void setParameters(Map<String, Object> parameters) { + this.parameters = parameters; + } + + @JsonCreator + public CloudifyExecutionRequest(@JsonProperty("deployment_id") String deployment_id, + @JsonProperty("workflow_id") String workflow_id, + @JsonProperty("allow_custom_parameters") Boolean allowCustomParameters, + @JsonProperty("force") Boolean force, + @JsonProperty("tenant") String tenant, + @JsonProperty("parameters") Map<String, Object> parameters) { + this.deployment_id = deployment_id; + this.workflow_id = workflow_id; + this.allow_custom_parameters = allowCustomParameters; + this.force = force; + this.tenant = tenant; + this.parameters = parameters; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeId.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeId.java index 6352f40..da517b1 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeId.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeId.java @@ -19,18 +19,20 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyNodeId extends ECTransportModel { - /** The id of the node */ - public final String id; - - @JsonCreator - public CloudifyNodeId(@JsonProperty("id") String id) { - this.id = id; - } + /** The id of the node */ + public final String id; + + @JsonCreator + public CloudifyNodeId(@JsonProperty("id") String id) { + this.id = id; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeIdList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeIdList.java index f384a6f..53bde24 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeIdList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeIdList.java @@ -19,7 +19,7 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; @@ -28,36 +28,34 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyNodeIdList { - public final List<CloudifyNodeId> items; - public final Metadata metadata; + public final List<CloudifyNodeId> items; + public final Metadata metadata; @JsonCreator - public CloudifyNodeIdList(@JsonProperty("items") List<CloudifyNodeId> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } - - public static final class Metadata { - public final Pagination pagination; + public CloudifyNodeIdList(@JsonProperty("items") List<CloudifyNodeId> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } + + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstance.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstance.java index c89079d..2b17e77 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstance.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstance.java @@ -19,26 +19,27 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; -import java.util.List; import java.util.Map; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyNodeInstance extends ECTransportModel { - /** The id of the node instance. */ - public final String id; - - /** The runtime properties of the node instance. */ - public final Map<String, Object> runtime_properties; + /** The id of the node instance. */ + public final String id; + + /** The runtime properties of the node instance. */ + public final Map<String, Object> runtime_properties; - @JsonCreator - public CloudifyNodeInstance(@JsonProperty("id") String id, - @JsonProperty("runtime_properties") Map<String, Object> runtime_properties) { - this.id = id; - this.runtime_properties = runtime_properties; - } + @JsonCreator + public CloudifyNodeInstance(@JsonProperty("id") String id, + @JsonProperty("runtime_properties") Map<String, Object> runtime_properties) { + this.id = id; + this.runtime_properties = runtime_properties; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintContent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceId.java index ca24849..1775b65 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintContent.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceId.java @@ -19,25 +19,25 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; /** - * Trivial wrapper for Blueprint YAML content. + * Model with fields only for the top-level attributes. All complex child + * structures are represented as generic collections. */ -public final class CloudifyBlueprintContent extends ECTransportModel { - - /** A unique identifier for the blueprint. */ - public final String id; - /** The content of the blueprint as YAML */ - public final String content; +public final class CloudifyNodeInstanceId extends ECTransportModel { - @JsonCreator - public CloudifyBlueprintContent(@JsonProperty("id") String id, @JsonProperty("content") String content) { - this.id = id; - this.content = content; - } + /** The id of the node instance. */ + public final String id; + + @JsonCreator + public CloudifyNodeInstanceId(@JsonProperty("id") String id) { + this.id = id; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceIdList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceIdList.java index 423abe2..1909bf6 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceIdList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceIdList.java @@ -1,4 +1,3 @@ - /******************************************************************************* * =============LICENSE_START========================================================= * @@ -20,46 +19,46 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyNodeInstanceIdList extends ECTransportModel { - - public final List<CloudifyNodeInstanceId> items; - public final Metadata metadata; + + public final List<CloudifyNodeInstanceId> items; + public final Metadata metadata; @JsonCreator - public CloudifyNodeInstanceIdList(@JsonProperty("items") List<CloudifyNodeInstanceId> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } - - public static final class Metadata { - public final Pagination pagination; + public CloudifyNodeInstanceIdList(@JsonProperty("items") List<CloudifyNodeInstanceId> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } + + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } - + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } + } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceList.java index 1813e5c..adf005c 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceList.java @@ -19,45 +19,45 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyNodeInstanceList extends ECTransportModel { - public final List<CloudifyNodeInstance> items; - public final Metadata metadata; + public final List<CloudifyNodeInstance> items; + public final Metadata metadata; @JsonCreator - public CloudifyNodeInstanceList(@JsonProperty("items") List<CloudifyNodeInstance> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } - - public static final class Metadata { - public final Pagination pagination; + public CloudifyNodeInstanceList(@JsonProperty("items") List<CloudifyNodeInstance> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } + + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintUpload.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyPlugin.java index a77e974..c79126c 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintUpload.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyPlugin.java @@ -19,37 +19,40 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -/** - * Model for message POST-ed to controller to create a Cloudify Blueprint: - * - * <pre> - { - "blueprint_id" : "blueprint-id", - "blueprint_filename" : "name.yaml", - "zip_url" : "url" - } - * </pre> +public class CloudifyPlugin { +/* + * "uploaded_at": "2020-04-29T14:46:59.628Z", + "package_version": "1.7.2", + "package_name": "k8splugin", + "distribution": "centos", + "supported_platform": "linux_x86_64", */ -public final class CloudifyBlueprintUpload extends ECTransportModel { - - /** A unique identifier for the blueprint. */ - public final String blueprint_id; - /** The blueprint’s main file name. */ - public final String blueprint_filename; - /** The zip file URL. */ - public final String zip_url; - + public final String package_name; + + public final String package_version; + + public final String supported_platform; + + public final String distribution; + + public final String uploaded_at; + @JsonCreator - public CloudifyBlueprintUpload(@JsonProperty("blueprint_id") String blueprint_id, - @JsonProperty("blueprint_filename") String blueprint_filename, @JsonProperty("zip_url") String zip_url) { - this.blueprint_id = blueprint_id; - this.blueprint_filename = blueprint_filename; - this.zip_url = zip_url; + public CloudifyPlugin( + @JsonProperty("package_name") String package_name, + @JsonProperty("package_version") String package_version, + @JsonProperty("supported_platform") String supported_platform, + @JsonProperty("distribution") String distribution, + @JsonProperty("uploaded_at") String uploaded_at) { + this.package_name = package_name; + this.package_version = package_version; + this.supported_platform = supported_platform; + this.distribution = distribution; + this.uploaded_at = uploaded_at; } - } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyPluginList.java index 4dfef1e..8930fd4 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyPluginList.java @@ -19,21 +19,21 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -public class CloudifyDeploymentList extends ECTransportModel { - - public final List<CloudifyDeployment> items; +public class CloudifyPluginList extends ECTransportModel { + public final List<CloudifyPlugin> items; public final Metadata metadata; @JsonCreator - public CloudifyDeploymentList(@JsonProperty("items") List<CloudifyDeployment> items, - @JsonProperty("metadata") Metadata metadata) { + public CloudifyPluginList(@JsonProperty("items") List<CloudifyPlugin> items, @JsonProperty("metadata") Metadata metadata){ this.items = items; this.metadata = metadata; } @@ -42,23 +42,21 @@ public class CloudifyDeploymentList extends ECTransportModel { public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - + public static final class Pagination { public final long total; public final long offset; public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ this.total = total; this.offset = offset; this.size = size; } } } - } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifySecret.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifySecret.java new file mode 100644 index 0000000..d087ce3 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifySecret.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.cloudify; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CloudifySecret extends ECTransportModel { + + /** The time when the secret was created */ + public final String created_at; + /** The secret’s key, unique per tenant */ + public final String key; + /** The time the secret was last updated at */ + public final String updated_at; + /** The secret’s value */ + public final String value; + /** Defines who can see the secret. Can be private, tenant or global*/ + public final String visibility; + /** Determines who can see the value of the secret. */ + public final String is_hidden_value; + + public final String tenant_name; + + public final String resource_availability; + + @JsonCreator + public CloudifySecret( + @JsonProperty("created_at") String created_at, + @JsonProperty("key") String key, + @JsonProperty("updated_at") String updated_at, + @JsonProperty("value") String value, + @JsonProperty("visibility") String visibility, + @JsonProperty("is_hidden_value") String is_hidden_value, + @JsonProperty("tenant_name") String tenant_name, + @JsonProperty("resource_availability") String resource_availability) { + this.created_at = created_at; + this.key = key; + this.updated_at = updated_at; + this.value = value; + this.visibility = visibility; + this.is_hidden_value = is_hidden_value; + this.tenant_name = tenant_name; + this.resource_availability = resource_availability; + } + + /** + * @return the key + */ + public String getKey() { + return key; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyTenant.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyTenant.java index b885936..53f5149 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyTenant.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyTenant.java @@ -19,25 +19,29 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; + + +import org.onap.ccsdk.dashboard.model.ECTransportModel; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyTenant extends ECTransportModel { - /** A unique identifier for the tenant */ - public final String id; - /** The tenant's name. */ - public final String name; - /** tenant display name */ - public String dName; - - @JsonCreator - public CloudifyTenant(@JsonProperty("name") String name, @JsonProperty("dName") String dName, - @JsonProperty("id") String id) { - this.name = name; - this.dName = dName; - this.id = id; - } + /** A unique identifier for the tenant */ + public final String id; + /** The tenant's name. */ + public final String name; + /** tenant display name */ + public String dName; + + @JsonCreator + public CloudifyTenant(@JsonProperty("name") String name, + @JsonProperty("dName") String dName, + @JsonProperty("id") String id) { + this.name = name; + this.dName = dName; + this.id = id; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyTenantList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyTenantList.java index c7f8530..4610b9e 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyTenantList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyTenantList.java @@ -19,44 +19,44 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.cloudify; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class CloudifyTenantList extends ECTransportModel { - public final List<CloudifyTenant> items; - public final Metadata metadata; + public final List<CloudifyTenant> items; + public final Metadata metadata; @JsonCreator - public CloudifyTenantList(@JsonProperty("items") List<CloudifyTenant> items, - @JsonProperty("metadata") Metadata metadata) { - this.items = items; - this.metadata = metadata; - } - - public static final class Metadata { - public final Pagination pagination; + public CloudifyTenantList(@JsonProperty("items") List<CloudifyTenant> items, @JsonProperty("metadata") Metadata metadata){ + this.items = items; + this.metadata = metadata; + } + + public static final class Metadata { + public final Pagination pagination; @JsonCreator - public Metadata(@JsonProperty("pagination") Pagination pagination) { + public Metadata(@JsonProperty("pagination") Pagination pagination){ this.pagination = pagination; } - - public static final class Pagination { - public final long total; - public final long offset; - public final long size; + + public static final class Pagination { + public final long total; + public final long offset; + public final long size; @JsonCreator - public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, - @JsonProperty("size") long size) { - this.total = total; - this.offset = offset; - this.size = size; - } - } - } + public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceGroupByResults.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/ServiceRefCfyList.java index d8e6e8b..10c9bea 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceGroupByResults.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/ServiceRefCfyList.java @@ -19,24 +19,31 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model.inventory; +package org.onap.ccsdk.dashboard.model.cloudify; -import java.util.Set; +import java.util.Collection; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -public class ServiceGroupByResults { +public class ServiceRefCfyList { + /** Number of Service objects */ + public final Integer totalCount; + /** Collection containing all of the returned Service objects */ + public final Collection<CloudifyDeployedTenant> items; - /** Property name of the service that the group by operation was performed on */ - public String propertyName; - /** Set of Service objects that have the aforementioned propertyName */ - public Set<InventoryProperty> propertyValues; + /** + * @return the items + */ + public Collection<CloudifyDeployedTenant> getItems() { + return items; + } @JsonCreator - public ServiceGroupByResults(@JsonProperty("propertyName") String propertyName, - @JsonProperty("propertyValues") Set<InventoryProperty> propertyValues) { - this.propertyName = propertyName; - this.propertyValues = propertyValues; + public ServiceRefCfyList( + @JsonProperty("items") Collection<CloudifyDeployedTenant> items, + @JsonProperty("totalCount") Integer totalCount) { + this.items = items; + this.totalCount = totalCount; } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulDatacenter.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDatacenter.java index 1e57b12..e95cdb1 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulDatacenter.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDatacenter.java @@ -19,7 +19,9 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.consul; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDeploymentHealth.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDeploymentHealth.java new file mode 100644 index 0000000..6837b8d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDeploymentHealth.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.consul; + +public class ConsulDeploymentHealth { + + private final String node; + private final String checkID; + private final String name; + private final String status; + private final String serviceID; + private final String serviceName; + + private ConsulDeploymentHealth(String node, String checkID, String name, String status, + String serviceID, String serviceName) { + this.node = node; + this.checkID = checkID; + this.name = name; + this.status = status; + this.serviceID = serviceID; + this.serviceName = serviceName; + } + + public String getNode() { + return node; + } + + public String getCheckID() { + return checkID; + } + + public String getName() { + return name; + } + + public String getStatus() { + return status; + } + + public String getServiceID() { + return serviceID; + } + + public String getServiceName() { + return serviceName; + } + + public static class Builder { + private final String node; + private final String checkID; + private final String name; + private final String status; + private final String serviceID; + private final String serviceName; + + public Builder(ConsulServiceHealth input) { + this.node = input.node; + this.checkID = input.checkID; + this.name = input.name; + this.status = input.status; + this.serviceID = input.serviceID; + this.serviceName = input.serviceName; + } + + public ConsulDeploymentHealth build() { + return new ConsulDeploymentHealth(node, checkID, name,status, serviceID, serviceName); + } + + public String getNode() { + return node; + } + + public String getCheckID() { + return checkID; + } + + public String getName() { + return name; + } + + public String getStatus() { + return status; + } + + public String getServiceID() { + return serviceID; + } + + public String getServiceName() { + return serviceName; + } + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulHealthServiceRegistration.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulHealthServiceRegistration.java index 5612b6d..76f9491 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulHealthServiceRegistration.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulHealthServiceRegistration.java @@ -19,10 +19,12 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.consul; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulNodeInfo.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulNodeInfo.java index 7122a52..3cbf3e0 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulNodeInfo.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulNodeInfo.java @@ -19,10 +19,12 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.consul; import java.util.Map; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceCatalogItem.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceCatalogItem.java new file mode 100644 index 0000000..a5bfc3d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceCatalogItem.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.consul; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ConsulServiceCatalogItem { + + public final String node; + public final String address; + public final String datacenter; + public final String serviceName; + public final String serviceAddress; + public final String servicePort; + + @JsonCreator + public ConsulServiceCatalogItem(@JsonProperty("Node") String node, @JsonProperty("Address") String address, + @JsonProperty("Datacenter") String datacenter, @JsonProperty("ServiceName") String serviceName, + @JsonProperty("ServiceAddress") String serviceAddress, @JsonProperty("ServicePort") String servicePort ) { + this.node = node; + this.address = address; + this.datacenter = datacenter; + this.serviceName = serviceName; + this.serviceAddress = serviceAddress; + this.servicePort = servicePort; + } + + public String getNode() { + return node; + } + + public String getAddress() { + return address; + } + + public String getDatacenter() { + return datacenter; + } + + public String getServiceName() { + return serviceName; + } + + public String getServiceAddress() { + return serviceAddress; + } + + public String getServicePort() { + return servicePort; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealth.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceHealth.java index 5f3876a..1c0cb35 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealth.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceHealth.java @@ -19,7 +19,9 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.consul; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -53,6 +55,8 @@ public final class ConsulServiceHealth extends ECTransportModel { public final String output; public final String serviceID; public final String serviceName; + public final String[] serviceTags; + public String tenant; public final int createIndex; public final int modifyIndex; @@ -61,7 +65,7 @@ public final class ConsulServiceHealth extends ECTransportModel { @JsonProperty("Name") String name, @JsonProperty("Status") String status, @JsonProperty("Notes") String notes, @JsonProperty("Output") String output, @JsonProperty("ServiceID") String serviceID, @JsonProperty("ServiceName") String serviceName, - @JsonProperty("CreateIndex") int createIndex, @JsonProperty("ModifyIndex") int modifyIndex) { + @JsonProperty("ServiceTags") String[] serviceTags, @JsonProperty("CreateIndex") int createIndex, @JsonProperty("ModifyIndex") int modifyIndex) { this.node = node; this.checkID = checkID; this.name = name; @@ -70,8 +74,28 @@ public final class ConsulServiceHealth extends ECTransportModel { this.output = output; this.serviceID = serviceID; this.serviceName = serviceName; + this.serviceTags = serviceTags; this.createIndex = createIndex; this.modifyIndex = modifyIndex; + ConstructTenant(); + } + + /* + * Search the service tags to find and + * construct cfy tenant + */ + private void ConstructTenant() { + String tenantString = ""; + for (String tag : serviceTags) { + if (tag.contains("cfytenantname=")) { + tenantString = tag; + break; + } + } + if (!tenantString.equals("")) + tenant = tenantString.substring(tenantString.indexOf("=") + 1); + else + tenant = ""; } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealthHistory.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceHealthHistory.java index 42e1fd2..a3f0cf9 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealthHistory.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceHealthHistory.java @@ -19,7 +19,9 @@ * * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.consul; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceInfo.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceInfo.java index bb04a66..7f34bdb 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceInfo.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceInfo.java @@ -20,10 +20,12 @@ * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; +package org.onap.ccsdk.dashboard.model.consul; import java.util.List; +import org.onap.ccsdk.dashboard.model.ECTransportModel; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentInput.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentInput.java index 7e93d9c..33dfb6a 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentInput.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentInput.java @@ -21,6 +21,8 @@ *******************************************************************************/ package org.onap.ccsdk.dashboard.model.deploymenthandler; +import java.util.Collection; +import java.util.LinkedList; import java.util.Map; import java.util.Optional; @@ -77,11 +79,32 @@ public class DeploymentInput { */ private final Map<String, Object> inputs; + private final Collection<String> reinstall_list; + + private final boolean skip_install; + + private final boolean skip_uninstall; + + private final boolean skip_reinstall; + + private final boolean force; + + private final boolean ignore_failure; + + private final boolean install_first; + @JsonCreator public DeploymentInput(@JsonProperty("component") String component, @JsonProperty("tag") String tag, @JsonProperty("blueprintName") String blueprintName, @JsonProperty("blueprintVersion") Integer blueprintVersion, @JsonProperty("blueprintId") String blueprintId, - @JsonProperty("inputs") Map<String, Object> inputs, @JsonProperty("tenant") String tenant) { + @JsonProperty("inputs") Map<String, Object> inputs, @JsonProperty("tenant") String tenant, + @JsonProperty("reinstall_list") Collection<String> reinstallList, + @JsonProperty("skip_install") boolean skipInstall, + @JsonProperty("skip_uninstall") boolean skipUninstall, + @JsonProperty("skip_reinstall") boolean skipReinstall, + @JsonProperty("force") boolean force, + @JsonProperty("ignore_failure") boolean ignoreFailure, + @JsonProperty("install_first") boolean installFirst) { this.component = component; this.tag = tag; this.blueprintName = blueprintName; @@ -89,6 +112,13 @@ public class DeploymentInput { this.blueprintId = Optional.ofNullable(blueprintId); this.inputs = inputs; this.tenant = tenant; + this.reinstall_list = (reinstallList == null) ? new LinkedList<String>() : reinstallList; + this.skip_install = skipInstall; + this.skip_uninstall = skipUninstall; + this.skip_reinstall = skipReinstall; + this.force = force; + this.ignore_failure = ignoreFailure; + this.install_first = installFirst; } public String getBlueprintName() { @@ -118,4 +148,32 @@ public class DeploymentInput { public Optional<String> getBlueprintId() { return blueprintId; } + + public Collection<String> getReinstall_list() { + return reinstall_list; + } + + public boolean isSkip_install() { + return skip_install; + } + + public boolean isSkip_uninstall() { + return skip_uninstall; + } + + public boolean isSkip_reinstall() { + return skip_reinstall; + } + + public boolean isForce() { + return force; + } + + public boolean isIgnore_failure() { + return ignore_failure; + } + + public boolean isInstall_first() { + return install_first; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequest.java index b0ac9e9..94bb064 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequest.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequest.java @@ -57,10 +57,10 @@ public class DeploymentRequest { * deployed. */ private final Map<String, Object> inputs; - + @JsonCreator public DeploymentRequest(@JsonProperty("serviceTypeId") String serviceTypeId, - @JsonProperty("inputs") Map<String, Object> inputs) { + @JsonProperty("inputs") Map<String, Object> inputs ) { this.serviceTypeId = serviceTypeId; this.inputs = inputs; } @@ -72,4 +72,5 @@ public class DeploymentRequest { public Map<String, Object> getInputs() { return this.inputs; } + } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequestObject.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequestObject.java index ae229b2..0bb6f74 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequestObject.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequestObject.java @@ -21,7 +21,11 @@ *******************************************************************************/ package org.onap.ccsdk.dashboard.model.deploymenthandler; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; import java.util.Map; +import java.util.Optional; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -69,15 +73,60 @@ public class DeploymentRequestObject { */ private final Map<String, Object> inputs; + private final Collection<String> reinstall_list; + + private final boolean skip_install; + + private final boolean skip_uninstall; + + private final boolean skip_reinstall; + + private final boolean force; + + private final boolean ignore_failure; + + private final boolean install_first; + @JsonCreator public DeploymentRequestObject(@JsonProperty("deploymentId") String deploymentId, @JsonProperty("serviceTypeId") String serviceTypeId, @JsonProperty("inputs") Map<String, Object> inputs, - @JsonProperty("tenant") String tenant, @JsonProperty("method") String method) { + @JsonProperty("tenant") String tenant, @JsonProperty("method") String method, + @JsonProperty("reinstall_list") Collection<String> reinstallList, + @JsonProperty("skip_install") boolean skipInstall, + @JsonProperty("skip_uninstall") boolean skipUninstall, + @JsonProperty("skip_reinstall") boolean skipReinstall, + @JsonProperty("force") boolean force, + @JsonProperty("ignore_failure") boolean ignoreFailure, + @JsonProperty("install_first") boolean installFirst) { this.deploymentId = deploymentId; this.serviceTypeId = serviceTypeId; this.inputs = inputs; this.tenant = tenant; this.method = method; + this.reinstall_list = (reinstallList == null) ? new LinkedList<String>() : reinstallList; + this.skip_install = skipInstall; + this.skip_uninstall = skipUninstall; + this.skip_reinstall = skipReinstall; + this.force = force; + this.ignore_failure = ignoreFailure; + this.install_first = installFirst; + } + + public DeploymentRequestObject(String deploymentId, String serviceTypeId, String method, + Map<String, Object> inputs, String tenant) { + super(); + this.deploymentId = deploymentId; + this.method = method; + this.serviceTypeId = serviceTypeId; + this.tenant = tenant; + this.inputs = inputs; + this.reinstall_list = null; + this.skip_install = true; + this.skip_uninstall = true; + this.skip_reinstall = true; + this.force = false; + this.ignore_failure = true; + this.install_first = false; } public String getDeploymentId() { @@ -99,4 +148,32 @@ public class DeploymentRequestObject { public String getMethod() { return method; } + + public Collection<String> getReinstall_list() { + return reinstall_list; + } + + public boolean isSkip_install() { + return skip_install; + } + + public boolean isSkip_uninstall() { + return skip_uninstall; + } + + public boolean isSkip_reinstall() { + return skip_reinstall; + } + + public boolean isForce() { + return force; + } + + public boolean isIgnore_failure() { + return ignore_failure; + } + + public boolean isInstall_first() { + return install_first; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/InventoryDeploymentRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/InventoryDeploymentRequest.java deleted file mode 100644 index 173744a..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/InventoryDeploymentRequest.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model.deploymenthandler; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Model for message used by the controller to create a DeploymentRequest for - * the Deployment Handler API. - * - * <pre> - { - "deploymentId" : "deploymentId", - "body" : - { - "serviceTypeId" : "serviceTypeId", - "inputs" : - { - "input1" : "parameter1" - "input2" : "parameter2" - ... - "inputn" : "parametern" - } - } - } - * </pre> - */ -public final class InventoryDeploymentRequest { - - /** Unique deployment identifier assigned by the API client. */ - private final String deploymentId; - - /** - * The service type identifier (a unique ID assigned by DCAE inventory) for the - * service to be deployed. - */ - private final String serviceTypeId; - - /** - * Object containing inputs needed by the service blueprint to create an - * instance of the service. Content of the object depends on the service being - * deployed. - */ - private final Map<String, Object> inputs; - - @JsonCreator - public InventoryDeploymentRequest(@JsonProperty("deploymentId") String deploymentId, - @JsonProperty("serviceTypeId") String serviceTypeId, @JsonProperty("inputs") Map<String, Object> inputs) { - this.deploymentId = deploymentId; - this.serviceTypeId = serviceTypeId; - this.inputs = inputs; - } - - public String getDeploymentId() { - return this.deploymentId; - } - - public String getServiceTypeId() { - return this.serviceTypeId; - } - - public Map<String, Object> getInputs() { - return this.inputs; - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Blueprint.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Blueprint.java index 70f5fd5..184e0fb 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Blueprint.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Blueprint.java @@ -32,6 +32,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; @JsonIgnoreProperties(ignoreUnknown = true) @@ -39,6 +40,7 @@ public class Blueprint { private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory()); + static { YAML_MAPPER.registerModule(new Jdk8Module()); } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Service.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Service.java index 3631623..dc1daa7 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Service.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Service.java @@ -57,7 +57,15 @@ public class Service { private Optional<Boolean> canDeploy; /** tenant name for this service */ private String tenant; - + /** install execution workflow status */ + private String installStatus; + /** true if helm plugin is used */ + public Boolean isHelm; + /** true if helm status is enabled */ + public Boolean helmStatus; + /** Consul service health status */ + private String healthStatus; + @JsonCreator public Service(@JsonProperty("serviceId") String serviceId, @JsonProperty("selfLink") Link selfLink, @JsonProperty("created") String created, @JsonProperty("modified") String modified, @@ -165,4 +173,36 @@ public class Service { * public ServiceRef build() { return new ServiceRef(serviceId, created, * modified); } } */ + + public String getInstallStatus() { + return installStatus; + } + + public void setInstallStatus(String installStatus) { + this.installStatus = installStatus; + } + + public Boolean getIsHelm() { + return isHelm; + } + + public void setIsHelm(Boolean isHelm) { + this.isHelm = isHelm; + } + + public Boolean getHelmStatus() { + return helmStatus; + } + + public void setHelmStatus(Boolean helmStatus) { + this.helmStatus = helmStatus; + } + + public String getHealthStatus() { + return this.healthStatus; + } + + public void setHealthStatus(String healthStatus) { + this.healthStatus = healthStatus; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceComponentRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceComponentRequest.java deleted file mode 100644 index 123392b..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceComponentRequest.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model.inventory; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ServiceComponentRequest { - - /** Component ID of the Service Component */ - public String componentId; - /** Component Type of the Service Component */ - public String componentType; - /** - * Specifies the name of the underlying source service responsible for this - * component - */ - public String componentSource; - /** - * Used to determine if this component can be shared amongst different Services - */ - public Integer shareable; - - @JsonCreator - public ServiceComponentRequest(@JsonProperty("componentId") String componentId, - @JsonProperty("componentType") String componentType, - @JsonProperty("componentSource") String componentSource, @JsonProperty("shareable") Integer shareable) { - this.componentId = componentId; - this.componentType = componentType; - this.componentSource = componentSource; - this.shareable = shareable; - } - - public static ServiceComponentRequest from(ServiceComponent sc) { - return new ServiceComponentRequest(sc.componentId, sc.componentType, sc.componentSource, sc.shareable); - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRef.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRef.java index f338d28..7b70e1c 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRef.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRef.java @@ -27,21 +27,25 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class ServiceRef { /** Service ID of the Service */ - private final String serviceId; + public final String id; /** Creation date of the Service */ - private final String created; + public final String created_at; /** Last modified date of the Service */ - private final String modified; - + public final String updated_at; + public final String tenant_name = ""; + @JsonCreator - public ServiceRef(@JsonProperty("serviceId") String serviceId, @JsonProperty("created") String created, - @JsonProperty("modified") String modified) { - this.serviceId = serviceId; - this.created = created; - this.modified = modified; + public ServiceRef( + @JsonProperty("id") String serviceId, + @JsonProperty("created_at") String created, + @JsonProperty("updated_at") String modified + ) { + this.id = serviceId; + this.created_at = created; + this.updated_at = modified; } - +/* public String getServiceId() { return serviceId; } @@ -53,7 +57,7 @@ public class ServiceRef { public String getModified() { return modified; } - +*/ /* * private ServiceRef ( String serviceId, String created, String modified) { * this.serviceId = serviceId; this.created = created; this.modified = modified; diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRefList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRefList.java index d9491d9..def0e0a 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRefList.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRefList.java @@ -23,6 +23,8 @@ package org.onap.ccsdk.dashboard.model.inventory; import java.util.Collection; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -30,6 +32,7 @@ public class ServiceRefList { /** Number of Service objects */ public final Integer totalCount; /** Collection containing all of the returned Service objects */ + //public final Collection<CloudifyDeployedTenant> items; public final Collection<ServiceRef> items; @JsonCreator diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRequest.java deleted file mode 100644 index 46b3351..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRequest.java +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model.inventory; - -import java.util.ArrayList; -import java.util.Collection; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class ServiceRequest { - - /** ID of the associated service type */ - public String typeId; - /** Id of the associated VNF that this service is monitoring */ - public String vnfId; - /** The type of the associated VNF that this service is monitoring */ - public String vnfType; - /** Location identifier of the associated VNF that this service is monitoring */ - public String vnfLocation; - /** Reference to a Cloudify deployment */ - public String deploymentRef; - /** - * Collection of ServiceComponentRequest objects that this service is composed - * of - */ - public Collection<ServiceComponentRequest> components; - - @JsonCreator - public ServiceRequest(@JsonProperty("typeId") String typeId, @JsonProperty("vnfId") String vnfId, - @JsonProperty("vnfType") String vnfType, @JsonProperty("vnfLocation") String vnfLocation, - @JsonProperty("deploymentRef") String deploymentRef, - @JsonProperty("components") Collection<ServiceComponentRequest> components) { - this.typeId = typeId; - this.vnfId = vnfId; - this.vnfType = vnfType; - this.vnfLocation = vnfLocation; - this.deploymentRef = deploymentRef; - this.components = components; - } - - public static ServiceRequest from(String typeId, Service service) { - - // Convert the Collection<ServiceComponent> in service to - // Collection<ServiceComponentRequest> for serviceRequest - final Collection<ServiceComponent> serviceComponents = service.getComponents(); - final Collection<ServiceComponentRequest> serviceComponentRequests = new ArrayList<ServiceComponentRequest>(); - - if (serviceComponents != null) { - for (ServiceComponent sc : serviceComponents) { - serviceComponentRequests.add(ServiceComponentRequest.from(sc)); - } - } - - return new ServiceRequest(typeId, service.getVnfId(), service.getVnfType(), service.getVnfLocation(), - service.getDeploymentRef(), serviceComponentRequests); - } -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceType.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceType.java index 4af4cb1..f1351fc 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceType.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceType.java @@ -237,8 +237,9 @@ public class ServiceType { this.blueprintInputs = bpObj.getInputs(); this.blueprintDescription = bpObj.getDescription(); } catch (BlueprintParseException e) { -/* throw new RuntimeException( - "Error while parsing blueprint template for " + this.typeName + " " + this.typeVersion, e);*/ + //this.blueprintDescription = ""; + //throw new RuntimeException( + //"Error while parsing blueprint template for " + this.typeName + " " + this.typeVersion, e); } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeQueryParams.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeQueryParams.java index 8d98d9d..7b733ee 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeQueryParams.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeQueryParams.java @@ -33,9 +33,10 @@ public class ServiceTypeQueryParams { private final String asdcResourceId; private final String application; private final String component; + private final String owner; // Non-instantiable - private ServiceTypeQueryParams() { + private ServiceTypeQueryParams(org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary.Builder builder) { this.typeName = null; this.onlyLatest = null; this.onlyActive = null; @@ -46,11 +47,12 @@ public class ServiceTypeQueryParams { this.asdcResourceId = null; this.application = null; this.component = null; + this.owner = null; } private ServiceTypeQueryParams(String typeName, Boolean onlyLatest, Boolean onlyActive, String vnfType, String serviceId, String serviceLocation, String asdcServiceId, String asdcResourceId, String application, - String component) { + String component, String owner) { this.typeName = typeName; this.onlyLatest = onlyLatest; this.onlyActive = onlyActive; @@ -61,6 +63,7 @@ public class ServiceTypeQueryParams { this.asdcResourceId = asdcResourceId; this.application = application; this.component = component; + this.owner = owner; } public static class Builder { @@ -74,7 +77,13 @@ public class ServiceTypeQueryParams { private String asdcResourceId; private String application; private String component; + private String owner; + public Builder owner(String owner) { + this.owner = owner; + return this; + } + public Builder typeName(String typeName) { this.typeName = typeName; return this; @@ -115,9 +124,18 @@ public class ServiceTypeQueryParams { return this; } + public Builder application(String application) { + this.application = application; + return this; + } + + public Builder component(String component) { + this.component = component; + return this; + } public ServiceTypeQueryParams build() { return new ServiceTypeQueryParams(typeName, onlyLatest, onlyActive, vnfType, serviceId, serviceLocation, - asdcServiceId, asdcResourceId, application, component); + asdcServiceId, asdcResourceId, application, component, owner); } } @@ -160,4 +178,8 @@ public class ServiceTypeQueryParams { public String getComponent() { return this.component; } + + public String getOwner() { + return this.owner; + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeRequest.java index 533571b..84efcb8 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeRequest.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeRequest.java @@ -100,6 +100,16 @@ public class ServiceTypeRequest { this.asdcResourceId = asdcResourceId; this.asdcServiceURL = asdcServiceURL; } + + public ServiceTypeRequest(String owner, String typeName, Integer typeVersion, String blueprintTemplate, + String application, String component) { + this.owner = owner; + this.typeName = typeName; + this.typeVersion = typeVersion; + this.blueprintTemplate = blueprintTemplate; + this.application = application; + this.component = component; + } public static ServiceTypeRequest from(ServiceType serviceType) { return new ServiceTypeRequest(serviceType.getOwner(), serviceType.getTypeName(), serviceType.getTypeVersion(), @@ -107,7 +117,12 @@ public class ServiceTypeRequest { serviceType.getServiceIds(), serviceType.getVnfTypes(), serviceType.getServiceLocations(), serviceType.getAsdcServiceId(), serviceType.getAsdcResourceId(), serviceType.getAsdcServiceURL()); } - +/* + public static ServiceTypeRequest from(ServiceType serviceType) { + return new ServiceTypeRequest(serviceType.getOwner(), serviceType.getTypeName(), serviceType.getTypeVersion(), + serviceType.getBlueprintTemplate(), serviceType.getApplication(), serviceType.getComponent()); + } +*/ public String getBlueprintTemplate() { return this.blueprintTemplate; } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeServiceMap.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeServiceMap.java index efcdf3b..3b2f541 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeServiceMap.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeServiceMap.java @@ -2,7 +2,7 @@ * =============LICENSE_START========================================================= * * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ * limitations under the License. * ============LICENSE_END========================================================= * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. *******************************************************************************/ package org.onap.ccsdk.dashboard.model.inventory; @@ -28,11 +27,11 @@ public class ServiceTypeServiceMap { private final String serviceTypeId; - private final ServiceRefList serviceRefList; + private final Object serviceRefList; @JsonCreator public ServiceTypeServiceMap(@JsonProperty("serviceTypeId") String serviceTypeId, - @JsonProperty("created") ServiceRefList serviceRefList) { + @JsonProperty("serviceRefList") Object serviceRefList) { this.serviceTypeId = serviceTypeId; this.serviceRefList = serviceRefList; } @@ -41,7 +40,7 @@ public class ServiceTypeServiceMap { return serviceTypeId; } - public ServiceRefList getServiceRefList() { + public Object getServiceRefList() { return serviceRefList; } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummary.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummary.java new file mode 100644 index 0000000..877a8ed --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummary.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + *******************************************************************************/ + +package org.onap.ccsdk.dashboard.model.inventory; + +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.onap.ccsdk.dashboard.model.cloudify.ServiceRefCfyList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author rp5662 + * + */ +public class ServiceTypeSummary { + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "ServiceTypeSummary [owner=" + owner + ", typeName=" + typeName + ", typeVersion=" + + typeVersion + ", component=" + component + ", typeId=" + typeId + ", created=" + + created + "]"; + } + + /** Owner of the ServiceType */ + private final String owner; + + /** Name of the ServiceType */ + private final String typeName; + + /** Version number for this ServiceType */ + private final Integer typeVersion; + + /** controller application name */ + private final String application; + + /** onboarding component name */ + private final String component; + + /** Unique identifier for this ServiceType */ + private final Optional<String> typeId; + + /** Creation date of the ServiceType */ + private final Optional<String> created; + + /** internal role based setting */ + private Optional<Boolean> canDeploy; + + private ServiceRefCfyList deployments; + + private Optional<Boolean> expanded; + + @JsonCreator + public ServiceTypeSummary( + @JsonProperty("owner") String owner, + @JsonProperty("typeName") String typeName, + @JsonProperty("typeVersion") Integer typeVersion, + @JsonProperty("application") String application, + @JsonProperty("component") String component, + @JsonProperty("typeId") String typeId, + @JsonProperty("created") String created, + @JsonProperty("canDeploy") Boolean canDeploy) { + + this.owner = owner; + this.typeName = typeName; + this.typeVersion = typeVersion; + this.application = application; + this.component = component; + this.typeId = Optional.ofNullable(typeId); + this.created = Optional.ofNullable(created); + this.canDeploy = Optional.of(false); + this.expanded = Optional.of(false); + } + + private ServiceTypeSummary(Builder builder) { + this.typeName = builder.typeName; + this.owner = builder.owner; + this.typeVersion = builder.typeVersion; + this.typeId = builder.typeId; + this.application = builder.application; + this.component = builder.component; + this.created = builder.created; + this.canDeploy = builder.canDeploy; + } + + public static class Builder { + private String owner; + private String typeName; + private Integer typeVersion; + private String application; + private String component; + private Optional<String> typeId = Optional.empty(); + private Optional<String> created = Optional.empty(); + private Optional<Boolean> canDeploy = Optional.empty(); + + public Builder owner(String owner) { + this.owner = owner; + return this; + } + + public Builder typeName(String typeName) { + this.typeName = typeName; + return this; + } + + public Builder typeVersion(Integer typeVersion) { + this.typeVersion = typeVersion; + return this; + } + + public Builder application(String application) { + this.application = application; + return this; + } + + public Builder component(String component) { + this.component = component; + return this; + } + public ServiceTypeSummary build() { + return new ServiceTypeSummary(this); + } + } + + public String getTypeName() { + return typeName; + } + + public String getOwner() { + return owner; + } + + public Integer getTypeVersion() { + return typeVersion; + } + + public String getApplication() { + return application; + } + + public String getComponent() { + return component; + } + + public Optional<String> getTypeId() { + return typeId; + } + + public Optional<String> getCreated() { + return created; + } + + public Optional<Boolean> getCanDeploy() { + return canDeploy; + } + + public void setCanDeploy(Optional<Boolean> canDeploy) { + this.canDeploy = canDeploy; + } + + public ServiceRefCfyList getDeployments() { + return deployments; + } + + public void setDeployments(ServiceRefCfyList deployments) { + this.deployments = deployments; + } + + // Used for back end search, only searches the fields displayed in the front + // end. + public boolean contains(String searchString) { + if (StringUtils.containsIgnoreCase(this.getOwner(), searchString) + || StringUtils.containsIgnoreCase(this.getTypeId().get(), searchString) + || StringUtils.containsIgnoreCase(this.getTypeName(), searchString) + || StringUtils.containsIgnoreCase(Integer.toString(this.getTypeVersion()), searchString) + || StringUtils.containsIgnoreCase(this.getCreated().get(), searchString) + || StringUtils.containsIgnoreCase(this.getComponent(), searchString) + || StringUtils.containsIgnoreCase(this.getApplication(), searchString)) { + return true; + } + return false; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((typeId == null) ? 0 : typeId.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ServiceTypeSummary other = (ServiceTypeSummary) obj; + if (typeId == null) { + if (other.typeId != null) + return false; + } else if (!typeId.equals(other.typeId)) + return false; + return true; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummaryList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummaryList.java new file mode 100644 index 0000000..149e75b --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummaryList.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model.inventory; + +import java.util.Collection; + +import org.onap.ccsdk.dashboard.model.ECTransportModel; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ServiceTypeSummaryList extends ECTransportModel { + + /** Number of ServiceType objects */ + public final Integer totalCount; + /** Collection containing all of the returned ServiceType objects */ + public final Collection<ServiceTypeSummary> items; + /** Links to the previous and next page of items */ + public final PaginationLinks paginationLinks; + + @JsonCreator + public ServiceTypeSummaryList( + @JsonProperty("items") Collection<ServiceTypeSummary> items, + @JsonProperty("totalCount") Integer totalCount, + @JsonProperty("links") PaginationLinks paginationLinks) { + this.items = items; + this.totalCount = totalCount; + this.paginationLinks = paginationLinks; + } + + /** InlineResponse200Links */ + public static final class PaginationLinks { + public final Link previousLink; + public final Link nextLink; + + @JsonCreator + public PaginationLinks(@JsonProperty("previousLink") Link previousLink, + @JsonProperty("nextLink") Link nextLink) { + this.previousLink = previousLink; + this.nextLink = nextLink; + } + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyClient.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyClient.java index 1ffab54..04a084e 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyClient.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyClient.java @@ -21,20 +21,26 @@ *******************************************************************************/ package org.onap.ccsdk.dashboard.rest; +import java.util.List; import java.util.Map; -import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse; -import org.onap.ccsdk.dashboard.model.CloudifyEventList; -import org.onap.ccsdk.dashboard.model.CloudifyExecution; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList; -import org.onap.ccsdk.dashboard.model.CloudifyTenantList; +import javax.servlet.http.HttpServletRequest; + +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret; /** * @author rp5662 @@ -51,7 +57,7 @@ public interface CloudifyClient { /** * Gets the list of Cloudify tenants. * - * @return CloudifyBlueprintList + * @return CloudifyTenantList */ public CloudifyTenantList getTenants(); @@ -85,13 +91,6 @@ public interface CloudifyClient { public CloudifyNodeInstanceIdList getNodeInstanceId(String deploymentId, String nodeId, String tenant); /** - * Gets all the deployments with include filters for tenant name - * - * @return List of CloudifyDeployedTenant objects - */ - public CloudifyDeployedTenantList getTenantInfoFromDeploy(String tenant); - - /** * Get the node-instance-id. * * @param deploymentId deployment ID @@ -102,14 +101,6 @@ public interface CloudifyClient { public CloudifyNodeInstanceIdList getNodeInstanceId(String id, String tenant); /** - * Initiate a deployment update in cloudify - * - * @param execution - * @return - */ - public CloudifyDeploymentUpdateResponse updateDeployment(CloudifyDeploymentUpdateRequest execution); - - /** * Query execution information for a deployment ID passed as input * * @param deploymentId @@ -167,7 +158,21 @@ public interface CloudifyClient { * Query deployments from cloudify * */ - public CloudifyDeploymentList getDeployments(); + public CloudifyDeploymentList getDeployments(String tenant, int pageSize, int pageOffset); + + /** + * Query deployments from cloudify and filter based + * on given input key and value + * At the moment only supports key "contains" not "equals" + * For value it supports only "equals" not "contains" + * @param inputKey + * @param inputValue + * @param returnFullDeployment If true, returns full deployment obj, otherwise only some attributes + * @return + */ + public List<CloudifyDeployment> getDeploymentsByInputFilter(String inputKey, String inputValue) throws Exception; + + public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request, String filter) throws Exception; /** * Query a blueprint object matching the blueprint ID in cloudify @@ -186,4 +191,70 @@ public interface CloudifyClient { * @return */ public CloudifyDeploymentList getDeploymentInputs(String id, String tenant); + + /** + * Query a cloudify secret under a tenant scope + * + * @param secretName + * @param tenant + * @return + */ + public CloudifySecret getSecret(String secretName, String tenant); + + /** + * Query install workflow execution summary for a deployment ID + * + * @param deploymentId + * @param tenant + * @return + */ + public CloudifyExecutionList getInstallExecutionSummary(String deploymentId, String tenant); + + /** + * + * Delete Blueprint + * + * @param blueprint ID + */ + public void deleteBlueprint(String bpName, String tenant); + /** + * + * Query deployment node instances + * + * @param deploymentId + * @param tenant + * @return + */ + public CloudifyNodeInstanceIdList getNodeInstances(String deploymentId, String tenant); + + public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset, + boolean recurse); + + public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset, + boolean recurse, boolean cache); + + public byte[] viewBlueprint(String tenant, String id); + + public void cacheDeployments(); + + public CloudifyDeployment getDeploymentResource(final String id, final String tenant); + + public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request) throws Exception; + + public CloudifyNodeInstanceList getNodeInstanceDetails(String deploymentId, String tenant); + + public List<CloudifyDeployedTenant> getDeploymentForBlueprint(final String bpId); + + public List<CloudifyDeploymentExt> updateWorkflowStatus(List<CloudifyDeployment> itemList); + + public List<CloudifyDeploymentHelm> updateHelmInfo(List<CloudifyDeployment> itemList); + + public List<String> getDeploymentNamesWithFilter(HttpServletRequest request) + throws Exception; + + public CloudifyPluginList getPlugins(); + + public CloudifyExecutionList getExecutionsSummaryPerTenant(String tenant); + + public CloudifyExecution getExecutionIdSummary(final String id, final String tenant); } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImpl.java index 28bd87c..0e64ef0 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImpl.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImpl.java @@ -23,32 +23,53 @@ package org.onap.ccsdk.dashboard.rest; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import java.util.Map; - +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Predicate; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import org.json.JSONObject; -import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse; -import org.onap.ccsdk.dashboard.model.CloudifyEventList; -import org.onap.ccsdk.dashboard.model.CloudifyExecution; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; -import org.onap.ccsdk.dashboard.model.CloudifyNodeIdList; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList; -import org.onap.ccsdk.dashboard.model.CloudifyTenantList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprint; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenantList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenant; import org.onap.ccsdk.dashboard.util.DashboardProperties; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.objectcache.AbstractCacheManager; +import org.onap.portalsdk.core.web.support.AppUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.Scheduled; @org.springframework.stereotype.Service public class CloudifyRestClientImpl extends RestClientBase implements CloudifyClient { @@ -64,19 +85,35 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl private static final String NODE_INSTANCES = "node-instances"; private static final String UPDATE_DEPLOYMENT = "update-deployment"; private static final String EVENTS = "events"; - private static final String TENANT = "tenant_name"; + private static final String SECRETS = "secrets"; + private static final String SERVICE_ID = "service-list"; + private static final String PLUGINS = "plugins"; + + /** + * For caching data + */ + private AbstractCacheManager cacheManager; + + @Autowired + public void setCacheManager(AbstractCacheManager cacheManager) { + this.cacheManager = cacheManager; + } + public AbstractCacheManager getCacheManager() { + return cacheManager; + } + @PostConstruct public void init() { - String webapiUrl = DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_URL); + String webapiUrl = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL); if (webapiUrl == null) { throw new IllegalArgumentException("Null URL not permitted"); } - String user = DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_USERNAME); - String pass = DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_PASS); + String user = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME); + String pass = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS); URL url = null; try { url = new URL(webapiUrl); @@ -90,6 +127,207 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl } } + @SuppressWarnings("unchecked") + public List<CloudifyDeploymentHelm> updateHelmInfo(List<CloudifyDeployment> itemList) { + boolean isHelm = false; + boolean helmStatus = false; + List<CloudifyDeploymentHelm> result = new ArrayList<>(); + for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) { + try { + isHelm = false; + helmStatus = false; + CloudifyBlueprintList bpList = + this.getBlueprint(srvc.blueprint_id, srvc.tenant_name); + Map<String, Object> bpPlan = bpList.items.get(0).plan; + Map<String, String> workflows = (Map<String, String>) bpPlan.get("workflows"); + Map<String, String> pluginInfo = + ((List<Map<String, String>>) bpPlan.get("deployment_plugins_to_install")) + .get(0); + if (pluginInfo.get("name").equals("helm-plugin")) { + isHelm = true; + } + if (workflows.containsKey("status")) { + helmStatus = true; + } + CloudifyDeploymentHelm cfyDeplHelm = + new CloudifyDeploymentHelm(srvc.id, isHelm, helmStatus); + result.add(cfyDeplHelm); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "getBlueprint failed"); + CloudifyDeploymentHelm cfyDeplHelm = + new CloudifyDeploymentHelm(srvc.id, false, false); + result.add(cfyDeplHelm); + continue; + } + } + return result; + } + + public List<CloudifyDeploymentExt> updateWorkflowStatus(List<CloudifyDeployment> itemList) { + List<CloudifyDeploymentExt> result = new ArrayList<>(); + for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) { + try { + // find deployment execution info per item + CloudifyExecutionList execResults = + this.getExecutionsSummary(srvc.id, srvc.tenant_name); + if (execResults.items != null && !execResults.items.isEmpty()) { + CloudifyDeploymentExt cfyDeplExt = + new CloudifyDeploymentExt(srvc.id, + srvc.blueprint_id, srvc.tenant_name); + cfyDeplExt.lastExecution = + execResults.items.get(0); + result.add(cfyDeplExt); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsSummary failed"); + srvc.lastExecution = null; + continue; + } + } + return result; + } + + public List<CloudifyDeployedTenant> getDeploymentForBlueprint(final String bpId) { + String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, + new String[] { "blueprint_id", bpId, "_all_tenants", "true", "_include", "id,created_at,updated_at,tenant_name"}); + logger.debug(EELFLoggerDelegate.debugLogger, "getDeploymentForBlueprint begin: url {}", url); + ResponseEntity<CloudifyDeployedTenantList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyDeployedTenantList>() { + }); + return response.getBody().items; + } + + public CloudifyDeployment getDeploymentResource(final String id, final String tenant) { + String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, + new String[] { "id", id, "_include", "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name", + "_sort","-updated_at", "_sort", "-created_at"}); + logger.debug(EELFLoggerDelegate.debugLogger, "getDeploymentResource begin: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyDeploymentList>() { + }); + return response.getBody().items.get(0); + } + + @Scheduled(fixedRate=86400000, initialDelay=15000) + public void cacheTenants() { + logger.debug(EELFLoggerDelegate.debugLogger, "cacheTenants begin"); + CloudifyTenantList tenantsList = this.getTenants(); + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.writeLock().lock(); + getCacheManager().putObject(TENANTS, tenantsList.items); + lock.writeLock().unlock(); + logger.debug(EELFLoggerDelegate.debugLogger, "cacheTenants end"); + } + + @SuppressWarnings("unchecked") + @Scheduled(fixedDelay=3600000, initialDelay=360000) + public void cacheDeploymentExecInfo() { + logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentExecInfo begin"); + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + List<CloudifyTenant> tenantItems = + (List<CloudifyTenant>) getCacheManager().getObject(TENANTS); + lock.readLock().unlock(); + String cfyTen = ""; + if (tenantItems != null) { + for (CloudifyTenant item : tenantItems) { + cfyTen = item.name; + lock.readLock().lock(); + List<CloudifyDeployment> cfyDeplList = + (List<CloudifyDeployment>)getCacheManager(). + getObject(SERVICE_ID + ":" + cfyTen); + lock.readLock().unlock(); + if (cfyDeplList != null) { + List<CloudifyDeploymentExt> cfyDeplExecList = + this.updateWorkflowStatus(cfyDeplList); + lock.writeLock().lock(); + getCacheManager().putObject(SERVICE_ID + ":" + cfyTen + ":ext", cfyDeplExecList); + lock.writeLock().unlock(); + } + } + } + logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentExecInfo end"); + } + + @SuppressWarnings("unchecked") + @Scheduled(fixedDelay=3900000, initialDelay=600000) + public void cacheDeploymentHelmInfo() { + logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentHelmInfo begin"); + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + List<CloudifyTenant> tenantItems = + (List<CloudifyTenant>) getCacheManager().getObject(TENANTS); + lock.readLock().unlock(); + String cfyTen = ""; + if (tenantItems != null) { + for (CloudifyTenant item : tenantItems) { + cfyTen = item.name; + lock.readLock().lock(); + List<CloudifyDeployment> cfyDeplList = + (List<CloudifyDeployment>)getCacheManager(). + getObject(SERVICE_ID + ":" + cfyTen); + lock.readLock().unlock(); + if (cfyDeplList != null) { + List<CloudifyDeploymentHelm> cfyDeplHelmList = + this.updateHelmInfo(cfyDeplList); + lock.writeLock().lock(); + getCacheManager().putObject(SERVICE_ID + ":" + cfyTen + ":helm", cfyDeplHelmList); + lock.writeLock().unlock(); + } + } + } + logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentHelmInfo end"); + } + + @Scheduled(fixedDelay=300000, initialDelay=90000) + public void cacheDeployments() { + logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeployments begin"); + int pageSize = 500; + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + List<CloudifyTenant> tenantItems = + (List<CloudifyTenant>) getCacheManager().getObject(TENANTS); + lock.readLock().unlock(); + String cfyTen = "default_tenant"; + if (tenantItems != null) { + for (CloudifyTenant item : tenantItems) { + cfyTen = item.name; + String url = buildUrl(new String[] {baseUrl, DEPLOYMENTS}, + new String[] {"_include", + "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name", + "_sort", "-updated_at", "_sort", "-created_at", "_size", + new Integer(pageSize).toString(), "_offset", new Integer(0).toString()}); + logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeployments begin: url {}", url); + HttpEntity<String> entity = getTenantHeader(cfyTen); + ResponseEntity<CloudifyDeploymentList> response = + restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyDeploymentList>() {}); + List<CloudifyDeployment> cfyDeplList = new ArrayList<CloudifyDeployment>(); + cfyDeplList.addAll(response.getBody().items); + int totalItems = (int) response.getBody().metadata.pagination.total; + int deplPgOffset = 0; + deplPgOffset += pageSize; + while (deplPgOffset < totalItems) { + url = buildUrl(new String[] {baseUrl, DEPLOYMENTS}, new String[] { + "_include", + "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name", + "_sort", "-updated_at", "_sort", "-created_at", "_size", + new Integer(pageSize).toString(), "_offset", + new Integer(deplPgOffset).toString()}); + response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyDeploymentList>() {}); + deplPgOffset += pageSize; + cfyDeplList.addAll(response.getBody().items); + } + lock.writeLock().lock(); + getCacheManager().putObject(SERVICE_ID + ":" + cfyTen, cfyDeplList); + lock.writeLock().unlock(); + } + } + logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeployments done putting deployment data"); + } + @Override public CloudifyTenantList getTenants() { String url = buildUrl(new String[] { baseUrl, TENANTS }, null); @@ -124,6 +362,30 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl } @Override + public CloudifyNodeInstanceList getNodeInstanceDetails(String deploymentId, String tenant) { + String url = buildUrl(new String[] { baseUrl, NODE_INSTANCES }, + new String[] { "deployment_id", deploymentId}); + logger.debug(EELFLoggerDelegate.debugLogger, "getNodeInstanceDetails: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifyNodeInstanceList> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyNodeInstanceList>() { + }); + return response.getBody(); + } + + @Override + public CloudifyNodeInstanceIdList getNodeInstances(String deploymentId, String tenant) { + String url = buildUrl(new String[] { baseUrl, NODE_INSTANCES }, + new String[] { "deployment_id", deploymentId, "_include", "id" }); + logger.debug(EELFLoggerDelegate.debugLogger, "getNodeInstanceId: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifyNodeInstanceIdList> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyNodeInstanceIdList>() { + }); + return response.getBody(); + } + + @Override public CloudifyNodeInstanceList getNodeInstanceVersion(String deploymentId, String nodeId, String tenant) { String url = buildUrl(new String[] { baseUrl, NODE_INSTANCES }, new String[] { "deployment_id", deploymentId, "node_id", nodeId, "_include", "runtime_properties,id" }); @@ -164,21 +426,20 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl } @Override - public CloudifyDeployedTenantList getTenantInfoFromDeploy(String tenant) { - String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, - new String[] { "_include", "id,blueprint_id,tenant_name" }); - logger.debug(EELFLoggerDelegate.debugLogger, "getTenantInfoFromDeploy: url {}", url); + public CloudifyExecutionList getExecutions(final String deploymentId, final String tenant) { + String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId }); + logger.debug(EELFLoggerDelegate.debugLogger, "getExecutions: url {}", url); HttpEntity<String> entity = getTenantHeader(tenant); - - ResponseEntity<CloudifyDeployedTenantList> response = restTemplate.exchange(url, HttpMethod.GET, entity, - new ParameterizedTypeReference<CloudifyDeployedTenantList>() { + ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyExecutionList>() { }); return response.getBody(); } @Override - public CloudifyExecutionList getExecutions(final String deploymentId, final String tenant) { - String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId }); + public CloudifyExecutionList getExecutionsSummary(final String deploymentId, final String tenant) { + String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId, + "_include", "deployment_id,id,status,workflow_id,tenant_name,created_at,ended_at", "_sort", "-created_at" }); logger.debug(EELFLoggerDelegate.debugLogger, "getExecutions: url {}", url); HttpEntity<String> entity = getTenantHeader(tenant); ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity, @@ -188,9 +449,32 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl } @Override - public CloudifyExecutionList getExecutionsSummary(final String deploymentId, final String tenant) { + public CloudifyExecutionList getExecutionsSummaryPerTenant(final String tenant) { + String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { + "_include","deployment_id,id,status,workflow_id,tenant_name,created_at,ended_at", "_sort", "-created_at" }); + logger.debug(EELFLoggerDelegate.debugLogger, "getExecutionsSummaryPerTenant: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyExecutionList>() { + }); + return response.getBody(); + } + + public CloudifyExecution getExecutionIdSummary(final String id, final String tenant) { + String url = buildUrl(new String[] { baseUrl, EXECUTIONS, id }, new String[] { + "_include","deployment_id,id,status,workflow_id,tenant_name,created_at,ended_at", "_sort", "-created_at" }); + logger.debug(EELFLoggerDelegate.debugLogger, "getExecutionIdSummary: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifyExecution> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyExecution>() { + }); + return response.getBody(); + } + + @Override + public CloudifyExecutionList getInstallExecutionSummary(final String deploymentId, final String tenant) { String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId, - "_include", "deployment_id,id,status,workflow_id,tenant_name,created_at" }); + "workflow_id", "install", "_include", "deployment_id,id,status,workflow_id,tenant_name,created_at" }); logger.debug(EELFLoggerDelegate.debugLogger, "getExecutions: url {}", url); HttpEntity<String> entity = getTenantHeader(tenant); ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity, @@ -198,7 +482,7 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl }); return response.getBody(); } - + @Override public CloudifyExecution startExecution(CloudifyExecutionRequest execution) { String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, null); @@ -211,13 +495,6 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl } @Override - public CloudifyDeploymentUpdateResponse updateDeployment(CloudifyDeploymentUpdateRequest execution) { - String url = buildUrl(new String[] { baseUrl, UPDATE_DEPLOYMENT }, null); - logger.debug(EELFLoggerDelegate.debugLogger, "updateDeployment: url {}", url); - return restTemplate.postForObject(url, execution, CloudifyDeploymentUpdateResponse.class); - } - - @Override public CloudifyExecution cancelExecution(final String executionId, Map<String, String> parameters, final String tenant) { String url = buildUrl(new String[] { baseUrl, EXECUTIONS, executionId }, null); @@ -246,18 +523,516 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl } @Override - public CloudifyDeploymentList getDeployments() { - String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, null); + public byte[] viewBlueprint(String tenant, final String id) { + String url = buildUrl(new String[] { baseUrl, BLUEPRINTS, id, "archive" }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "viewBlueprint: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<byte[]> response = + restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class); + if (response.getStatusCode() == HttpStatus.OK) { + return response.getBody(); + } + return null; + } + + @Override + public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset, boolean recurse) { + return this.getDeployments(tenant, pageSize, pageOffset, true, true); + } + + @SuppressWarnings("unchecked") + @Override + public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset, boolean recurse, boolean cache) { + List<CloudifyDeployment> cfyDeplList = null; + if (cache) { + cfyDeplList = + (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenant); + } + if (cfyDeplList == null || cfyDeplList.isEmpty()) { + String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, + new String[] { "_include", "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name", + "_sort","-updated_at", "_sort", "-created_at", + "_size", new Integer(pageSize).toString(), + "_offset" , new Integer(pageOffset).toString()}); + logger.debug(EELFLoggerDelegate.debugLogger, "getDeployments: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyDeploymentList>() { + }); + cfyDeplList = new ArrayList<CloudifyDeployment>(); + cfyDeplList.addAll(response.getBody().items); + if (recurse) { + int totalItems = (int)response.getBody().metadata.pagination.total; + int deplPgOffset = 0; + deplPgOffset += pageSize; + while (deplPgOffset < totalItems) { + url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, + new String[] { "_include", "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name", + "_sort","-updated_at", "_sort", "-created_at", + "_size", new Integer(pageSize).toString(), + "_offset" , new Integer(deplPgOffset).toString()}); + response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyDeploymentList>() { + }); + deplPgOffset += pageSize; + cfyDeplList.addAll(response.getBody().items); + } + } + } + return cfyDeplList; + } + + public CloudifyDeploymentList getDeployments(String tenant, int pageSize, int pageOffset) { + String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, + new String[] { "_include", "id,blueprint_id,created_at,updated_at,created_by,description", + "_sort","-updated_at", "_sort", "-created_at", + "_size", new Integer(pageSize).toString(), + "_offset" , new Integer(pageOffset).toString()}); logger.debug(EELFLoggerDelegate.debugLogger, "getDeployments: url {}", url); - ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, null, + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity, new ParameterizedTypeReference<CloudifyDeploymentList>() { }); + return response.getBody(); } + + @Override + public List<CloudifyDeployment> getDeploymentsByInputFilter(String inputKey, String inputValue) throws Exception { + JSONObject inputObject = new JSONObject() + .put("inputKey", inputKey) + .put("inputValue", inputValue); + String filter = new JSONObject() + .put("input", inputObject) + .toString(); + return getDeploymentsWithFilter(null, filter); + } + + @SuppressWarnings("unchecked") + @Override + public List<String> getDeploymentNamesWithFilter(HttpServletRequest request) + throws Exception { + List<CloudifyDeployment> itemList = this.getDeploymentsWithFilter(request); + Set<String> svcIdList = new HashSet<String>(); + if (itemList != null) { + svcIdList = + (Set) itemList.stream().map(x -> ((CloudifyDeployment)x).id).collect(Collectors.toSet()); + } + List<String> response = new ArrayList<String>(); + response.addAll(svcIdList); + return response; + } + + @SuppressWarnings("unchecked") + @Override + public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request) throws Exception { + String filters = request.getParameter("filters"); + List<CloudifyDeployment> deployments = new ArrayList<CloudifyDeployment>(); + if (filters != null) { + deployments = getDeploymentsWithFilter(request, filters); + } else { + List<CloudifyTenant> selectedTenants = new ArrayList<CloudifyTenant>(); + selectedTenants = getTenants().items; + List<CloudifyDeployment> itemList = null; + for (CloudifyTenant tenant : selectedTenants) { + itemList = this.getDeployments(tenant.name, 500, 0, true); + deployments.addAll(itemList); + } + // apply user role based auth + Set<String> userApps = null; + Set<String> userRoleSet = null; + try { + HttpSession session = AppUtils.getSession(request); + userApps = (Set<String>) session.getAttribute("authComponents"); + userRoleSet = (Set<String>) session.getAttribute("user_roles"); + } catch (Exception e) { + // requester is REST API + userRoleSet = (Set<String>)request.getAttribute("userRoles"); + userApps = (Set<String>) request.getAttribute("userApps"); + } + + if (userApps == null) { + userApps = new TreeSet<String>(); + } + + if (userRoleSet == null) { + userRoleSet = new TreeSet<String>(); + } + + Predicate<String> adminPred = + p -> p.contains("System_Administrator") || p.contains("Write_Access"); + + Predicate<String> ecompSuperPred = + p -> p.contains("ECOMPC_WRITE") || p.contains("ECOMPC_READ"); + + if (userRoleSet.size() > 0) { + if (userRoleSet.stream().noneMatch(adminPred)) { + List<String> myApps = new ArrayList(userApps); + if (userRoleSet.stream().noneMatch(ecompSuperPred)) { + deployments = (List<CloudifyDeployment>) deployments.stream().filter(s -> myApps.stream() + .anyMatch(roleFilter -> ((CloudifyDeployment)s).id.toLowerCase().startsWith(roleFilter))) + .collect(Collectors.toList()); + } else { + Predicate<CloudifyDeployment> appFilter = + p -> p.id.toLowerCase().indexOf("dcae") == -1 || p.id.toLowerCase().indexOf("d2a") == -1; + deployments = (List<CloudifyDeployment>) deployments.stream().filter(appFilter) + .collect(Collectors.toList()); + } + } + } + } + return deployments; + } + + @Override + public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request, String filter) + throws Exception { + String url = ""; + JSONObject filterJson = new JSONObject(filter); + ReadWriteLock lock = new ReentrantReadWriteLock(); + + //---------Handle Tenant filter---------// + List<CloudifyTenant> selectedTenants = new ArrayList<CloudifyTenant>(); + if (filterJson.has("tenant")) { + String tenantFilterString = ""; + Object tenantObject = filterJson.get("tenant"); + + //Check for logic operators + if (tenantObject instanceof JSONObject) { + JSONObject tenantJsonObject = filterJson.getJSONObject("tenant"); + if (tenantJsonObject.has("$not")) { + tenantFilterString = tenantJsonObject.getString("$not"); + selectedTenants = tenantFilter(tenantFilterString, true); + } + else { + throw new Exception("ERROR: Not a valid logic operator"); + } + } + else if (tenantObject instanceof String) { + tenantFilterString = filterJson.getString("tenant"); + selectedTenants = tenantFilter(tenantFilterString, false); + } + } + else { + selectedTenants = getTenants().items; + } + //---------Get Deployments based on tenants selected---------// + List<CloudifyDeployment> deployments = new ArrayList<CloudifyDeployment>(); + List<CloudifyDeployment> itemList = null; + HttpEntity<String> entity; + String tenantFilterStr = ""; + int pageSize = 500; + + //---------Handle the _include filter---------// + String include = filterJson.has("_include") ? filterJson.getString("_include") : null; + for (CloudifyTenant tenant : selectedTenants) { + tenantFilterStr = tenant.name; + lock.readLock().lock(); + itemList = + (List<CloudifyDeployment>)getCacheManager(). + getObject("service-list" + ":" + tenantFilterStr); + lock.readLock().unlock(); + + if (itemList == null || include != null) { + if (include == null || include.isEmpty()) { + include = "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name"; + } + url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] {"_include", + include,"_sort", "-updated_at", "_sort", "-created_at", "_size", + new Integer(pageSize).toString(), "_offset", new Integer(0).toString()}); + + logger.debug(EELFLoggerDelegate.debugLogger, "getDeployments: url {}", url); + + entity = getTenantHeader(tenant.name); + ResponseEntity<CloudifyDeploymentList> response = + restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyDeploymentList>() { + }); + deployments.addAll(response.getBody().items); + int totalItems = (int) response.getBody().metadata.pagination.total; + int deplPgOffset = 0; + deplPgOffset += pageSize; + while (deplPgOffset < totalItems) { + url = buildUrl(new String[] {baseUrl, DEPLOYMENTS}, new String[] { + "_include", + include, + "_sort", "-updated_at", "_sort", "-created_at", "_size", + new Integer(pageSize).toString(), "_offset", + new Integer(deplPgOffset).toString()}); + response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifyDeploymentList>() {}); + deplPgOffset += pageSize; + deployments.addAll(response.getBody().items); + } + } else { + deployments.addAll(itemList); + } + } + // apply user role based auth + Set<String> userRoleSet = (Set<String>) request.getAttribute("userRoles"); + Set<String> userApps = (Set<String>) request.getAttribute("userApps"); + + Predicate<String> adminPred = + p -> p.contains("System_Administrator") || p.contains("Write_Access"); + + Predicate<String> ecompSuperPred = + p -> p.contains("ECOMPC_WRITE") || p.contains("ECOMPC_READ"); + + if (userRoleSet.stream().noneMatch(adminPred)) { + if (userRoleSet.stream().noneMatch(ecompSuperPred)) { + deployments = (List<CloudifyDeployment>) deployments.stream().filter(s -> userApps + .stream() + .anyMatch(appFilter -> (((CloudifyDeployment) s).id.toLowerCase().indexOf(appFilter) == 0))) + .collect(Collectors.<CloudifyDeployment>toList()); + } else { + Predicate<CloudifyDeployment> appFilter = p -> p.id.toLowerCase().indexOf("dcae") == -1; + deployments = (List<CloudifyDeployment>) deployments.stream().filter(appFilter) + .collect(Collectors.toList()); + } + } + + List<CloudifyDeployment> filteredDeployments = deployments; + //-------------------ServiceId Filter-------------------// + if (filterJson.has("serviceId")) { + String serviceIdFilterString; + Object serviceIdObject = filterJson.get("serviceId"); + + //Check for logic operators + if (serviceIdObject instanceof JSONObject) { + JSONObject serviceIdJsonObject = filterJson.getJSONObject("serviceId"); + if (serviceIdJsonObject.has("$not")) { + serviceIdFilterString = serviceIdJsonObject.getString("$not"); + filteredDeployments = serviceIdFilter(serviceIdFilterString, filteredDeployments, true); + } + else { + throw new Exception("ERROR: Not a valid logic operator"); + } + } + else if (serviceIdObject instanceof String) { + serviceIdFilterString = filterJson.getString("serviceId"); + filteredDeployments = serviceIdFilter(serviceIdFilterString, filteredDeployments, false); + } + } + + //------------------Handle Input Filter--------------// + if (filterJson.has("input")) { + JSONObject inputFilterObject; + Object inputObject = filterJson.get("input"); + + //Check for logic operators + if (inputObject instanceof JSONObject) { + JSONObject inputJsonObject = filterJson.getJSONObject("input"); + if (inputJsonObject.has("$not")) { + inputFilterObject = inputJsonObject.getJSONObject("$not"); + filteredDeployments = inputFilter(inputFilterObject, filteredDeployments, true); + } + //If no operators, pass to filter func + else { + inputFilterObject = inputJsonObject; + filteredDeployments = inputFilter(inputFilterObject, filteredDeployments, false); + } + } + } + + //-------------------Install Status Filter-------------------// + if (filterJson.has("installStatus")) { + String installStatusFilterString; + Object installStatusObject = filterJson.get("installStatus"); + + //Check for logic operators + if (installStatusObject instanceof JSONObject) { + JSONObject installStatusJsonObject = filterJson.getJSONObject("installStatus"); + if (installStatusJsonObject.has("$not")) { + installStatusFilterString = installStatusJsonObject.getString("$not"); + filteredDeployments = installStatusFilter(installStatusFilterString, filteredDeployments, true); + } + else { + throw new Exception("ERROR: Not a valid logic operator"); + } + } + else if (installStatusObject instanceof String) { + installStatusFilterString = filterJson.getString("installStatus"); + filteredDeployments = installStatusFilter(installStatusFilterString, filteredDeployments, false); + } + } + + //-------------------isHelm Filter-------------------// + if (filterJson.has("isHelm")) { + String helmFilterString; + Object helmObject = filterJson.get("isHelm"); + + //Check for logic operators + if (helmObject instanceof JSONObject) { + JSONObject helmJsonObject = filterJson.getJSONObject("isHelm"); + if (helmJsonObject.has("$not")) { + helmFilterString = helmJsonObject.getString("$not"); + filteredDeployments = helmFilter(helmFilterString, filteredDeployments, true); + } + else { + throw new Exception("ERROR: Not a valid logic operator"); + } + } + else if (helmObject instanceof String) { + helmFilterString = filterJson.getString("isHelm"); + filteredDeployments = helmFilter(helmFilterString, filteredDeployments, false); + } + } + //CloudifyDeploymentList filteredDepList = new CloudifyDeploymentList(filteredDeployments, null); + return filteredDeployments; + } + + /* + * Helper function to handle the tenant filter + */ + private List<CloudifyTenant> tenantFilter(String filterString, boolean isNot) throws Exception { + CloudifyTenantList availableTenants = getTenants(); + List<CloudifyTenant> selectedTenants = new ArrayList<CloudifyTenant>(); + + //If using tenant filter, verify its valid tenant name + if (filterString != null && !filterString.isEmpty()) { + for (CloudifyTenant tenant : availableTenants.items) { + if (!isNot && tenant.name.equals(filterString)) { + selectedTenants.add(tenant); + } + else if (isNot && !tenant.name.equals(filterString)) { + selectedTenants.add(tenant); + } + } + if (selectedTenants.isEmpty()) { + throw new Exception("ERROR: Tenant filter was used but resulted in no selected tenants"); + } + } + //If no proper tenants given + else { + throw new Exception("ERROR: Tenant filter was used but no tenants were given"); + } + return selectedTenants; + } + + + /* + * Helper function to filter deployments by serviceId + */ + private List<CloudifyDeployment> serviceIdFilter(String filterString, List<CloudifyDeployment> deployments, boolean isNot) throws Exception { + List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>(); + if (filterString != null && !filterString.isEmpty()) { + for (CloudifyDeployment dep : deployments) { + if (!isNot && dep.id.contains(filterString)) + newFilteredDeployments.add(dep); + else if (isNot && !dep.id.contains(filterString)) + newFilteredDeployments.add(dep); + } + } + else { + throw new Exception("ERROR: Service ID filter was used but a valid serviceId String was not provided"); + } + return newFilteredDeployments; + } + + + /* + * Helper function to filter deployments by input + */ + private List<CloudifyDeployment> inputFilter(JSONObject filterJson, List<CloudifyDeployment> deployments, boolean isNot) throws Exception { + List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>(); + if (filterJson != null && filterJson.has("inputKey") && filterJson.has("inputValue") && + !filterJson.isNull("inputKey") && !filterJson.isNull("inputValue")) { + String inputKey = filterJson.getString("inputKey"); + String inputValue = filterJson.getString("inputValue"); + + ///For now, only allow the use of aaf_username and dcaeTargetType input key + if (!inputKey.equals("aaf_username") && !inputKey.equals("dcae_target_type")) + throw new Exception("ERROR: This input key is NOT supported"); + + //For each deployment, get the input keys that contain <inputKey> + //then check their value to see if it contains the desired <inputValue> + for (CloudifyDeployment dep : deployments) { + if (dep.inputs == null) + throw new Exception("ERROR: Deployment inputs not found, 'inputs' must be in the include filter for input filtering"); + Set<String> filteredDepInputKeys = dep.inputs.keySet().stream() + .filter(s -> s.contains(inputKey)).collect(Collectors.toSet()); + for (String filteredKey : filteredDepInputKeys) { + String value = dep.inputs.get(filteredKey).toString(); + if (!isNot && value.equals(inputValue)) { + newFilteredDeployments.add(dep); + break; + } + else if (isNot && !value.equals(inputValue)) { + newFilteredDeployments.add(dep); + break; + } + } + } + } + else { //If filter used but no valid KV found + throw new Exception("ERROR: Input filter was used but a valid inputKey and inputValue was not provided"); + } + return newFilteredDeployments; + } + + /* + * Helper function to filter deployments by install status + */ + private List<CloudifyDeployment> installStatusFilter(String filterString, List<CloudifyDeployment> deployments, boolean isNot) throws Exception { + List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>(); + if (filterString != null && !filterString.isEmpty()) { + + //For each deployment, get execution status and compare to filter + for (CloudifyDeployment dep : deployments) { + List<CloudifyExecution> executions = getInstallExecutionSummary(dep.id, dep.tenant_name).items; + if (executions.size() > 0) { + String status = executions.get(0).status; + if (!isNot && status.equals(filterString)) { + newFilteredDeployments.add(dep); + } + else if (isNot && !status.equals(filterString)) { + newFilteredDeployments.add(dep); + } + } + } + } + else { //If using filter but invalid install status given + throw new Exception("ERROR: Install Status filter was used but a valid installStatus String was not provided"); + } + return newFilteredDeployments; + } + + /* + * Helper function to filter by isHelm + */ + private List<CloudifyDeployment> helmFilter(String filterJson, List<CloudifyDeployment> deployments, boolean isNot) { + List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>(); + if (filterJson != null && !filterJson.isEmpty()) { + + //For each deployment, get blueprint and see if it has helm plugin and compare to filter + for (CloudifyDeployment dep : deployments) { + CloudifyBlueprintList bpList = getBlueprint(dep.blueprint_id, dep.tenant_name); + Map<String, Object> bpPlan = bpList.items.get(0).plan; + Map<String, String> workflows = (Map<String, String>) bpPlan.get("workflows"); + Map<String, String> pluginInfo = ((List<Map<String, String>>) bpPlan + .get("deployment_plugins_to_install")).get(0); + if (pluginInfo.get("name").equals("helm-plugin")) { + if (!isNot && (filterJson.equals("true") || filterJson.equals("True") || filterJson.equals("TRUE"))) + newFilteredDeployments.add(dep); + else if (isNot && (filterJson.equals("false") || filterJson.equals("False") || filterJson.equals("FALSE"))) + newFilteredDeployments.add(dep); + } + else + if (!isNot && (filterJson.equals("false") || filterJson.equals("False") || filterJson.equals("FALSE"))) + newFilteredDeployments.add(dep); + else if (isNot && (filterJson.equals("true") || filterJson.equals("True") || filterJson.equals("TRUE"))) + newFilteredDeployments.add(dep); + } + } + else { //If not using filter, just return original deployments + newFilteredDeployments = deployments; + } + return newFilteredDeployments; + } @Override public CloudifyDeploymentList getDeployment(final String id) { - String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id }); + String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id, "_all_tenants", "true" }); logger.debug(EELFLoggerDelegate.debugLogger, "getDeployment: url {}", url); ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<CloudifyDeploymentList>() { @@ -267,7 +1042,7 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl @Override public CloudifyDeploymentList getDeployment(final String id, final String tenant) { - String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id, TENANT, tenant }); + String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id}); logger.debug(EELFLoggerDelegate.debugLogger, "getDeployment: url {}", url); HttpEntity<String> entity = getTenantHeader(tenant); ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity, @@ -285,4 +1060,44 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl entity, new ParameterizedTypeReference<CloudifyDeploymentList>() {}); return response.getBody(); } + + /** + * Get a cloudify secret + * + * @return CloudifySecret + */ + @Override + public CloudifySecret getSecret(String secretName, String tenant) { + String url = buildUrl(new String[] { baseUrl, SECRETS, secretName }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getSecrets: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + ResponseEntity<CloudifySecret> response = restTemplate.exchange(url, HttpMethod.GET, entity, + new ParameterizedTypeReference<CloudifySecret>() { + }); + return response.getBody(); + } + + /** + * Get the list of cloudify plugins + * + * @return List<CloudifyPlugin> + */ + public CloudifyPluginList getPlugins() { + String url = buildUrl(new String[] { baseUrl, PLUGINS }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getPlugins: url {}", url); + ResponseEntity<CloudifyPluginList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyPluginList>() { + }); + CloudifyPluginList result = response.getBody(); + return result; + } + + @Override + public void deleteBlueprint(String bpName, String tenant) { + String url = buildUrl(new String[] { baseUrl, BLUEPRINTS, bpName }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "deleteBlueprint: url {}", url); + HttpEntity<String> entity = getTenantHeader(tenant); + restTemplate.exchange(url, HttpMethod.DELETE, entity, new ParameterizedTypeReference<CloudifyBlueprint>() { + }); + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulClient.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulClient.java index c63652b..90da400 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulClient.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulClient.java @@ -21,13 +21,16 @@ *******************************************************************************/ package org.onap.ccsdk.dashboard.rest; +import java.net.URL; import java.util.List; -import org.onap.ccsdk.dashboard.model.ConsulDatacenter; -import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration; -import org.onap.ccsdk.dashboard.model.ConsulNodeInfo; -import org.onap.ccsdk.dashboard.model.ConsulServiceHealth; -import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; +import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter; +import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration; +import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo; +import org.springframework.web.client.RestTemplate; /** * Defines the interface of the Consul REST client. @@ -48,6 +51,16 @@ public interface ConsulClient { * @return List of ConsulServiceHealth */ public List<ConsulServiceHealth> getServiceHealth(String datacenter, String srvcName); + + /** + * Gets the status for the service which corresponds to deployment Id on all nodes. + * Filters services on Consul to find services that contain service tag that + * matches the given deployment id + * + * @param deploymentId Deployment Id + * @return List of ConsulServiceHealth + */ + public ConsulDeploymentHealth getServiceHealthByDeploymentId(String deploymentId); /** * Gets all the nodes that are monitored by Consul. @@ -71,20 +84,4 @@ public interface ConsulClient { */ public List<ConsulDatacenter> getDatacenters(); - /** - * Registers a service with Consul for health check. - * - * @param registration Details about the service to be registered. - * @return Result of registering a service - */ - public String registerService(ConsulHealthServiceRegistration registration); - - /** - * Deregisters a service with Consul for health check. - * - * @param serviceName Name of the service to be deregistered. - * @return Response code - */ - public int deregisterService(String serviceName); - } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImpl.java index 2567577..911e342 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImpl.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImpl.java @@ -29,15 +29,25 @@ import java.util.Map; import javax.annotation.PostConstruct; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; import org.json.JSONArray; import org.json.JSONObject; -import org.onap.ccsdk.dashboard.model.ConsulDatacenter; -import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration; -import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration.EndpointCheck; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList; +import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter; +import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration; +import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration.EndpointCheck; +import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo; +import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth; import org.onap.ccsdk.dashboard.util.DashboardProperties; -import org.onap.ccsdk.dashboard.model.ConsulNodeInfo; -import org.onap.ccsdk.dashboard.model.ConsulServiceHealth; -import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; @@ -45,6 +55,9 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -55,18 +68,27 @@ public class ConsulRestClientImpl extends RestClientBase implements ConsulClient private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ConsulRestClientImpl.class); private String baseUrl; - private final ObjectMapper objectMapper = new ObjectMapper(); + private String consul_acl_token; + private HttpEntity<String> token_entity; private static final String API_VER = "v1"; private static final String CATALOG = "catalog"; private static final String SERVICES = "services"; private static final String HEALTH = "health"; private static final String CHECKS = "checks"; + private static final String STATE = "state"; + private static final String ANY = "any"; @PostConstruct public void init() { - String webapiUrl = DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_CONSUL_URL); + if (consul_acl_token == null || consul_acl_token.isEmpty()) { + consul_acl_token = getConsulAcl(); + } + if (consul_acl_token != null && !consul_acl_token.isEmpty()) { + token_entity = getConsulTokenHeader(consul_acl_token); + } + String webapiUrl = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CONSUL_URL); if (webapiUrl == null) throw new IllegalArgumentException("Null URL not permitted"); URL url = null; @@ -82,136 +104,271 @@ public class ConsulRestClientImpl extends RestClientBase implements ConsulClient } } + protected String getConsulAcl() { + return getConsulAcl(null); + } + + protected String getConsulAcl(RestTemplate cfyRest) { + String acl_token = null; + String webapiUrl = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL); + String cfyBaseUrl = ""; + if (webapiUrl != null) { + String user = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME); + String pass = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS); + URL url = null; + try { + url = new URL(webapiUrl); + cfyBaseUrl = url.toExternalForm(); + String urlScheme = webapiUrl.split(":")[0]; + if (cfyRest == null) { + cfyRest = + createCfyRestTemplate(url, user, pass, urlScheme); + } + String urlStr = buildUrl(new String[] { cfyBaseUrl, "secrets", "eom-dashboard-acl-token" }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getAclSecret: url {}", urlStr); + + ResponseEntity<CloudifySecret> response = cfyRest.exchange(urlStr, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifySecret>() { + }); + acl_token = response.getBody().getValue(); + } catch (MalformedURLException me) { + //throw new RuntimeException("Failed to parse URL", ex); + logger.error(EELFLoggerDelegate.errorLogger, "Failed to parse URL - malformed" + me.getMessage()); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + acl_token = ""; + } + } + return acl_token; + } + + protected RestTemplate createCfyRestTemplate(URL url, String user, String pass, String urlScheme) throws Exception { + RestTemplate restTempl = null; + final HttpHost httpHost = new HttpHost(url.getHost(), url.getPort(), urlScheme); + // Build a client with a credentials provider + CloseableHttpClient httpClient = null; + + if (user != null && pass != null) { + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(new AuthScope(httpHost), new UsernamePasswordCredentials(user, pass)); + httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(credsProvider).build(); + } else { + httpClient = HttpClientBuilder.create().build(); + } + // Create request factory + HttpComponentsClientHttpRequestFactoryBasicAuth requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth( + httpHost); + requestFactory.setHttpClient(httpClient); + restTempl = new RestTemplate(); + restTempl.setRequestFactory(requestFactory); + return restTempl; + } + + /** + * @param consul_acl_token the consul_acl_token to set + */ + public void setConsul_acl_token(String consul_acl_token) { + this.consul_acl_token = consul_acl_token; + } + @Override public List<ConsulServiceHealth> getServiceHealth(String dc, String srvc) { String url = buildUrl(new String[] { baseUrl, API_VER, HEALTH, CHECKS, srvc }, new String[] { "dc", dc }); logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealth: url {}", url); - ResponseEntity<List<ConsulServiceHealth>> response = restTemplate.exchange(url, HttpMethod.GET, null, + ResponseEntity<List<ConsulServiceHealth>> response = null; + try { + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, + new ParameterizedTypeReference<List<ConsulServiceHealth>>() { + }); + } catch (HttpStatusCodeException e) { + if (e.getStatusCode().value() == 403) { + // update consul ACL token header and retry + consul_acl_token = getConsulAcl(); + if (consul_acl_token != null && !consul_acl_token.isEmpty()) { + token_entity = getConsulTokenHeader(consul_acl_token); + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, + new ParameterizedTypeReference<List<ConsulServiceHealth>>() { + }); + } else { + throw e; + } + } + } + if (!response.getBody().isEmpty()) { + return response.getBody(); + } else { + return null; + } + } + + @Override + public ConsulDeploymentHealth getServiceHealthByDeploymentId(String deploymentId) { + String url = buildUrl(new String[] { baseUrl, API_VER, HEALTH, STATE, ANY }, + new String[] {"filter", "ServiceTags contains " + "\"" + deploymentId + "\""}); + logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealthByDeploymentId: url {}", url); + ResponseEntity<List<ConsulServiceHealth>> response = null; + try { + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, new ParameterizedTypeReference<List<ConsulServiceHealth>>() { }); - return response.getBody(); + } catch (HttpStatusCodeException e) { + if (e.getStatusCode().value() == 403) { + // update consul ACL token header and retry + consul_acl_token = getConsulAcl(); + if (consul_acl_token != null && !consul_acl_token.isEmpty()) { + token_entity = getConsulTokenHeader(consul_acl_token); + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, + new ParameterizedTypeReference<List<ConsulServiceHealth>>() { + }); + } else { + throw e; + } + } + } + if (!response.getBody().isEmpty()) { + return new ConsulDeploymentHealth.Builder(response.getBody().get(0)).build(); + } else { + return null; + } } @Override public List<ConsulServiceInfo> getServices(String dc) { String url = buildUrl(new String[] { baseUrl, API_VER, CATALOG, SERVICES }, new String[] { "dc", dc }); logger.debug(EELFLoggerDelegate.debugLogger, "getServices: url {}", url); - ResponseEntity<Map<String, Object>> response = restTemplate.exchange(url, HttpMethod.GET, null, + ResponseEntity<Map<String, Object>> response = null; + try { + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, new ParameterizedTypeReference<Map<String, Object>>() { }); - Map<String, Object> serviceInfo = response.getBody(); - List<ConsulServiceInfo> list = new ArrayList<>(); - for (Map.Entry<String, Object> entry : serviceInfo.entrySet()) { - // Be defensive - List<String> addrs = null; - if (entry.getValue() instanceof List<?>) - addrs = (List<String>) entry.getValue(); - else - addrs = new ArrayList<>(); - list.add(new ConsulServiceInfo(entry.getKey(), addrs)); - } - return list; + } catch (HttpStatusCodeException e) { + if (e.getStatusCode().value() == 403) { + // update consul ACL token header and retry + consul_acl_token = getConsulAcl(); + if (consul_acl_token != null && !consul_acl_token.isEmpty()) { + token_entity = getConsulTokenHeader(consul_acl_token); + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, + new ParameterizedTypeReference<Map<String, Object>>() { + }); + } else { + throw e; + } + } + } + if (!response.getBody().isEmpty()) { + Map<String, Object> serviceInfo = response.getBody(); + List<ConsulServiceInfo> list = new ArrayList<>(); + for (Map.Entry<String, Object> entry : serviceInfo.entrySet()) { + // Be defensive + List<String> addrs = null; + if (entry.getValue() instanceof List<?>) + addrs = (List<String>) entry.getValue(); + else + addrs = new ArrayList<>(); + list.add(new ConsulServiceInfo(entry.getKey(), addrs)); + } + return list; + } else { + return null; + } } @Override public List<ConsulNodeInfo> getNodes(String dc) { String url = buildUrl(new String[] { baseUrl, API_VER, CATALOG, "nodes" }, new String[] { "dc", dc }); logger.debug(EELFLoggerDelegate.debugLogger, "getNodesHealth: url {}", url); - ResponseEntity<List<ConsulNodeInfo>> response = restTemplate.exchange(url, HttpMethod.GET, null, + ResponseEntity<List<ConsulNodeInfo>> response = null; + try { + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, new ParameterizedTypeReference<List<ConsulNodeInfo>>() { }); - return response.getBody(); + } catch (HttpStatusCodeException e) { + if (e.getStatusCode().value() == 403) { + // update consul ACL token header and retry + consul_acl_token = getConsulAcl(); + if (consul_acl_token != null && !consul_acl_token.isEmpty()) { + token_entity = getConsulTokenHeader(consul_acl_token); + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, + new ParameterizedTypeReference<List<ConsulNodeInfo>>() { + }); + } else { + throw e; + } + } + } + if (!response.getBody().isEmpty()) { + return response.getBody(); + } else { + return null; + } } @Override public List<ConsulServiceHealth> getNodeServicesHealth(String dc, String nodeId) { String url = buildUrl(new String[] { baseUrl, API_VER, HEALTH, "node", nodeId }, new String[] { "dc", dc }); logger.debug(EELFLoggerDelegate.debugLogger, "getNodeServicesHealth: url {}", url); - ResponseEntity<List<ConsulServiceHealth>> response = restTemplate.exchange(url, HttpMethod.GET, null, + ResponseEntity<List<ConsulServiceHealth>> response = null; + try { + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, new ParameterizedTypeReference<List<ConsulServiceHealth>>() { }); - return response.getBody(); + } catch (HttpStatusCodeException e) { + if (e.getStatusCode().value() == 403) { + // update consul ACL token header and retry + consul_acl_token = getConsulAcl(); + if (consul_acl_token != null && !consul_acl_token.isEmpty()) { + token_entity = getConsulTokenHeader(consul_acl_token); + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, + new ParameterizedTypeReference<List<ConsulServiceHealth>>() { + }); + } else { + throw e; + } + } + } + if (!response.getBody().isEmpty()) { + return response.getBody(); + } else { + return null; + } } @Override public List<ConsulDatacenter> getDatacenters() { String url = buildUrl(new String[] { baseUrl, API_VER, CATALOG, "datacenters" }, null); logger.debug(EELFLoggerDelegate.debugLogger, "getDatacentersHealth: url {}", url); - ResponseEntity<List<String>> response = restTemplate.exchange(url, HttpMethod.GET, null, + ResponseEntity<List<String>> response = null; + try { + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, new ParameterizedTypeReference<List<String>>() { }); - List<String> list = response.getBody(); - List<ConsulDatacenter> result = new ArrayList<>(); - for (String dc : list) - result.add(new ConsulDatacenter(dc)); - return result; - } - - @Override - public String registerService(ConsulHealthServiceRegistration registration) { - String url = buildUrl(new String[] { baseUrl, API_VER, "/agent/service/register" }, null); - logger.debug(EELFLoggerDelegate.debugLogger, "registerService: url {}", url); - String resultStr = ""; - JSONObject outputJson = new JSONObject(); - JSONObject checkObject = new JSONObject(); - List<EndpointCheck> checks = registration.services.get(0).checks; - String service_name = registration.services.get(0).name; - String service_port = registration.services.get(0).port; - String service_address = registration.services.get(0).address; - List<String> tags = registration.services.get(0).tags; - - outputJson.put("Name", service_name); - outputJson.put("ID", service_name); - outputJson.put("Port", Integer.parseInt(service_port)); - outputJson.put("Address", service_address); - outputJson.put("Tags", tags); - - if (checks.size() == 1) { - checkObject.put("HTTP", checks.get(0).endpoint); - checkObject.put("Interval", checks.get(0).interval); - if (!checks.get(0).description.isEmpty()) - checkObject.put("Notes", checks.get(0).description); - checkObject.put("ServiceID", service_name); - outputJson.put("Check", checkObject); - } else { - JSONArray checks_new = new JSONArray(); - for (EndpointCheck check : checks) { - checkObject.put("HTTP", check.endpoint); - checkObject.put("Interval", check.endpoint); - if (!check.description.isEmpty()) - checkObject.put("Notes", check.description); - checkObject.put("ServiceID", service_name); - checks_new.put(checkObject); + } catch (HttpStatusCodeException e) { + if (e.getStatusCode().value() == 403) { + // update consul ACL token header and retry + consul_acl_token = getConsulAcl(); + if (consul_acl_token != null && !consul_acl_token.isEmpty()) { + token_entity = getConsulTokenHeader(consul_acl_token); + response = restTemplate.exchange(url, HttpMethod.GET, token_entity, + new ParameterizedTypeReference<List<String>>() { + }); + } else { + throw e; + } } - outputJson.put("Checks", checks_new); } - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity<String> entity = new HttpEntity<String>(outputJson.toString(), headers); - ResponseEntity<JSONObject> result = restTemplate.exchange(url, HttpMethod.PUT, entity, - new ParameterizedTypeReference<JSONObject>() { - }); - try { - resultStr = objectMapper.writeValueAsString(result); - } catch (JsonProcessingException e) { - - } finally { - } - return resultStr; + if (!response.getBody().isEmpty()) { + List<String> list = response.getBody(); + List<ConsulDatacenter> result = new ArrayList<>(); + for (String dc : list) + result.add(new ConsulDatacenter(dc)); + return result; + } else { + return null; + } } - @Override - public int deregisterService(String serviceName) { - String url = buildUrl(new String[] { baseUrl, API_VER, "/agent/service/deregister", serviceName }, null); - logger.debug(EELFLoggerDelegate.debugLogger, "deregisterService: url {}", url); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity<String> entity = new HttpEntity<String>(headers); - ResponseEntity<JSONObject> result = restTemplate.exchange(url, HttpMethod.PUT, entity, - new ParameterizedTypeReference<JSONObject>() { - }); - return result.getStatusCode().value(); - } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClient.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClient.java index 0804e9a..012ec32 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClient.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClient.java @@ -23,6 +23,8 @@ package org.onap.ccsdk.dashboard.rest; import java.util.stream.Stream; +import javax.servlet.http.HttpServletRequest; + import org.onap.ccsdk.dashboard.exceptions.BadRequestException; import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException; import org.onap.ccsdk.dashboard.exceptions.DownstreamException; @@ -35,6 +37,11 @@ import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse; public interface DeploymentHandlerClient { /** + * Run deployment handler service health check + * + */ + public String checkHealth(); + /** * Gets a list of all service deployments known to the orchestrator. * * @return Stream<String> @@ -65,17 +72,16 @@ public interface DeploymentHandlerClient { * /dcae-deployments/{deploymentId} * */ - public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest) + public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest, + HttpServletRequest request) throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException; /** - * Initiate update for a deployment + * For API use, Request deployment of a DCAE Service. * * @param deploymentId Unique deployment identifier assigned by the API * client. * - * @param tenant Cloudify tenant where the deployment should be done - * * @param deploymentRequest Deployment request object that contains the * necessary fields for service deployment. * @@ -83,7 +89,7 @@ public interface DeploymentHandlerClient { * /dcae-deployments/{deploymentId} * */ - public DeploymentResponse updateDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest) + public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest) throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException; /** @@ -93,6 +99,16 @@ public interface DeploymentHandlerClient { * @param deploymentId Unique deployment identifier assigned by the API client. * */ + public void deleteDeployment(String deploymentId, String tenant, HttpServletRequest request) + throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException; + + /** + * For API use, Uninstall the DCAE service and remove all associated data from the + * orchestrator. + * + * @param deploymentId Unique deployment identifier assigned by the API client. + * + */ public void deleteDeployment(String deploymentId, String tenant) throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException; } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImpl.java index 6e9ecb4..803c710 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImpl.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImpl.java @@ -24,21 +24,35 @@ package org.onap.ccsdk.dashboard.rest; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Stream; import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; import org.onap.ccsdk.dashboard.exceptions.BadRequestException; import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException; import org.onap.ccsdk.dashboard.exceptions.DownstreamException; import org.onap.ccsdk.dashboard.exceptions.ServerErrorException; import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentErrorResponse; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentLink; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentsListResponse; import org.onap.ccsdk.dashboard.util.DashboardProperties; +import org.onap.portalsdk.core.objectcache.AbstractCacheManager; +import org.onap.portalsdk.core.web.support.UserUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -48,9 +62,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; -import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; @org.springframework.stereotype.Service public class DeploymentHandlerClientImpl extends RestClientBase implements DeploymentHandlerClient { @@ -59,13 +71,28 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo private static final String DEPLOYMENTS = "dcae-deployments"; private static final String UPDATE_PATH = "dcae-deployment-update"; + private static final String HEALTH_CHECK = "healthcheck"; + private static final String SERVICE_ID = "service-list"; + @Autowired + CloudifyClient cloudifyClient; + + private AbstractCacheManager cacheManager; + + @Autowired + public void setCacheManager(AbstractCacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + public AbstractCacheManager getCacheManager() { + return cacheManager; + } protected final ObjectMapper objectMapper = new ObjectMapper(); @PostConstruct public void init() { - String webapiUrl = DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_DHANDLER_URL); + String webapiUrl = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_DHANDLER_URL); if (webapiUrl == null) throw new IllegalArgumentException("Null URL not permitted"); URL url = null; @@ -82,6 +109,14 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo } + public String checkHealth() { + String url = buildUrl(new String[] { baseUrl, HEALTH_CHECK }, null); + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<String>() { + }); + return response.getBody(); + } + public Stream<DeploymentLink> getDeployments() { String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, null); ResponseEntity<DeploymentsListResponse> response = restTemplate.exchange(url, HttpMethod.GET, null, @@ -104,48 +139,19 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo @Override public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest) throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException { - String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS, deploymentId }, - new String[] { "cfy_tenant_name", tenant }); - try { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - ResponseEntity<DeploymentResponse> result = restTemplate.exchange(url, HttpMethod.PUT, - new HttpEntity<DeploymentRequest>(deploymentRequest, headers), - new ParameterizedTypeReference<DeploymentResponse>() { - }); - return result.getBody(); - } catch (HttpServerErrorException | HttpClientErrorException e) { - DeploymentErrorResponse errBody = null; - String errMsg = ""; - try { - errBody = objectMapper.readValue(e.getResponseBodyAsString(), DeploymentErrorResponse.class); - } catch (IOException e1) { - errBody = null; - } - if (errBody != null) { - errMsg = errBody.getMessage(); - } - StringBuilder errDetails = new StringBuilder(); - errDetails.append(e.getMessage()).append(" ").append(errMsg); - if (e.getStatusCode().value() == 400 || e.getStatusCode().value() == 415 - || e.getStatusCode().value() == 404) { - throw new BadRequestException(errDetails.toString()); - } else if (e.getStatusCode().value() == 409) { - throw new ServiceAlreadyExistsException(errDetails.toString()); - } else if (e.getStatusCode().value() == 500) { - throw new ServerErrorException(errDetails.toString()); - } else if (e.getStatusCode().value() == 502 || e.getStatusCode().value() == 504) { - throw new DownstreamException(errDetails.toString()); - } - } - return null; + return putDeployment(deploymentId, tenant, deploymentRequest, null); } - + @Override - public DeploymentResponse updateDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest) + public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest, + HttpServletRequest request) throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException { - String url = buildUrl(new String[] { baseUrl, UPDATE_PATH, deploymentId }, + String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS, deploymentId }, new String[] { "cfy_tenant_name", tenant }); + String user = ""; + if (request != null) { + user = UserUtils.getUserSession(request).getLoginId(); + } try { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); @@ -153,20 +159,71 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo new HttpEntity<DeploymentRequest>(deploymentRequest, headers), new ParameterizedTypeReference<DeploymentResponse>() { }); + //cache handling + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + List itemList = + (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenant); + List itemExecList = (List<CloudifyDeploymentExt>)getCacheManager().getObject( + SERVICE_ID + ":" + tenant + ":ext"); + List itemHelmList = (List<CloudifyDeploymentExt>)getCacheManager().getObject( + SERVICE_ID + ":" + tenant + ":helm"); + lock.readLock().unlock(); + if (itemList != null) { + // add the new resource into app cache + CloudifyDeployment cfyDepl = + cloudifyClient.getDeploymentResource(deploymentId, tenant); + lock.writeLock().lock(); + itemList.add(0, cfyDepl); + lock.writeLock().unlock(); + if (itemExecList != null) { + List<CloudifyDeployment> thisDep = new ArrayList<CloudifyDeployment>(); + thisDep.add(cfyDepl); + List<CloudifyDeploymentExt> thisDepExec = + cloudifyClient.updateWorkflowStatus(thisDep); + List<CloudifyDeploymentHelm> thisDepHelm = + cloudifyClient.updateHelmInfo(thisDep); + lock.writeLock().lock(); + itemExecList.add(0, thisDepExec.get(0)); + itemHelmList.add(0, thisDepHelm.get(0)); + lock.writeLock().unlock(); + } + // handle the owner deployment map cache + if (!user.isEmpty()) { + CloudifyDeployedTenant updDepl = + new CloudifyDeployedTenant(cfyDepl.id, cfyDepl.tenant_name, + cfyDepl.created_at, cfyDepl.updated_at); + lock.readLock().lock(); + Map<String, List<CloudifyDeployedTenant>> deplPerOwner = + (Map<String, List<CloudifyDeployedTenant>>) + getCacheManager().getObject("owner_deploy_map"); + lock.readLock().unlock(); + if (deplPerOwner != null) { + List<CloudifyDeployedTenant> currOwnedDepls = deplPerOwner.get(user); + if (currOwnedDepls != null) { + currOwnedDepls.add(0, updDepl); + } else { + currOwnedDepls = + new ArrayList<CloudifyDeployedTenant>(); + currOwnedDepls.add(updDepl); + } + lock.writeLock().lock(); + deplPerOwner.put(user, currOwnedDepls); + lock.writeLock().unlock(); + } else { + deplPerOwner = new HashMap<String, List<CloudifyDeployedTenant>>(); + List<CloudifyDeployedTenant> deplForBpAggr = new ArrayList<CloudifyDeployedTenant>(); + deplForBpAggr.add(updDepl); + deplPerOwner.put(user, deplForBpAggr); + } + } + } return result.getBody(); } catch (HttpServerErrorException | HttpClientErrorException e) { - DeploymentErrorResponse errBody = null; - String errMsg = ""; - try { - errBody = objectMapper.readValue(e.getResponseBodyAsString(), DeploymentErrorResponse.class); - } catch (IOException e1) { - errBody = null; - } - if (errBody != null) { - errMsg = errBody.getMessage(); - } + String errBody = null; + errBody = e.getResponseBodyAsString(); StringBuilder errDetails = new StringBuilder(); - errDetails.append(e.getMessage()).append(" ").append(errMsg); + errDetails.append(e.getMessage()).append(" ").append(errBody); if (e.getStatusCode().value() == 400 || e.getStatusCode().value() == 415 || e.getStatusCode().value() == 404) { throw new BadRequestException(errDetails.toString()); @@ -178,17 +235,62 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo throw new DownstreamException(errDetails.toString()); } } - return null; // Perhaps this should be a proper JSON error response. + return null; } @Override public void deleteDeployment(String deploymentId, String tenant) throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException { + deleteDeployment(deploymentId, tenant, null); + } + @Override + public void deleteDeployment(String deploymentId, String tenant, HttpServletRequest request) + throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException { String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS, deploymentId }, - new String[] { "cfy_tenant_name", tenant, "ignore_failure", "true" }); + new String[] { "cfy_tenant_name", tenant, "force_uninstall", "true" }); try { + String user = ""; + if (request != null) { + user = UserUtils.getUserSession(request).getLoginId(); + } restTemplate.exchange(url, HttpMethod.DELETE, null, new ParameterizedTypeReference<DeploymentResponse>() { }); + CloudifyDeployment cfyDepl = + cloudifyClient.getDeploymentResource(deploymentId, tenant); + // remove resource from app cache + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.readLock().lock(); + List itemList = + (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenant); + lock.readLock().unlock(); + if (itemList != null) { + lock.writeLock().lock(); + itemList.remove(cfyDepl); + getCacheManager().removeObject(SERVICE_ID + ":" + tenant); + // put updated collection back into cache + getCacheManager().putObject(SERVICE_ID + ":" + tenant, itemList); + lock.writeLock().unlock(); + } + // handle the owner deployment map cache + if (!user.isEmpty()) { + lock.readLock().lock(); + Map<String, List<CloudifyDeployedTenant>> deplPerOwner = + (Map<String, List<CloudifyDeployedTenant>>) + getCacheManager().getObject("owner_deploy_map"); + lock.readLock().unlock(); + if (deplPerOwner != null) { + List<CloudifyDeployedTenant> currOwnedDepls = deplPerOwner.get(user); + CloudifyDeployedTenant updDepl = + new CloudifyDeployedTenant(cfyDepl.id, cfyDepl.tenant_name, + cfyDepl.created_at, cfyDepl.updated_at); + if (currOwnedDepls != null) { + currOwnedDepls.remove(updDepl); + lock.writeLock().lock(); + deplPerOwner.put(user, currOwnedDepls); + lock.writeLock().unlock(); + } + } + } } catch (HttpServerErrorException | HttpClientErrorException e) { DeploymentErrorResponse errBody = null; String errMsg = ""; diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/InventoryClient.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/InventoryClient.java index 1b93bc7..8f19e9b 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/InventoryClient.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/InventoryClient.java @@ -37,6 +37,7 @@ import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; import org.onap.ccsdk.dashboard.model.inventory.ServiceType; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; /** * Defines the interface of the Inventory Client. @@ -44,12 +45,25 @@ import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; public interface InventoryClient { /** + * Run inventory service health check + * + */ + public String checkHealth(); + + /** + * Get and store in cache, list of all DCAE Service Type objects. + * + * @return void + */ + public void cacheServiceTypes(); + + /** * Gets a list of all DCAE Service Type objects. * * @return Collection<ServiceType> */ - public Stream<ServiceType> getServiceTypes(); - + public Stream<ServiceTypeSummary> getServiceTypes(); + /** * Gets a list of all DCAE Service Type objects that fall under a specified * filter. @@ -59,7 +73,7 @@ public interface InventoryClient { * * @return Collection<ServiceType> */ - public Stream<ServiceType> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams); + public Stream<ServiceTypeSummary> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams); /** * Inserts a new DCAE Service Type, or updates an existing instance associated @@ -117,7 +131,7 @@ public interface InventoryClient { * * @return Collection<Service> */ - public Stream<Service> getServices(); + //public Stream<Service> getServices(); /** * Gets a list of all DCAE Service objects that fall under a specified filter. @@ -127,7 +141,7 @@ public interface InventoryClient { * * @return Collection<Service> */ - public Stream<Service> getServices(ServiceQueryParams serviceQueryParams); + //public Stream<Service> getServices(ServiceQueryParams serviceQueryParams); /** * Gets a list of all DCAE Service References that match a service type filter. @@ -159,32 +173,8 @@ public interface InventoryClient { * @return Service */ - public Optional<Service> getService(String serviceId); - - /** - * Puts a new DCAE Service with the specified serviceId, or updates an existing - * DCAE Service corresponding to the specified serviceId. - * - * @param typeId Type ID of the associated DCAE Service Type - * - * @param service DCAE Service to be uploaded. - */ - public void putService(String typeId, Service service); - - /** - * Deletes an existing DCAE Service object corresponding to the specified - * serviceId. - * - * @param serviceId Service ID of the DCAE Service to be deleted. - * - * @exception ServiceNotFoundException Thrown if the DCAE Service is - * not found. - * - * @exception ServiceAlreadyDeactivatedException Thrown if the DCAE Service is - * already deactivated. - * - */ + //public Optional<Service> getService(String serviceId); - public void deleteService(String serviceId) throws ServiceNotFoundException, ServiceAlreadyDeactivatedException; + public String getBaseUrl(); } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestClientBase.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestClientBase.java index c7c1cdf..69fca94 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestClientBase.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestClientBase.java @@ -30,6 +30,7 @@ import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.web.client.RestTemplate; @@ -43,6 +44,13 @@ import org.springframework.web.client.RestTemplate; public class RestClientBase { protected RestTemplate restTemplate = null; + /** + * @param restTemplate the restTemplate to set + */ + public void setRestTemplate(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + protected void createRestTemplate(URL url, String user, String pass, String urlScheme) { RestTemplate restTempl = null; final HttpHost httpHost = new HttpHost(url.getHost(), url.getPort(), urlScheme); @@ -61,7 +69,9 @@ public class RestClientBase { HttpComponentsClientHttpRequestFactoryBasicAuth requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth( httpHost); requestFactory.setHttpClient(httpClient); - + //requestFactory.setReadTimeout(10000); + //requestFactory.setConnectionRequestTimeout(2000); + //requestFactory.setConnectTimeout(10000); // Put the factory in the template restTempl = new RestTemplate(); restTempl.setRequestFactory(requestFactory); @@ -111,4 +121,16 @@ public class RestClientBase { headers.set("Tenant", tenant); return new HttpEntity<String>("parameters", headers); } + + /** + * Create Http Entity for the consul token header + * + * @param token string + * @return + */ + protected HttpEntity<String> getConsulTokenHeader(String token) { + HttpHeaders headers = new HttpHeaders(); + headers.set("X-Consul-Token", token); + return new HttpEntity<String>("parameters", headers); + } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImpl.java index c1296f0..100170c 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImpl.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImpl.java @@ -28,51 +28,61 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Predicate; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.PostConstruct; -import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceAlreadyDeactivatedException; -import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceNotFoundException; import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException; import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException; import org.onap.ccsdk.dashboard.model.inventory.ApiResponseMessage; -import org.onap.ccsdk.dashboard.model.inventory.InventoryProperty; import org.onap.ccsdk.dashboard.model.inventory.Link; import org.onap.ccsdk.dashboard.model.inventory.Service; -import org.onap.ccsdk.dashboard.model.inventory.ServiceGroupByResults; import org.onap.ccsdk.dashboard.model.inventory.ServiceList; import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; import org.onap.ccsdk.dashboard.model.inventory.ServiceRef; import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; -import org.onap.ccsdk.dashboard.model.inventory.ServiceRequest; import org.onap.ccsdk.dashboard.model.inventory.ServiceType; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList; import org.onap.ccsdk.dashboard.util.DashboardProperties; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.objectcache.AbstractCacheManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; import org.springframework.web.client.HttpClientErrorException; @org.springframework.stereotype.Service +@Component public class RestInventoryClientImpl extends RestClientBase implements InventoryClient { - + private static EELFLoggerDelegate logger = + EELFLoggerDelegate.getLogger(RestInventoryClientImpl.class); + private String baseUrl; public static final String SERVICE_TYPES = "dcae-service-types"; public static final String SERVICES = "dcae-services"; public static final String SERVICES_GROUPBY = "dcae-services-groupby"; + public static final String HEALTH_CHECK = "healthcheck"; + /** + * For caching data + */ + private AbstractCacheManager cacheManager; + @PostConstruct public void init() { - String webapiUrl = DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_INVENTORY_URL); + String webapiUrl = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_INVENTORY_URL); if (webapiUrl == null) throw new IllegalArgumentException("Null URL not permitted"); URL url = null; @@ -90,28 +100,74 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory } - public Stream<ServiceType> getServiceTypes() { - String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, null); - ResponseEntity<ServiceTypeList> response = restTemplate.exchange(url, HttpMethod.GET, null, - new ParameterizedTypeReference<ServiceTypeList>() { + public String checkHealth() { + String url = buildUrl(new String[] { baseUrl, HEALTH_CHECK }, null); + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<String>() { }); - Collection<ServiceType> collection = response.getBody().items; - + return response.getBody(); + } + + @Scheduled(fixedDelay=300000, initialDelay=30000) + public void cacheServiceTypes() { + logger.debug(EELFLoggerDelegate.debugLogger, "cacheServiceTypes begin"); + String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, new String[] {"onlyLatest", "false"}); + ResponseEntity<ServiceTypeSummaryList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<ServiceTypeSummaryList>() { + }); + Collection<ServiceTypeSummary> collection = response.getBody().items; // Continue retrieving items on the next page if they exist Link nextLink = response.getBody().paginationLinks.nextLink; while (nextLink != null) { url = response.getBody().paginationLinks.nextLink.href; response = restTemplate.exchange(url, HttpMethod.GET, null, - new ParameterizedTypeReference<ServiceTypeList>() { + new ParameterizedTypeReference<ServiceTypeSummaryList>() { }); collection.addAll(response.getBody().items); nextLink = response.getBody().paginationLinks.nextLink; } + ReadWriteLock lock = new ReentrantReadWriteLock(); + // put into cache + lock.writeLock().lock(); + getCacheManager().putObject(SERVICE_TYPES, collection); + lock.writeLock().unlock(); + logger.debug(EELFLoggerDelegate.debugLogger, "cacheServiceTypes end"); + } + public Stream<ServiceTypeSummary> getServiceTypes() { + String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, new String[] {"onlyLatest", "false"}); + ResponseEntity<ServiceTypeSummaryList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<ServiceTypeSummaryList>() { + }); + Collection<ServiceTypeSummary> collection = response.getBody().items; + // Continue retrieving items on the next page if they exist + Link nextLink = response.getBody().paginationLinks.nextLink; + while (nextLink != null) { + url = response.getBody().paginationLinks.nextLink.href; + response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<ServiceTypeSummaryList>() { + }); + collection.addAll(response.getBody().items); + nextLink = response.getBody().paginationLinks.nextLink; + } + ReadWriteLock lock = new ReentrantReadWriteLock(); + // put into cache + lock.writeLock().lock(); + getCacheManager().putObject(SERVICE_TYPES, collection); + lock.writeLock().unlock(); return collection.stream(); } + + @Autowired + public void setCacheManager(AbstractCacheManager cacheManager) { + this.cacheManager = cacheManager; + } - public Stream<ServiceType> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams) { + public AbstractCacheManager getCacheManager() { + return cacheManager; + } + + public Stream<ServiceTypeSummary> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams) { // Only utilize the parameters that aren't null HashMap<String, String> map = new HashMap<>(); @@ -139,6 +195,12 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory if (serviceTypeQueryParams.getAsdcResourceId() != null) { map.put("asdcResourceId", serviceTypeQueryParams.getAsdcResourceId()); } + if (serviceTypeQueryParams.getApplication() != null) { + map.put("application", serviceTypeQueryParams.getApplication()); + } + if (serviceTypeQueryParams.getComponent() != null) { + map.put("component", serviceTypeQueryParams.getComponent()); + } ArrayList<String> params = new ArrayList<>(); for (Entry<String, String> ent : map.entrySet()) { params.add(ent.getKey()); @@ -146,17 +208,17 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory } String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, params.toArray(new String[params.size()])); - ResponseEntity<ServiceTypeList> response = restTemplate.exchange(url, HttpMethod.GET, null, - new ParameterizedTypeReference<ServiceTypeList>() { + ResponseEntity<ServiceTypeSummaryList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<ServiceTypeSummaryList>() { }); - Collection<ServiceType> collection = response.getBody().items; + Collection<ServiceTypeSummary> collection = response.getBody().items; // Continue retrieving items on the next page if they exist Link nextLink = response.getBody().paginationLinks.nextLink; while (nextLink != null) { url = response.getBody().paginationLinks.nextLink.href; response = restTemplate.exchange(url, HttpMethod.GET, null, - new ParameterizedTypeReference<ServiceTypeList>() { + new ParameterizedTypeReference<ServiceTypeSummaryList>() { }); collection.addAll(response.getBody().items); nextLink = response.getBody().paginationLinks.nextLink; @@ -170,14 +232,31 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory // Take the ServiceType object and create a ServiceTypeRequest from it ServiceTypeRequest serviceTypeRequest = ServiceTypeRequest.from(serviceType); - - return restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class); + ServiceType upldBp = restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class); + List<ServiceTypeSummary> itemList = this.getServiceTypes().collect(Collectors.toList()); + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.writeLock().lock(); + getCacheManager().removeObject(SERVICE_TYPES); + // put updated collection back into cache + getCacheManager().putObject(SERVICE_TYPES, itemList); + lock.writeLock().unlock(); + return upldBp; } + @SuppressWarnings("unchecked") public ServiceType addServiceType(ServiceTypeRequest serviceTypeRequest) { String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, null); - - return restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class); + ServiceType uplBp = restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class); + // update application cache with new record to refresh screen immediately + // query inventory for the newly uploaded entry, + // using query params (typeName, owner, app, component) + List<ServiceTypeSummary> itemList = this.getServiceTypes().collect(Collectors.toList()); + ReadWriteLock lock = new ReentrantReadWriteLock(); + lock.writeLock().lock(); + // put updated collection back into cache + getCacheManager().putObject(SERVICE_TYPES, itemList); + lock.writeLock().unlock(); + return uplBp; } public Optional<ServiceType> getServiceType(String typeId) { @@ -188,12 +267,33 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory return Optional.ofNullable(response.getBody()); } + @SuppressWarnings("unchecked") public void deleteServiceType(String typeId) throws ServiceTypeNotFoundException, ServiceTypeAlreadyDeactivatedException { String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES, typeId }, null); + ReadWriteLock lock = new ReentrantReadWriteLock(); try { - restTemplate.exchange(url, HttpMethod.DELETE, null, new ParameterizedTypeReference<ApiResponseMessage>() { + ResponseEntity<ApiResponseMessage> response = + restTemplate.exchange(url, HttpMethod.DELETE, null, + new ParameterizedTypeReference<ApiResponseMessage>() { }); + // update the application cache + lock.readLock().lock(); + List<ServiceTypeSummary> itemList = + (List<ServiceTypeSummary>)getCacheManager().getObject(SERVICE_TYPES); + lock.readLock().unlock(); + if (itemList == null) { + itemList = getServiceTypes().collect(Collectors.toList()); + } + Predicate<ServiceTypeSummary> typeIdFilter = + p -> p.getTypeId().isPresent() && !p.getTypeId().get().equals(typeId); + itemList = (List<ServiceTypeSummary>)itemList.stream().filter(typeIdFilter). + collect(Collectors.toList()); + lock.writeLock().lock(); + getCacheManager().removeObject(SERVICE_TYPES); + // put updated collection back into cache + getCacheManager().putObject(SERVICE_TYPES, itemList); + lock.writeLock().unlock(); } catch (HttpClientErrorException e) { if (e.getStatusCode().value() == 410) { throw new ServiceTypeAlreadyDeactivatedException(e.getMessage()); @@ -203,7 +303,7 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory } } - public Stream<Service> getServices() { +/* public Stream<Service> getServices() { String url = buildUrl(new String[] { baseUrl, SERVICES }, null); ResponseEntity<ServiceList> response = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<ServiceList>() { @@ -222,7 +322,7 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory return collection.stream(); } - +*/ public ServiceRefList getServicesForType(ServiceQueryParams serviceQueryParams) { // Only utilize the typeId @@ -257,7 +357,7 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory return new ServiceRefList(srvcRefList, itemCnt); } - +/* public Stream<Service> getServices(ServiceQueryParams serviceQueryParams) { // Only utilize the parameters that aren't null @@ -308,43 +408,22 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory return collection.stream(); } - /* - * public Set<InventoryProperty> getPropertiesOfServices(String propertyName) { - * String url = buildUrl(new String[] {baseUrl, SERVICES_GROUPBY, propertyName}, - * null); ResponseEntity<ServiceGroupByResults> response = - * restTemplate.exchange(url, HttpMethod.GET, null, new - * ParameterizedTypeReference<ServiceGroupByResults>() { }); return - * response.getBody().propertyValues; } - */ public Optional<Service> getService(String serviceId) { String url = buildUrl(new String[] { baseUrl, SERVICES, serviceId }, null); - ResponseEntity<Service> response = restTemplate.exchange(url, HttpMethod.GET, null, - new ParameterizedTypeReference<Service>() { - }); - return Optional.ofNullable(response.getBody()); - } - - public void putService(String typeId, Service service) { - String url = buildUrl(new String[] { baseUrl, SERVICES, service.getServiceId() }, null); - - ServiceRequest serviceRequest = ServiceRequest.from(typeId, service); - - restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<ServiceRequest>(serviceRequest), - new ParameterizedTypeReference<Service>() { - }); - } - - public void deleteService(String serviceId) throws ServiceNotFoundException, ServiceAlreadyDeactivatedException { - String url = buildUrl(new String[] { baseUrl, SERVICES, serviceId }, null); + ResponseEntity<Service> response = null; try { - restTemplate.exchange(url, HttpMethod.DELETE, null, new ParameterizedTypeReference<ApiResponseMessage>() { - }); - } catch (HttpClientErrorException e) { - if (e.getStatusCode().value() == 410) { - throw new ServiceAlreadyDeactivatedException(e.getMessage()); - } else if (e.getStatusCode().value() == 404) { - throw new ServiceNotFoundException(e.getMessage()); - } + response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<Service>() { + }); + } + catch(HttpClientErrorException e) { + return null; } + + return Optional.ofNullable(response.getBody()); + } + */ + public String getBaseUrl() { + return this.baseUrl; } } diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointService.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointService.java deleted file mode 100644 index b63f972..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointService.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ - -package org.onap.ccsdk.dashboard.service; - -import java.util.List; - -import org.onap.ccsdk.dashboard.domain.ControllerEndpoint; -import org.onap.ccsdk.dashboard.domain.EcdComponent; - -/** - * Provides methods for managing the user's selection of controller endpoint. - * - * No method throws a checked exception, in keeping with the Spring philosophy - * of throwing unchecked exceptions. - */ -public interface ControllerEndpointService { - - /** - * Gets the object for the specified user ID. - * - * @param userId Application user ID - * @return ControllerEndpointCredentials instance; null if none exists. - */ - ControllerEndpoint getControllerEndpointSelection(long userId); - - /** - * Creates or updates an entry for the user ID specified within the object. - * - * @param endpoint info to store. - */ - void updateControllerEndpointSelection(ControllerEndpoint endpoint); - - /** - * Deletes the object for the specified user ID. - * - * @param userId Application user ID - */ - void deleteControllerEndpointSelection(long userId); - - /** - * Gets all component names that are currently supported through ECOMPC - * dashboard - * - * @return Component instance list; - */ - public List<EcdComponent> getComponents(); - - /** - * - * Add a new component to support in ECOMPC platform - * - * @param component - */ - void insertComponent(EcdComponent component); -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointServiceImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointServiceImpl.java deleted file mode 100644 index 6eacb47..0000000 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointServiceImpl.java +++ /dev/null @@ -1,115 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ - -package org.onap.ccsdk.dashboard.service; - -import org.onap.ccsdk.dashboard.domain.ControllerEndpoint; -import org.onap.ccsdk.dashboard.domain.EcdComponent; - -import java.util.List; - -import org.onap.portalsdk.core.service.DataAccessService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * Complete controller endpoint information is in properties. The database just - * stores the user's selection. Users are not expected to enter credentials so - * this hybrid solution keeps credentials out of the database. - */ -@Service("controllerEndpointService") -@Transactional -public class ControllerEndpointServiceImpl implements ControllerEndpointService { - - @Autowired - private DataAccessService dataAccessService; - - /** - * @return Data access service - */ - public DataAccessService getDataAccessService() { - return dataAccessService; - } - - /** - * @param dataAccessService Data access service - */ - public void setDataAccessService(DataAccessService dataAccessService) { - this.dataAccessService = dataAccessService; - } - - /* - * (non-Javadoc) - * - * @see org.openecomp.controller.dashboard.service.ControllerEndpointService# - * getControllerEndpoint(java.lang.Integer) - */ - @Override - public ControllerEndpoint getControllerEndpointSelection(long userId) { - return (ControllerEndpoint) getDataAccessService().getDomainObject(ControllerEndpoint.class, userId, null); - } - - /* - * (non-Javadoc) - * - * @see org.openecomp.controller.dashboard.service.ControllerEndpointService# - * getComponents() - */ - @SuppressWarnings("unchecked") - @Override - public List<EcdComponent> getComponents() { - return dataAccessService.executeNamedQuery("getAllComponents", null, null); - } - - @Override - public void insertComponent(EcdComponent component) { - dataAccessService.saveDomainObject(component, null); - } - - /* - * (non-Javadoc) - * - * @see org.openecomp.controller.dashboard.service.ControllerEndpointService# - * updateControllerEndpoint(org.openecomp.controller.dashboard.domain. - * ControllerEndpoint) - */ - @Override - public void updateControllerEndpointSelection(ControllerEndpoint endpoint) { - getDataAccessService().saveDomainObject(endpoint, null); - } - - /* - * // (non-Javadoc) - * - * @see org.openecomp.controller.dashboard.service.ControllerEndpointService# - * deleteControllerEndpoint(java.lang.Integer) - */ - @Override - public void deleteControllerEndpointSelection(long userId) { - ControllerEndpoint dbEntry = (ControllerEndpoint) getDataAccessService() - .getDomainObject(ControllerEndpoint.class, userId, null); - if (dbEntry != null) - getDataAccessService().deleteDomainObject(dbEntry, null); - } - -} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/util/DashboardProperties.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/util/DashboardProperties.java index 35d5d01..d785ea5 100644 --- a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/util/DashboardProperties.java +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/util/DashboardProperties.java @@ -3,8 +3,6 @@ * * ================================================================================= * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * - * Modifications Copyright (C) 2019 IBM. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,83 +43,61 @@ import org.springframework.core.env.Environment; public class DashboardProperties { /** - * Key for property that indicates if test data should be used - */ - public static final String CONTROLLER_MOCK_DATA = "controller.mock.data"; - /** - * Key for property with list of controllers + * Key for property with list of sites */ - public static final String CONTROLLER_KEY_LIST = "controller.key.list"; + public static final String CONTROLLER_SITE_LIST = "controller.site.list"; /** - * Subkey for property with Controller name (description) + * Subkey for property with site name */ - public static final String CONTROLLER_SUBKEY_NAME = "name"; + public static final String SITE_SUBKEY_NAME = "name"; /** - * Subkey for property with Controller URL + * Subkey for property with Cloudify URL */ - public static final String CONTROLLER_SUBKEY_URL = "url"; + public static final String SITE_SUBKEY_CLOUDIFY_URL = "cloudify.url"; /** * Subkey for property with Inventory URL */ - public static final String CONTROLLER_SUBKEY_INVENTORY_URL = "inventory.url"; + public static final String SITE_SUBKEY_INVENTORY_URL = "inventory.url"; /** * Subkey for property with Deployment Handler URL */ - public static final String CONTROLLER_SUBKEY_DHANDLER_URL = "dhandler.url"; + public static final String SITE_SUBKEY_DHANDLER_URL = "dhandler.url"; /** * Subkey for property with Consul URL */ - public static final String CONTROLLER_SUBKEY_CONSUL_URL = "consul.url"; + public static final String SITE_SUBKEY_CONSUL_URL = "consul.url"; + /** + * Subkey for property with DBCL URL + */ + public static final String SITE_SUBKEY_DBCL_URL = "dbcl.url"; + /** + * Subkey for property with DBCL URL + */ + public static final String SITE_SUBKEY_FEED_URL = "feed_m.url"; /** * Subkey for property with Controller user name for authentication */ - public static final String CONTROLLER_SUBKEY_USERNAME = "username"; + public static final String SITE_SUBKEY_CLOUDIFY_USERNAME = "cloudify.username"; /** * Subkey for property with Controller password */ - public static final String CONTROLLER_SUBKEY_PASS = "password"; + public static final String SITE_SUBKEY_CLOUDIFY_PASS = "cloudify.password"; /** * Subkey for property with Controller password encryption status */ - public static final String CONTROLLER_SUBKEY_ENCRYPTED = "is_encrypted"; + public static final String SITE_SUBKEY_CLOUDIFY_ENCRYPTED = "is_encrypted"; + /** * Key for dashboard deployment environment - dev/uat/prod */ public static final String CONTROLLER_IN_ENV = "controller.env"; /** - * Key for cloudify tenant environment - */ - public static final String CLOUDIFY_TENANT_PRIM = "cloudify.tenant.primary"; - - /** - * Key for aic tenant environment - */ - public static final String AIC_TENANT_PRIM = "aic.tenant.primary"; - - /** - * Key for controller type: ATT or OS - */ - public static final String CONTROLLER_TYPE = "controller.type"; - - /** * Key for K8s deploy permission string * */ public static final String APP_K8S_PERM = "k8s.deploy.perm"; - public static final String OPS_K8S_URL = "ops.k8s.url"; - - public static final String OPS_GRAFANA_URL = "ops.grf.url"; - - public static final String OPS_CLOUDIFY_URL = "ops.cfy.url"; - - public static final String OPS_CONSUL_URL = "ops.cnsl.url"; - - public static final String OPS_PROMETHEUS_URL = "ops.prom.url"; - - public static final String OPS_DBCL_URL = "ops.dbcl.url"; - private static Environment environment; protected Environment getEnvironment() { @@ -133,7 +109,7 @@ public class DashboardProperties { */ @Autowired public void setEnvironment(final Environment environment) { - DashboardProperties.environment = environment; + this.environment = environment; } /** @@ -180,8 +156,8 @@ public class DashboardProperties { String listVal = getProperty(key); if (listVal == null) return null; - - return listVal.split("\\s*,\\s*"); + String[] vals = listVal.split("\\s*,\\s*"); + return vals; } /** @@ -197,4 +173,16 @@ public class DashboardProperties { return getProperty(key); } + /** + * Convenience method to get a property from the fake hierarchical key-value + * set. + * + * @param controllerKey First part of key + * @param propKey Second part of key + * @return Property value for key "controllerKey.propKey" + */ + public static String getControllerPropertyDef(final String controllerKey, final String propKey, String defVal) { + final String key = controllerKey + '.' + propKey; + return getPropertyDef(key, defVal); + } } diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/api/controller/NbApiControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/api/controller/NbApiControllerTest.java new file mode 100644 index 0000000..3c33bda --- /dev/null +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/api/controller/NbApiControllerTest.java @@ -0,0 +1,818 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.ccsdk.api.controller; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Stream; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.ccsdk.dashboard.core.MockUser; +import org.onap.ccsdk.dashboard.core.MockitoTestSuite; +import org.onap.ccsdk.dashboard.exceptions.BadRequestException; +import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException; +import org.onap.ccsdk.dashboard.exceptions.DownstreamException; +import org.onap.ccsdk.dashboard.exceptions.ServerErrorException; +import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException; +import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException; +import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceId; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList; +import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse; +import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks; +import org.onap.ccsdk.dashboard.model.inventory.Service; +import org.onap.ccsdk.dashboard.model.inventory.ServiceList; +import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRef; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; +import org.onap.ccsdk.dashboard.model.inventory.ServiceType; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest; +import org.onap.ccsdk.dashboard.rest.CloudifyClient; +import org.onap.ccsdk.dashboard.rest.ConsulClient; +import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient; +import org.onap.ccsdk.dashboard.rest.InventoryClient; +import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.util.CacheManager; +import org.powermock.modules.junit4.PowerMockRunner; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; + +@RunWith(PowerMockRunner.class) +public class NbApiControllerTest extends MockitoTestSuite { + + @Mock + InventoryClient inventoryClient; + + @Mock + DeploymentHandlerClient deploymentHandlerClient; + + @Mock + CloudifyClient cfyClient; + + @Mock + ConsulClient consulClient; + + @Mock + ServletUriComponentsBuilder uriBuilder; + + @InjectMocks + NbApiController subject = new NbApiController(); + + private HttpStatusCodeException httpException = + new HttpServerErrorException(HttpStatus.BAD_GATEWAY); + + protected final ObjectMapper objectMapper = new ObjectMapper(); + + HttpServletRequest mockedRequest; + HttpServletResponse mockedResponse; + + MockUser mockUser = new MockUser(); + ServiceList deplList = null; + Service deplItem = null; + + + ServiceTypeSummary bpItem, bpItem2 = null; + ServiceTypeSummaryList bpList, bpList2 = null; + ServiceType bpItemFull = null; + ServiceTypeList bpItemFullList = null; + ServiceTypeRequest bpUploadItem = null; + + BadRequestException badReqError; + ServiceAlreadyExistsException srvcExistError; + ServerErrorException serverError; + DownstreamException downStrmError; + JsonProcessingException jsonError; + DeploymentNotFoundException notFoundError; + private ServiceTypeNotFoundException serviceTypeException = + new ServiceTypeNotFoundException("Invalid blueprint"); + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + objectMapper.registerModule(new Jdk8Module()); + getExpectedDeployments(); + getExpectedBueprints(); + createBpUploadItem(); + mockedRequest = getMockedRequest(); + mockedResponse = getMockedResponse(); + badReqError = new BadRequestException("bad request"); + srvcExistError = new ServiceAlreadyExistsException("service already exists"); + serverError = new ServerErrorException("Error occured in server"); + downStrmError = new DownstreamException("error occured in downstream"); + notFoundError = new DeploymentNotFoundException("item not found"); + CacheManager testCache = new CacheManager(); + subject.setCacheManager(testCache); + User user = mockUser.mockUser(); + user.setLoginId("tester"); + StringBuffer urlBuff = new StringBuffer(); + urlBuff.append("http://orcl.com"); + //Mockito.when(mockedRequest.getRemoteUser()).thenReturn("tester"); + Mockito.when(mockedRequest.getRequestURL()).thenReturn(urlBuff); + } + + public void getExpectedDeployments() + throws JsonParseException, JsonMappingException, IOException { + + deplItem = new Service("dcae_dtiapi_1902", null, "1552335532348", "1552335532348", null, + "dummyVnfId", null, "dummyVnfType", "dummyLocation", "dcae_dtiapi_1902", null); + Collection<Service> items = new ArrayList<Service>(); + items.add(deplItem); + + String pageLinks = + "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}"; + ServiceList.PaginationLinks paginationLinks = + objectMapper.readValue(pageLinks, ServiceList.PaginationLinks.class); + int totalCount = 1; + deplList = new ServiceList(items, totalCount, paginationLinks); + + } + + public void getExpectedBueprints() + throws JsonParseException, JsonMappingException, IOException { + + /*bpItem = new ServiceTypeSummary.Builder().application("DCAE").component("dcae"). + typeName("xyz1731-helm-1906").owner("xyz1731").typeVersion(1906).build();*/ + + bpItem = new ServiceTypeSummary("xyz1730", "xyz1730-helm-1905", 1905, "DCAE", "dcae", "123-456-321", + "342343", true); + + bpItem2 = new ServiceTypeSummary("xyz1731", "xyz1731-helm-1906", 1906, "DCAE", "dcae", "123-456-789", + "342343", true); + bpItemFull = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906, + "tosca_definitions_version: cloudify_dsl_1_3", "", "DCAE", "dcae").build(); + + Collection<ServiceTypeSummary> items = new ArrayList<ServiceTypeSummary>(); + items.add(bpItem); + + Collection<ServiceTypeSummary> items2 = new ArrayList<ServiceTypeSummary>(); + items2.add(bpItem2); + + String pageLinks2 = + "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}"; + ServiceTypeSummaryList.PaginationLinks paginationLinks = + objectMapper.readValue(pageLinks2, ServiceTypeSummaryList.PaginationLinks.class); + int totalCount = 1; + bpList = new ServiceTypeSummaryList(items, totalCount, paginationLinks); + bpList2 = new ServiceTypeSummaryList(items2, totalCount, paginationLinks); + + } + + public void createBpUploadItem() { + bpUploadItem = ServiceTypeRequest.from(bpItemFull); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public final void testCreateBlueprint() throws Exception { + String bpTemplate = "tosca_definitions_version: cloudify_dsl_1_3"; + ServiceTypeUploadRequest bpUploadReq = + new ServiceTypeUploadRequest("dcae_user", "mod1", 2008, bpTemplate, "DCAE", "dcae"); + + when(inventoryClient.addServiceType(Matchers.<ServiceTypeRequest>any())) + .thenThrow(BlueprintParseException.class).thenThrow(httpException) + .thenThrow(Exception.class).thenReturn(bpItemFull); + + //when(mockedRequest.getRequestURI()).thenReturn("https://invt-svc:8080/dcae-service-types"); + String actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder); + assertTrue(actual.contains("error")); + actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder); + assertTrue(actual.contains("error")); + actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder); + assertTrue(actual.contains("error")); + actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder); + assertTrue(actual.contains("xyz")); + } + + @Test + public final void testCreateBlueprint_badReq() throws Exception { + String bpTemplate = "tosca_definitions_version: cloudify_dsl_1_3"; + ServiceTypeUploadRequest bpUploadReq = + new ServiceTypeUploadRequest("dcae_user", "mod1", 2008, bpTemplate, "DCAE", ""); + + when(inventoryClient.addServiceType(Matchers.<ServiceTypeRequest>any())) + .thenThrow(BlueprintParseException.class).thenThrow(httpException) + .thenThrow(Exception.class).thenReturn(null); + + String actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder); + assertTrue(actual.contains("error")); + } + + @Test + public final void testQueryBlueprint() throws Exception { + + Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull); + when(inventoryClient.getServiceType(Mockito.any())).thenReturn(optionBp).thenThrow(Exception.class); + + String actual = subject.queryBlueprint("123-343", mockedRequest, mockedResponse, uriBuilder); + assertTrue(actual.contains("xyz")); + + actual = subject.queryBlueprint("123-343", mockedRequest, mockedResponse, uriBuilder); + assertTrue(actual.contains("error")); + } + + @Test + public final void testGetTenants() throws Exception { + String tenantsList = + "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, " + + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], " + + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}"; + CloudifyTenantList sampleData = null; + try { + sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class); + } catch (Exception e) { + } + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + + Mockito.when(cfyClient.getTenants()).thenReturn(sampleData); + + String tenantStr = subject.getTenants(mockedRequest); + assertTrue(tenantStr.contains("dyh1b")); + } + + @Test + public final void testGetBlueprintsByPage() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + String filterStr = "{\"owner\": \"xyz1730\", \"name\": \"xyz1730-helm-1905\", \"id\": \"123\"}"; + + mockedRequest.addParameter("filters", filterStr); + mockedRequest.addParameter("sort", "name"); + + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + + Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet); + Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps); + + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class); + String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("xyz")); + + result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("error")); + } + + @Test + public final void testGetBlueprintsByPage_sortByOwner() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + mockedRequest.addParameter("sort", "owner"); + + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + + Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet); + Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps); + + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class); + String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("xyz")); + + result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("error")); + } + + @Test + public final void testGetBlueprintsByPage_sortByTypeId() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + mockedRequest.addParameter("sort", "typeId"); + + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + + Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet); + Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps); + + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class); + String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("xyz")); + + result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("error")); + } + + @Test + public final void testGetBlueprintsByPage_sortByCreated() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + mockedRequest.addParameter("sort", "created"); + + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + + Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet); + Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps); + + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class); + String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("xyz")); + + result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("error")); + } + + @Test + public final void testGetBlueprintsByPage_sortByVersion() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + mockedRequest.addParameter("sort", "typeVersion"); + + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + + Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet); + Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps); + + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class); + String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("xyz")); + + result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(result.contains("error")); + } + + @SuppressWarnings("unchecked") + @Test + public final void testGetDeployment() { + CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1"); + + List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>(); + items.add(cldDepl); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata); + + when(cfyClient.getDeployment(Mockito.any())).thenReturn(cldDeplList).thenThrow(Exception.class); + + String actual = subject.getDeployment("id1", mockedRequest); + assertTrue(actual.contains("id1")); + + actual = subject.getDeployment("id1", mockedRequest); + assertTrue(actual.contains("error")); + } + + @Test + public final void testGetDeploymentsByPage() throws Exception { + CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1"); + + List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>(); + items.add(cldDepl); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata); + + when(cfyClient.getDeploymentsWithFilter(Mockito.any())).thenReturn(items).thenThrow(Exception.class); + + String actual = subject.getDeploymentsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(actual.contains("id1")); + + actual = subject.getDeploymentsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse); + assertTrue(actual.contains("error")); + } + + @Test + public final void testGetDeploymentInputs() throws Exception { + CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1"); + + List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>(); + items.add(cldDepl); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata); + + when(cfyClient.getDeploymentInputs(Mockito.any(), Mockito.any())).thenReturn(cldDeplList).thenThrow(httpException).thenThrow(Exception.class); + + String actual = subject.getDeploymentInputs("dep_id", "tenant1", mockedRequest); + assertTrue(actual.contains("id1")); + + actual = subject.getDeploymentInputs("dep_id", "tenant1", mockedRequest); + assertTrue(actual.contains("error")); + + actual = subject.getDeploymentInputs("dep_id", "tenant1", mockedRequest); + assertTrue(actual.contains("error")); + + } + + @Test + public final void testGetServicesForType() throws Exception { + String testTypeIds = "44234234"; + ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434"); + Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>(); + expectedSrvcIds.add(expectedSrvc); + ServiceRefList expectedSrvcRefList = new ServiceRefList(expectedSrvcIds, 1); + + when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any())) + .thenReturn(expectedSrvcRefList); + String actual = subject.getServicesForType(mockedRequest, testTypeIds); + assertTrue(actual.contains(testTypeIds)); + } + + @SuppressWarnings("unchecked") + @Test + public final void testCreateDeployment() throws Exception { + Map<String, Object> inputs = new HashMap<>(); + inputs.put("key1", "value1"); + inputs.put("key2", "value2"); + inputs.put("key3", "value3"); + inputs.put("key4", 100); + + DeploymentInput deployInput1 = new DeploymentInput("component1", "tag1", + "xyz1731-helm-1906", 1906, "blueprintId", inputs, "tenant1", + null, true, true, true, false, true, false); + + DeploymentInput deployInput2 = new DeploymentInput("component1", "tag1", + "xyz1731-helm-1906", 1906, null, inputs, "tenant1", + null, true, true, true, false, true, false); + + DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status"); + DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink); + + Collection<ServiceTypeSummary> items = bpList2.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) + .thenReturn(sampleStream1); + +/* String actualResp0 = subject.createDeployment(mockedRequest, mockedResponse, deployInput2); + assertTrue(actualResp0.contains("error"));*/ + + Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull); + Mockito.when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(optionBp); + + StringBuffer expectedStrBuff = new StringBuffer(); + expectedStrBuff.append("http://oom.s2.com"); + when(mockedRequest.getRequestURL()).thenReturn(expectedStrBuff); + + when(deploymentHandlerClient.putDeployment(Matchers.anyString(), Matchers.anyString(), + Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenReturn(expectResp) + .thenThrow(badReqError) + .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError) + .thenThrow(Exception.class); + + String actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1); + assertTrue(actualResp.contains("component1")); + + actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput2); + assertTrue(actualResp.contains("component1")); + + actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1); + assertTrue(actualResp.contains("error")); + + actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1); + assertTrue(actualResp.contains("error")); + + actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1); + assertTrue(actualResp.contains("error")); + + actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1); + assertTrue(actualResp.contains("error")); + + actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1); + assertTrue(actualResp.contains("error")); + + } + + @Test + public final void testGetExecutionByDeploymentId() throws Exception { + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); + + cldExecutionList.add(cldExecution); + + CloudifyExecutionList cloudifyExecutionList = + new CloudifyExecutionList(cldExecutionList, null); + + when(cfyClient.getExecutionsSummary(Mockito.any(), Mockito.any())) + .thenReturn(cloudifyExecutionList).thenThrow(httpException).thenThrow(Exception.class);; + + String actual = subject.getExecutionByDeploymentId("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("execution_id1")); + + actual = subject.getExecutionByDeploymentId("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("error")); + + actual = subject.getExecutionByDeploymentId("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("error")); + + } + + @Test + public final void testGetServiceHealthByDeploymentId() throws Exception { + String[] svcTags = {"cfytenantname=onap"}; + ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00", + "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing", + "This is a pgaas1_Service_ID health check", + "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n", + "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395); + + ConsulDeploymentHealth cnslDeployHlth = + new ConsulDeploymentHealth.Builder(consulSrvcHlth).build(); + + when(consulClient.getServiceHealthByDeploymentId(Mockito.any())).thenReturn(cnslDeployHlth) + .thenThrow(httpException).thenThrow(Exception.class); + + String actual = subject.getServiceHealthByDeploymentId("deploymentId", mockedRequest); + assertTrue(actual.contains("cjlvmcnsl00")); + + actual = subject.getServiceHealthByDeploymentId("deploymentId", mockedRequest); + assertTrue(actual.contains("error")); + + actual = subject.getServiceHealthByDeploymentId("deploymentId", mockedRequest); + assertTrue(actual.contains("error")); + } + + @Test + public final void testDeleteBlueprint() throws Exception { + //String expected = "{\"202\": \"OK\"}"; + String expected = "{\"204\": \"Blueprint deleted\"}"; + List<CloudifyDeployedTenant> deplForBp = new ArrayList<>(); + deplForBp.clear(); + Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any())) + .thenReturn(deplForBp); + + Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull); + Mockito.when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(optionBp); + + List<ServiceRef> srvcRefList = new ArrayList<>(); + srvcRefList.clear(); + int itemCnt = 0; + ServiceRefList mockSvcRefList = new ServiceRefList(srvcRefList, itemCnt); + + Mockito.when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any())) + .thenReturn(mockSvcRefList); + + doNothing().doThrow(serviceTypeException).doThrow(Exception.class).when(inventoryClient) + .deleteServiceType(Matchers.anyString()); + + String actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder); + assertEquals(expected, actual); + + actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder); + assertTrue(actual.contains("error")); + + actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder); + assertTrue(actual.contains("error")); + } + + @Test + public final void testDeleteBlueprint_withDepl() throws Exception { + CloudifyDeployedTenant mockCfyDeplTen = + new CloudifyDeployedTenant("id1", "tenant", "45435435", "54543534"); + + Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull); + Mockito.when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(optionBp); + + List<CloudifyDeployedTenant> deplForBp = new ArrayList<>(); + deplForBp.add(mockCfyDeplTen); + Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any())) + .thenReturn(deplForBp); + + String actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder); + assertTrue(actual.contains("error")); + } + + @Test + public final void testDeleteDeployment() throws Exception { + CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "dcae_dep_id", null, null, null, null, null, null, null, "tenant1"); + + List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>(); + items.add(cldDepl); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata); + + Mockito.when(cfyClient.getDeployment(Matchers.anyString(), Matchers.anyString())).thenReturn(cldDeplList); + + doNothing().doThrow(badReqError).doThrow(serverError).doThrow(downStrmError) + .doThrow(notFoundError).doThrow(Exception.class).when(deploymentHandlerClient) + .deleteDeployment(Matchers.anyString(), Matchers.anyString()); + + String actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse); + assertTrue(actual.contains("dcae_dep_id")); + + actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse); + assertTrue(actual.contains("error")); + + actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse); + assertTrue(actual.contains("error")); + + actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse); + assertTrue(actual.contains("error")); + + actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse); + assertTrue(actual.contains("error")); + + actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse); + assertTrue(actual.contains("error")); + + } + + @SuppressWarnings("unchecked") + @Test + public void testCancelExecution() throws Exception { + List<String> tenants = new ArrayList<String>(); + tenants.add("tenant1"); + + HttpHeaders httpHeader = new HttpHeaders(); + httpHeader.put("tenant", tenants); + + CloudifyExecution cfyExecObj = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + when(cfyClient.cancelExecution(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException); + + String actualResult = + subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse); + assertTrue(actualResult.contains("execution_id1")); + + actualResult = + subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse); + assertTrue(actualResult.contains("error")); + + actualResult = + subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse); + assertTrue(actualResult.contains("error")); + } + + @SuppressWarnings("unchecked") + @Test + public final void testModifyDeployment() throws Exception { + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + Map<String, Object> params = new HashMap<String, Object>(); + params.put("tenant", "tenant1"); + params.put("workflow", "upgrade"); + + CloudifyExecutionRequest cfyExecReq = new CloudifyExecutionRequest("deployment_id", + "upgrade", false, false, "tenant1", params); + + CloudifyNodeInstanceId cfyNodeInst = new CloudifyNodeInstanceId("node_instance_id1"); + + List<CloudifyNodeInstanceId> cfyNodeInstItems = new ArrayList<CloudifyNodeInstanceId>(); + + cfyNodeInstItems.add(cfyNodeInst); + + CloudifyNodeInstanceIdList cfyNodeInstList = + new CloudifyNodeInstanceIdList(cfyNodeInstItems, null); + + when(cfyClient.getNodeInstanceId(Mockito.any(), Mockito.any())).thenReturn(cfyNodeInstList); + + String secretTokenStr = + "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}"; + CloudifySecret secretData = null; + try { + secretData = objectMapper.readValue(secretTokenStr, CloudifySecret.class); + } catch (Exception e) { + + } + when(cfyClient.getSecret(Mockito.any(), Mockito.any())).thenReturn(secretData); + when(cfyClient.startExecution(Matchers.<CloudifyExecutionRequest>any())) + .thenReturn(cldExecution).thenThrow(Exception.class).thenThrow(httpException); + + String inputParamStr = "{\"tenant\": \"tenant1\", \"workflow\":\"upgrade\"}"; + + InputStream is1 = new ByteArrayInputStream(inputParamStr.getBytes()); + String actualResult = subject.modifyDeployment("depId", mockedRequest, is1); + assertTrue(actualResult.contains("execution_id1")); + + InputStream is2 = new ByteArrayInputStream(inputParamStr.getBytes()); + actualResult = subject.modifyDeployment("depId", mockedRequest, is2); + assertTrue(actualResult.contains("error")); + + InputStream is3 = new ByteArrayInputStream(inputParamStr.getBytes()); + actualResult = subject.modifyDeployment("depId", mockedRequest, is3); + assertTrue(actualResult.contains("error")); + + } + +} diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CloudifyControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CloudifyControllerTest.java index d6e1fb0..d88e530 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CloudifyControllerTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CloudifyControllerTest.java @@ -22,16 +22,22 @@ package org.onap.ccsdk.dashboard.controller; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Matchers; import org.mockito.Mock; @@ -39,39 +45,51 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.onap.ccsdk.dashboard.core.MockUser; import org.onap.ccsdk.dashboard.core.MockitoTestSuite; -import org.onap.ccsdk.dashboard.model.CloudifyBlueprint; -import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployment; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse; -import org.onap.ccsdk.dashboard.model.CloudifyEvent; -import org.onap.ccsdk.dashboard.model.CloudifyEventList; -import org.onap.ccsdk.dashboard.model.CloudifyExecution; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstance; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceId; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList; -import org.onap.ccsdk.dashboard.model.CloudifyTenant; -import org.onap.ccsdk.dashboard.model.CloudifyTenantList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprint; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEvent; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstance; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceId; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPlugin; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList; +import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRef; +import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; import org.onap.ccsdk.dashboard.rest.CloudifyClient; +import org.onap.ccsdk.dashboard.rest.InventoryClient; import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.util.CacheManager; import org.onap.portalsdk.core.web.support.UserUtils; +import org.powermock.modules.junit4.PowerMockRunner; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.web.client.HttpClientErrorException; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +@RunWith(PowerMockRunner.class) public class CloudifyControllerTest extends MockitoTestSuite { @Mock private CloudifyClient restClient; + + @Mock + private InventoryClient invClient; @InjectMocks private CloudifyController subject = new CloudifyController(); @@ -93,6 +111,8 @@ public class CloudifyControllerTest extends MockitoTestSuite { MockitoAnnotations.initMocks(this); objectMapper.registerModule(new Jdk8Module()); httpException = new HttpClientErrorException(HttpStatus.BAD_REQUEST, "statusText"); + CacheManager testCache = new CacheManager(); + subject.setCacheManager(testCache); } @SuppressWarnings("unchecked") @@ -125,6 +145,409 @@ public class CloudifyControllerTest extends MockitoTestSuite { assertTrue(tenantStr.contains("error")); } + @Test + public final void testGetAllServiceNames() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + //mockedRequest.addParameter("searchBy", "xyz"); + mockedRequest.addParameter("sortBy", "owner"); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + + CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1"); + + List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>(); + items.add(cldDepl); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata); + + Mockito.when(restClient.getDeployments( + Mockito.any(),Mockito.anyInt(), Mockito.anyInt(), Mockito.anyBoolean())) + .thenReturn(items); + + String actual = subject.getAllServiceNames(mockedRequest); + assertTrue(actual.contains("id1")); + } + @Test + public final void testGetDeploymentsByPage() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + mockedRequest.addParameter("searchBy", "tenant:default_tenant;cache:false;serviceRef:id1"); + mockedRequest.addParameter("sortBy", "owner"); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + + CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1"); + + List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>(); + items.add(cldDepl); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata); + + Mockito.when(restClient.getDeployments( + Mockito.any(),Mockito.anyInt(), Mockito.anyInt(), Mockito.anyBoolean(), Mockito.anyBoolean())) + .thenReturn(items); + List<CloudifyDeploymentExt> cfyDepExList = + new ArrayList<CloudifyDeploymentExt>(); + List<CloudifyDeploymentHelm> cfyDeplHelmList = + new ArrayList<CloudifyDeploymentHelm>(); + + Mockito.when(restClient.updateWorkflowStatus(Mockito.any())). + thenReturn(cfyDepExList); + Mockito.when(restClient.updateHelmInfo(Mockito.any())). + thenReturn(cfyDeplHelmList); + + String actual = subject.getDeploymentsByPage(mockedRequest); + assertTrue(actual.contains("id1")); + } + + @Test + public final void testViewBlueprintContentById() throws Exception { + byte[] result = "sample blueprint yaml content".getBytes(); + + when(restClient.viewBlueprint(Mockito.any(), Mockito.any())).thenReturn(result); + + byte[] actual = subject.viewBlueprintContentById("id", "tenant", mockedRequest); + assertArrayEquals(result, actual); + } + + @Test + public final void testGetDepCount() throws Exception { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + //mockedRequest.addParameter("searchBy", "xyz"); + mockedRequest.addParameter("sortBy", "owner"); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + + CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1"); + + List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>(); + items.add(cldDepl); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata); + + Mockito.when(restClient.getDeploymentsWithFilter(Mockito.any())) + .thenReturn(items); + + String actual = subject.getDepCount(mockedRequest); + assertTrue(actual.contains("items")); + } + + @Test + public final void testGetPluginCount() throws JsonProcessingException { + CloudifyPlugin sampleData = + new CloudifyPlugin("plugin1", "202001", "linux", "linux_k8s_plugin", "20200801"); + + List<CloudifyPlugin> cfyPlugins = new ArrayList<CloudifyPlugin>(); + cfyPlugins.add(sampleData); + + CloudifyPluginList.Metadata.Pagination pageObj = + new CloudifyPluginList.Metadata.Pagination(1, 0, 1); + CloudifyPluginList.Metadata metadata = new CloudifyPluginList.Metadata(pageObj); + + CloudifyPluginList cfyPluginList = new CloudifyPluginList(cfyPlugins, metadata); + + when(restClient.getPlugins()).thenReturn(cfyPluginList); + String actual = subject.getPluginCount(mockedRequest); + assertTrue(actual.contains("1")); + } + + @Test + public final void testDeleteBlueprint() throws Exception { + String json = "{\"202\": \"OK\"}"; + + doNothing().doThrow(httpException).doThrow(Exception.class).when(restClient).deleteBlueprint(Mockito.any(), Mockito.any()); + + String actual = subject.deleteBlueprint("id", "tenant", mockedRequest, mockedResponse); + assertTrue(actual.equals(json)); + + actual = subject.deleteBlueprint("id", "tenant", mockedRequest, mockedResponse); + assertTrue(actual.contains("error")); + + actual = subject.deleteBlueprint("id", "tenant", mockedRequest, mockedResponse); + assertTrue(actual.contains("error")); + } + + @Test + public final void testGetDeploymentsForType() throws Exception { + String[] testTypeIds = {"44234234"}; + ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434"); + Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>(); + expectedSrvcIds.add(expectedSrvc); + ServiceRefList expectedSrvcRefList = new ServiceRefList(expectedSrvcIds, 1); + + CloudifyDeployedTenant cfyDepTen = + new CloudifyDeployedTenant("id", "tenant_name", "created_at", "updated_at"); + + List<CloudifyDeployedTenant> cfyDeplTenList = new ArrayList<>(); + cfyDeplTenList.add(cfyDepTen); + + when(restClient.getDeploymentForBlueprint(Mockito.any())).thenReturn(cfyDeplTenList); + + when(invClient.getServicesForType(Matchers.<ServiceQueryParams>any())) + .thenReturn(expectedSrvcRefList); + String actual = subject.getDeploymentsForType(mockedRequest, testTypeIds); + assertTrue(actual.contains(testTypeIds[0])); + } + + @Test + @Ignore + public final void testCacheOwnerDeployMap() { + + } + + @Test + public final void testGetExecutionsPerTenant() throws Exception { + String tenantsList = + "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, " + + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], " + + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}"; + CloudifyTenantList tenantData = null; + try { + tenantData = objectMapper.readValue(tenantsList, CloudifyTenantList.class); + } catch (Exception e) { + } + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(restClient.getTenants()).thenReturn(tenantData); + + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); + + cldExecutionList.add(cldExecution); + + CloudifyExecutionList cloudifyExecutionList = + new CloudifyExecutionList(cldExecutionList, null); + + when(restClient.getExecutionsSummaryPerTenant(Mockito.any())) + .thenReturn(cloudifyExecutionList).thenReturn(cloudifyExecutionList) + .thenReturn(cloudifyExecutionList); + + String actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "failed"); + assertFalse(actual.contains("execution_id1")); + actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "successful"); + assertTrue(actual.contains("execution_id1")); + actual = subject.getExecutionsPerTenant(mockedRequest, null, "successful"); + assertTrue(actual.contains("execution_id1")); + } + + @Test + public final void testGetExecutionsPerTenant_error() throws Exception { + String tenantsList = + "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, " + + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], " + + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}"; + CloudifyTenantList tenantData = null; + try { + tenantData = objectMapper.readValue(tenantsList, CloudifyTenantList.class); + } catch (Exception e) { + } + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(restClient.getTenants()).thenReturn(tenantData); + + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); + + cldExecutionList.add(cldExecution); + + CloudifyExecutionList cloudifyExecutionList = + new CloudifyExecutionList(cldExecutionList, null); + + when(restClient.getExecutionsSummaryPerTenant(Mockito.any())) + .thenThrow(Exception.class).thenThrow(Exception.class).thenThrow(Exception.class); + + String actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "failed"); + assertTrue(actual.contains("error")); + + actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "successful"); + assertTrue(actual.contains("error")); + + actual = subject.getExecutionsPerTenant(mockedRequest, null, "failed"); + assertTrue(actual.contains("error")); + } + + @Test + public final void testQueryExecution() throws Exception { + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); + cldExecutionList.add(cldExecution); + + when(restClient.getExecutionIdSummary( + Mockito.any(), Mockito.any())).thenReturn(cldExecution); + + String actual = subject.queryExecution("id", "tenant", mockedRequest); + assertTrue(actual.contains("items")); + } + + @SuppressWarnings("unchecked") + @Test + public final void testGetActiveExecutions() throws Exception { + String tenantsList = + "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, " + + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], " + + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}"; + CloudifyTenantList tenantData = null; + try { + tenantData = objectMapper.readValue(tenantsList, CloudifyTenantList.class); + } catch (Exception e) { + } + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(restClient.getTenants()).thenReturn(tenantData).thenThrow(Exception.class); + + CloudifyExecution cldExecution = + new CloudifyExecution("started", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); + + cldExecutionList.add(cldExecution); + + CloudifyExecutionList cloudifyExecutionList = + new CloudifyExecutionList(cldExecutionList, null); + + when(restClient.getExecutionsSummaryPerTenant(Mockito.any())) + .thenReturn(cloudifyExecutionList).thenReturn(cloudifyExecutionList); + + String actual = subject.getActiveExecutions(mockedRequest); + assertTrue(actual.contains("execution_id1")); + actual = subject.getActiveExecutions(mockedRequest); + assertTrue(actual.contains("error")); + + } + + @Test + public final void testGetNodeInstanceDetails() throws Exception { + + Map<String, Object> runtime_properties = + new HashMap<>(); + runtime_properties.put("key1", "value1"); + + CloudifyNodeInstance cfyNodeInst = + new CloudifyNodeInstance("node_instance_id1", runtime_properties); + + List<CloudifyNodeInstance> cfyNodeInstItems = new ArrayList<CloudifyNodeInstance>(); + + cfyNodeInstItems.add(cfyNodeInst); + + CloudifyNodeInstanceList cfyNodeInstList = + new CloudifyNodeInstanceList(cfyNodeInstItems, null); + + when(restClient.getNodeInstanceDetails(Mockito.any(), Mockito.any())). + thenReturn(cfyNodeInstList).thenThrow(httpException). + thenThrow(Exception.class); + + String actual = + subject.getNodeInstanceDetails("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("node_instance_id1")); + + actual = + subject.getNodeInstanceDetails("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("error")); + + actual = + subject.getNodeInstanceDetails("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("error")); + } + + @Test + public final void testGetNodeInstances() throws Exception { + CloudifyNodeInstanceId cfyNodeInst = new CloudifyNodeInstanceId("node_instance_id1"); + + List<CloudifyNodeInstanceId> cfyNodeInstItems = new ArrayList<CloudifyNodeInstanceId>(); + + cfyNodeInstItems.add(cfyNodeInst); + + CloudifyNodeInstanceIdList cfyNodeInstList = + new CloudifyNodeInstanceIdList(cfyNodeInstItems, null); + + when(restClient.getNodeInstances(Mockito.any(), Mockito.any())). + thenReturn(cfyNodeInstList).thenThrow(httpException). + thenThrow(Exception.class); + + String actual = + subject.getNodeInstances("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("node_instance_id1")); + + actual = + subject.getNodeInstances("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("error")); + + actual = + subject.getNodeInstances("deploymentId", "tenant", mockedRequest); + assertTrue(actual.contains("error")); + } + + @Test + public final void testGetPlugins() throws Exception { + CloudifyPlugin sampleData = + new CloudifyPlugin("plugin1", "202001", "linux", "linux_k8s_plugin", "20200801"); + + List<CloudifyPlugin> cfyPlugins = new ArrayList<CloudifyPlugin>(); + cfyPlugins.add(sampleData); + + CloudifyPluginList.Metadata.Pagination pageObj = + new CloudifyPluginList.Metadata.Pagination(1, 0, 1); + CloudifyPluginList.Metadata metadata = new CloudifyPluginList.Metadata(pageObj); + + CloudifyPluginList cfyPluginList = new CloudifyPluginList(cfyPlugins, metadata); + + when(restClient.getPlugins()).thenReturn(cfyPluginList).thenThrow(Exception.class); + String actual = subject.getPlugins(mockedRequest); + assertTrue(actual.contains("plugin1")); + + actual = subject.getPlugins(mockedRequest); + assertTrue(actual.contains("error")); + } + + @Test + @Ignore + public final void testGetSecrets() { + + } + + @Test + @Ignore + public final void testGetSecret() { + + } + + @Test + @Ignore + public final void testDeleteSecret() { + + } + + @Test + @Ignore + public final void testCreateSecret() { + } + @SuppressWarnings({"unchecked", "unchecked"}) @Test public final void testGetBlueprintById() throws Exception { @@ -196,93 +619,13 @@ public class CloudifyControllerTest extends MockitoTestSuite { actualResult = subject.getDeploymentById("id1", null, mockedRequest); assertTrue(actualResult.contains("error")); } - - @SuppressWarnings("unchecked") - @Test - public void testGetTenantStatusForService() throws Exception { - - String[] deplIds = {"id1", "id2"}; - - CloudifyDeployedTenant cldDeplTenant = new CloudifyDeployedTenant("id1", "bp1", "tenant1"); - - List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>(); - - cldDeplTenantList.add(cldDeplTenant); - - CloudifyDeployedTenantList cldDeployedTenantList = - new CloudifyDeployedTenantList(cldDeplTenantList, null); - - CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1"); - - List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>(); - cldfyTenantList.add(cldTenant); - - CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null); - - CloudifyExecution cldExecution = - new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1", - "tenant1", "error", "execution_id1", null, false, false); - - List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); - - cldExecutionList.add(cldExecution); - - CloudifyExecutionList cloudifyExecutionList = - new CloudifyExecutionList(cldExecutionList, null); - - Map<String, Object> plan = new HashMap<String, Object>(); - HashMap<String, String> plugins_to_install = new HashMap<String, String>(); - plugins_to_install.put("name", "helm-plugin"); - ArrayList<HashMap<String, String>> deployment_plugins_to_install = - new ArrayList<HashMap<String, String>>(); - - deployment_plugins_to_install.add(plugins_to_install); - plan.put("deployment_plugins_to_install", deployment_plugins_to_install); - - Map<String, String> workflows = new HashMap<String, String>(); - workflows.put("status", "workflowshelm"); - plan.put("workflows", workflows); - - CloudifyBlueprint cldBp = - new CloudifyBlueprint("file1", "description1", "343242", "3423423", "id1", plan); - - List<CloudifyBlueprint> items = new ArrayList<CloudifyBlueprint>(); - items.add(cldBp); - - CloudifyBlueprintList.Metadata.Pagination pageObj = - new CloudifyBlueprintList.Metadata.Pagination(1, 0, 1); - - CloudifyBlueprintList.Metadata metadata = new CloudifyBlueprintList.Metadata(pageObj); - - CloudifyBlueprintList cldBpList = new CloudifyBlueprintList(items, metadata); - - when(restClient.getTenants()).thenReturn(cloudifyTenantList); - - when(restClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList); - - when(restClient.getExecutionsSummary(Mockito.any(), Mockito.any())) - .thenReturn(cloudifyExecutionList); - - when(restClient.getBlueprint(Mockito.any(), Mockito.any())).thenReturn(cldBpList) - .thenThrow(Exception.class).thenThrow(httpException); - - String actualResult = subject.getTenantStatusForService(mockedRequest, deplIds); - assertTrue(actualResult.contains("successful")); - - actualResult = subject.getTenantStatusForService(mockedRequest, deplIds); - assertTrue(actualResult.contains("error")); - - actualResult = subject.getTenantStatusForService(mockedRequest, deplIds); - assertTrue(actualResult.contains("error")); - } - - @SuppressWarnings("unchecked") + @Test public void testGetExecutionsByPage() throws Exception { CloudifyExecution cldExecution = - new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1", - "tenant1", "error", "execution_id1", null, false, false); - + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); cldExecutionList.add(cldExecution); @@ -301,8 +644,8 @@ public class CloudifyControllerTest extends MockitoTestSuite { CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata); - - when(restClient.getDeployments()).thenReturn(cldDeployList); + + when(restClient.getDeployments(Mockito.any(), Mockito.anyInt(), Mockito.anyInt())).thenReturn(cldDeployList); when(restClient.getExecutions(Mockito.any(), Mockito.any())) .thenReturn(cloudifyExecutionList).thenThrow(Exception.class) .thenReturn(cloudifyExecutionList); @@ -317,13 +660,13 @@ public class CloudifyControllerTest extends MockitoTestSuite { actualResult = subject.getExecutionsByPage(mockedRequest, null, "successful", "tenant1"); assertTrue(actualResult.contains("successful")); } - +/* @SuppressWarnings("unchecked") @Test public void testGetExecutionByIdAndDeploymentId() throws Exception { CloudifyExecution cldExecution = - new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1", - "tenant1", "error", "execution_id1", null, false, false); + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); @@ -347,7 +690,7 @@ public class CloudifyControllerTest extends MockitoTestSuite { "tenant", mockedRequest); assertTrue(actualResult.contains("error")); } - +*/ @SuppressWarnings("unchecked") @Test public void testGetExecutionEventsById() throws Exception { @@ -384,8 +727,9 @@ public class CloudifyControllerTest extends MockitoTestSuite { @SuppressWarnings("unchecked") @Test public void testStartExecution() throws Exception { - CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install", - false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false); + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); Map<String, Object> params = new HashMap<String, Object>(); params.put("key1", "value1"); @@ -401,12 +745,22 @@ public class CloudifyControllerTest extends MockitoTestSuite { CloudifyNodeInstanceIdList cfyNodeInstList = new CloudifyNodeInstanceIdList(cfyNodeInstItems, null); - + + String secretTokenStr = + "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}"; + CloudifySecret secretData = null; + try { + secretData = objectMapper.readValue(secretTokenStr, CloudifySecret.class); + } catch (Exception e) { + + } + when(restClient.getSecret(Mockito.any(), Mockito.any())).thenReturn(secretData); + when(restClient.getNodeInstanceId(Mockito.any(), Mockito.any())) .thenReturn(cfyNodeInstList); when(restClient.startExecution(Matchers.<CloudifyExecutionRequest>any())) - .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException); + .thenReturn(cldExecution).thenThrow(Exception.class).thenThrow(httpException); String actualResult = subject.startExecution(mockedRequest, cfyExecReq); assertTrue(actualResult.contains("execution_id1")); @@ -420,32 +774,6 @@ public class CloudifyControllerTest extends MockitoTestSuite { @SuppressWarnings("unchecked") @Test - public void testUpdateDeployment() throws Exception { - - CloudifyDeploymentUpdateRequest cfyDeployUpdateReq = - new CloudifyDeploymentUpdateRequest("deployment_id", "update", false, false, - "node_instance_id1", "4", "1000", "image", 2, "my_container"); - - CloudifyDeploymentUpdateResponse cfyDeployUpdateResp = new CloudifyDeploymentUpdateResponse( - "terminated", "created_at", "update", false, "blueprint_id", "deployment_id", "", "id1", - null, "tenant1", "junit", false, "resource_availability"); - - when(restClient.updateDeployment(Matchers.<CloudifyDeploymentUpdateRequest>any())) - .thenReturn(cfyDeployUpdateResp).thenThrow(Exception.class).thenThrow(httpException); - - String actualResult = subject.updateDeployment(mockedRequest, cfyDeployUpdateReq); - assertTrue(actualResult.contains("terminated")); - - actualResult = subject.updateDeployment(mockedRequest, cfyDeployUpdateReq); - assertTrue(actualResult.contains("error")); - - actualResult = subject.updateDeployment(mockedRequest, cfyDeployUpdateReq); - assertTrue(actualResult.contains("error")); - - } - - @SuppressWarnings("unchecked") - @Test public void testGetNodeInstanceId() throws Exception { CloudifyNodeInstanceId cfyNodeInst = new CloudifyNodeInstanceId("node_instance_id1"); @@ -506,8 +834,9 @@ public class CloudifyControllerTest extends MockitoTestSuite { HttpHeaders httpHeader = new HttpHeaders(); httpHeader.put("tenant", tenants); - CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "cancel", - false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false); + CloudifyExecution cfyExecObj = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); when(restClient.cancelExecution(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException); diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CommonApiControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CommonApiControllerTest.java deleted file mode 100644 index 7097275..0000000 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CommonApiControllerTest.java +++ /dev/null @@ -1,791 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ - -package org.onap.ccsdk.dashboard.controller; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.when; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Matchers; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.onap.ccsdk.dashboard.core.MockUser; -import org.onap.ccsdk.dashboard.core.MockitoTestSuite; -import org.onap.ccsdk.dashboard.domain.EcdComponent; -import org.onap.ccsdk.dashboard.exceptions.BadRequestException; -import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException; -import org.onap.ccsdk.dashboard.exceptions.DownstreamException; -import org.onap.ccsdk.dashboard.exceptions.ServerErrorException; -import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException; -import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException; -import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployment; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; -import org.onap.ccsdk.dashboard.model.CloudifyExecution; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstance; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceId; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList; -import org.onap.ccsdk.dashboard.model.CloudifyTenant; -import org.onap.ccsdk.dashboard.model.CloudifyTenantList; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse; -import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks; -import org.onap.ccsdk.dashboard.model.inventory.Service; -import org.onap.ccsdk.dashboard.model.inventory.ServiceList; -import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; -import org.onap.ccsdk.dashboard.model.inventory.ServiceRef; -import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList; -import org.onap.ccsdk.dashboard.model.inventory.ServiceType; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; -import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest; -import org.onap.ccsdk.dashboard.rest.CloudifyClient; -import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient; -import org.onap.ccsdk.dashboard.rest.InventoryClient; -import org.onap.ccsdk.dashboard.service.ControllerEndpointService; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.HttpStatusCodeException; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; - -public class CommonApiControllerTest extends MockitoTestSuite { - - @Mock - private CloudifyClient cfyClient; - - @Mock - private InventoryClient inventoryClient; - - @Mock - DeploymentHandlerClient deploymentHandlerClient; - - @Mock - ControllerEndpointService controllerEndpointService; - - @InjectMocks - CommonApiController subject = new CommonApiController(); - - private HttpStatusCodeException httpException = - new HttpServerErrorException(HttpStatus.BAD_GATEWAY); - - protected final ObjectMapper objectMapper = new ObjectMapper(); - - HttpServletRequest mockedRequest; - HttpServletResponse mockedResponse; - - MockUser mockUser = new MockUser(); - ServiceList deplList = null; - Service deplItem = null; - - ServiceType bpItem = null; - ServiceType bpItem2 = null; - ServiceTypeList bpList = null; - ServiceTypeList bpList2 = null; - - ServiceTypeRequest bpUploadItem = null; - - BadRequestException badReqError; - ServiceAlreadyExistsException srvcExistError; - ServerErrorException serverError; - DownstreamException downStrmError; - JsonProcessingException jsonError; - DeploymentNotFoundException notFoundError; - private ServiceTypeNotFoundException serviceTypeException = - new ServiceTypeNotFoundException("Invalid blueprint"); - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - objectMapper.registerModule(new Jdk8Module()); - getExpectedDeployments(); - getExpectedBueprints(); - createBpUploadItem(); - mockedRequest = getMockedRequest(); - mockedResponse = getMockedResponse(); - badReqError = new BadRequestException("bad request"); - srvcExistError = new ServiceAlreadyExistsException("service already exists"); - serverError = new ServerErrorException("Error occured in server"); - downStrmError = new DownstreamException("error occured in downstream"); - notFoundError = new DeploymentNotFoundException("item not found"); - } - - public void getExpectedDeployments() - throws JsonParseException, JsonMappingException, IOException { - - deplItem = new Service("dcae_dtiapi_1902", null, "1552335532348", "1552335532348", null, - "dummyVnfId", null, "dummyVnfType", "dummyLocation", "dcae_dtiapi_1902", null); - Collection<Service> items = new ArrayList<Service>(); - items.add(deplItem); - - String pageLinks = - "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}"; - ServiceList.PaginationLinks paginationLinks = - objectMapper.readValue(pageLinks, ServiceList.PaginationLinks.class); - int totalCount = 1; - deplList = new ServiceList(items, totalCount, paginationLinks); - - } - - public void getExpectedBueprints() - throws JsonParseException, JsonMappingException, IOException { - bpItem = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906, - "tosca_definitions_version: cloudify_dsl_1_3", "", "app1", "comp1").build(); - - Collection<ServiceType> items = new ArrayList<ServiceType>(); - items.add(bpItem); - - String pageLinks2 = - "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}"; - ServiceTypeList.PaginationLinks paginationLinks = - objectMapper.readValue(pageLinks2, ServiceTypeList.PaginationLinks.class); - int totalCount = 1; - bpList = new ServiceTypeList(items, totalCount, paginationLinks); - - bpItem2 = new ServiceType("xyz1731", "xyz1731-helm-1907", 1906, - "tosca_definitions_version: cloudify_dsl_1_3\\r\\nimports:\\r\\n - http://www.getcloudify.org/spec/cloudify/4.2/types.yaml\\r\\n", - "app1", "comp1", null, null, null, null, null, null, "typeId", null, "created", null, - true); - - Collection<ServiceType> items2 = new ArrayList<ServiceType>(); - items2.add(bpItem2); - - bpList2 = new ServiceTypeList(items2, totalCount, paginationLinks); - } - - public void createBpUploadItem() { - bpUploadItem = ServiceTypeRequest.from(bpItem); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public final void testInsertComponent() throws Exception { - EcdComponent component1 = new EcdComponent(); - - component1.setCname("comp1"); - component1.setCompId(100L); - component1.setDname("COMP1"); - - doNothing().when(controllerEndpointService).insertComponent(component1); - - String actualResult = subject.insertComponent(mockedRequest, component1); - assertTrue(actualResult.contains("Inserted")); - } - - @Test - public final void testGetComponents() throws Exception { - EcdComponent component1 = new EcdComponent(); - EcdComponent component2 = new EcdComponent(); - - component1.setCname("comp1"); - component1.setCompId(100L); - component1.setDname("COMP1"); - - component2.setCname("comp2"); - component2.setCompId(200L); - component2.setDname("COMP2"); - - List<EcdComponent> compsList = new ArrayList<EcdComponent>(); - compsList.add(component1); - compsList.add(component2); - - when(controllerEndpointService.getComponents()).thenReturn(compsList); - - String actualResult = subject.getComponents(mockedRequest); - assertTrue(actualResult.contains("comp1")); - } - - @Test - public final void testGetTenants() throws Exception { - String tenantsList = - "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, " - + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], " - + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}"; - CloudifyTenantList sampleData = null; - try { - sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class); - } catch (Exception e) { - } - MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - - Mockito.when(cfyClient.getTenants()).thenReturn(sampleData); - - String tenantStr = subject.getTenants(mockedRequest); - assertTrue(tenantStr.contains("dyh1b")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testGetTenantStatusForService() throws Exception { - String[] deplIds = {"id1", "id2"}; - - CloudifyDeployedTenant cldDeplTenant = new CloudifyDeployedTenant("id1", "bp1", "tenant1"); - - List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>(); - - cldDeplTenantList.add(cldDeplTenant); - - CloudifyDeployedTenantList cldDeployedTenantList = - new CloudifyDeployedTenantList(cldDeplTenantList, null); - - CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1"); - - List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>(); - cldfyTenantList.add(cldTenant); - - CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null); - - CloudifyExecution cldExecution = - new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1", - "tenant1", "error", "execution_id1", null, false, false); - - List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); - - cldExecutionList.add(cldExecution); - - CloudifyExecutionList cloudifyExecutionList = - new CloudifyExecutionList(cldExecutionList, null); - - when(cfyClient.getTenants()).thenReturn(cloudifyTenantList); - - when(cfyClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList); - - when(cfyClient.getExecutionsSummary(Mockito.any(), Mockito.any())) - .thenReturn(cloudifyExecutionList).thenThrow(Exception.class).thenThrow(httpException); - - String actualResult = subject.getTenantStatusForService(mockedRequest, deplIds); - assertTrue(actualResult.contains("successful")); - - actualResult = subject.getTenantStatusForService(mockedRequest, deplIds); - assertTrue(actualResult.contains("error")); - - actualResult = subject.getTenantStatusForService(mockedRequest, deplIds); - assertTrue(actualResult.contains("error")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testCreateBlueprint() throws Exception { - ServiceTypeUploadRequest bpUploadReq = ServiceTypeUploadRequest.from(bpItem); - - when(inventoryClient.addServiceType(Matchers.<ServiceTypeRequest>any())) - .thenThrow(BlueprintParseException.class).thenThrow(httpException) - .thenThrow(Exception.class).thenReturn(bpItem); - - String actual1 = subject.createBlueprint(mockedRequest, bpUploadReq); - assertTrue(actual1.contains("error")); - - String actual2 = subject.createBlueprint(mockedRequest, bpUploadReq); - assertTrue(actual2.contains("error")); - - String actual3 = subject.createBlueprint(mockedRequest, bpUploadReq); - assertTrue(actual3.contains("error")); - - String actual = subject.createBlueprint(mockedRequest, bpUploadReq); - assertTrue(actual.contains("app1")); - - } - - @SuppressWarnings("unchecked") - @Test - public final void testGetBlueprintsByPage() { - MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest(); - mockedRequest1.addParameter("_include", "typeName,typeId,typeVersion"); - mockedRequest1.addParameter("name", "xyz"); - - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream1).thenThrow(Exception.class).thenThrow(httpException); - - String result = subject.getBlueprintsByPage(mockedRequest1); - assertTrue(result.contains("xyz")); - - result = subject.getBlueprintsByPage(mockedRequest1); - assertTrue(result.contains("error")); - - result = subject.getBlueprintsByPage(mockedRequest1); - assertTrue(result.contains("error")); - - } - - @SuppressWarnings("unchecked") - @Test - public final void testQueryBlueprintFilter() { - MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest(); - mockedRequest1.addParameter("_include", "typeName,typeId,typeVersion"); - mockedRequest1.addParameter("name", "xyz"); - - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream1).thenThrow(Exception.class).thenThrow(httpException); - - String result = subject.queryBlueprintFilter(mockedRequest1); - assertTrue(result.contains("xyz")); - - result = subject.queryBlueprintFilter(mockedRequest1); - assertTrue(result.contains("error")); - - result = subject.queryBlueprintFilter(mockedRequest1); - assertTrue(result.contains("error")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testGetDeploymentsByPage() { - CloudifyDeployedTenant cldDeplTenant = - new CloudifyDeployedTenant("dcae_dtiapi_1902", "dcae_dtiapi_1902", "tenant1"); - - List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>(); - - cldDeplTenantList.add(cldDeplTenant); - - CloudifyDeployedTenantList cldDeployedTenantList = - new CloudifyDeployedTenantList(cldDeplTenantList, null); - - CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1"); - - List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>(); - cldfyTenantList.add(cldTenant); - - CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null); - - MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest(); - mockedRequest1.addParameter("_include", "id"); - mockedRequest1.addParameter("searchBy", "dti"); - - Collection<Service> items = deplList.items; - - when(cfyClient.getTenants()).thenReturn(cloudifyTenantList); - - when(cfyClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList) - .thenThrow(Exception.class).thenThrow(httpException).thenReturn(cldDeployedTenantList) - .thenReturn(cldDeployedTenantList); - - Stream<Service> sampleStream1 = items.stream(); - Stream<Service> sampleStream2 = items.stream(); - Stream<Service> sampleStream3 = items.stream(); - - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1) - .thenReturn(sampleStream2).thenReturn(sampleStream3).thenThrow(Exception.class) - .thenThrow(httpException); - - String result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1); - assertTrue(result.contains("dti")); - - result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1); - assertTrue(result.contains("dti")); - - result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1); - assertTrue(result.contains("dti")); - - result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1); - assertTrue(result.contains("error")); - - result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1); - assertTrue(result.contains("error")); - - } - - @SuppressWarnings("unchecked") - @Test - public final void testGetAllDeploymentsByPage() { - CloudifyDeployedTenant cldDeplTenant = - new CloudifyDeployedTenant("dcae_dtiapi_1902", "dcae_dtiapi_1902", "tenant1"); - - List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>(); - - cldDeplTenantList.add(cldDeplTenant); - - CloudifyDeployedTenantList cldDeployedTenantList = - new CloudifyDeployedTenantList(cldDeplTenantList, null); - - CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1"); - - List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>(); - cldfyTenantList.add(cldTenant); - - CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null); - - MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest(); - mockedRequest1.addParameter("_include", "id"); - mockedRequest1.addParameter("searchBy", "dti"); - - Collection<Service> items = deplList.items; - - when(cfyClient.getTenants()).thenReturn(cloudifyTenantList); - - when(cfyClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList) - .thenThrow(Exception.class).thenThrow(httpException).thenReturn(cldDeployedTenantList) - .thenReturn(cldDeployedTenantList); - - Stream<Service> sampleStream1 = items.stream(); - Stream<Service> sampleStream2 = items.stream(); - Stream<Service> sampleStream3 = items.stream(); - - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1) - .thenReturn(sampleStream2).thenReturn(sampleStream3).thenThrow(Exception.class) - .thenThrow(httpException); - - String result = subject.getAllDeploymentsByPage(mockedRequest1); - assertTrue(result.contains("dti")); - - result = subject.getAllDeploymentsByPage(mockedRequest1); - assertTrue(result.contains("dti")); - - result = subject.getAllDeploymentsByPage(mockedRequest1); - assertTrue(result.contains("dti")); - - result = subject.getAllDeploymentsByPage(mockedRequest1); - assertTrue(result.contains("error")); - - result = subject.getAllDeploymentsByPage(mockedRequest1); - assertTrue(result.contains("error")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testGetDeploymentRevisions() throws Exception { - CloudifyNodeInstance cfyNodeInstance = new CloudifyNodeInstance("id1", null); - - List<CloudifyNodeInstance> cfyNodeInstanceItems = new ArrayList<CloudifyNodeInstance>(); - cfyNodeInstanceItems.add(cfyNodeInstance); - - CloudifyNodeInstanceList cfyNodeInstList = - new CloudifyNodeInstanceList(cfyNodeInstanceItems, null); - - when(cfyClient.getNodeInstanceVersion(Mockito.any(), Mockito.any())) - .thenReturn(cfyNodeInstList).thenThrow(Exception.class).thenThrow(httpException); - - String actualResult = - subject.getDeploymentRevisions("deploymentId", "tenant", mockedRequest); - assertTrue(actualResult.contains("id1")); - - actualResult = subject.getDeploymentRevisions("deploymentId", "tenant", mockedRequest); - assertTrue(actualResult.contains("error")); - - actualResult = subject.getDeploymentRevisions("deploymentId", "tenant", mockedRequest); - assertTrue(actualResult.contains("error")); - } - - @Test - public final void testGetDeploymentInputs() throws Exception { - - Map<String, Object> inputHash = new HashMap<String, Object>(); - inputHash.put("key1", "value1"); - - CloudifyDeployment cldDeployment = - new CloudifyDeployment("description", "blueprint_id", "created_at", "updated_at", "id", - inputHash, null, null, null, null, null, null, "tenant"); - - List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>(); - cfyDeployItems.add(cldDeployment); - - CloudifyDeploymentList.Metadata.Pagination pageObj = - new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); - CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); - - CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata); - - when(cfyClient.getDeploymentInputs(Matchers.any(), Matchers.any())) - .thenReturn(cldDeployList); - - String actualResult = subject.getDeploymentInputs("deploymentId", "tenant", mockedRequest); - assertTrue(actualResult.contains("blueprint_id")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testModifyDeployment() throws Exception { - CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install", - false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false); - - Map<String, Object> params = new HashMap<String, Object>(); - params.put("tenant", "tenant1"); - params.put("workflow", "upgrade"); - - CloudifyExecutionRequest cfyExecReq = new CloudifyExecutionRequest("deployment_id", - "upgrade", false, false, "tenant1", params); - - CloudifyNodeInstanceId cfyNodeInst = new CloudifyNodeInstanceId("node_instance_id1"); - - List<CloudifyNodeInstanceId> cfyNodeInstItems = new ArrayList<CloudifyNodeInstanceId>(); - - cfyNodeInstItems.add(cfyNodeInst); - - CloudifyNodeInstanceIdList cfyNodeInstList = - new CloudifyNodeInstanceIdList(cfyNodeInstItems, null); - - when(cfyClient.getNodeInstanceId(Mockito.any(), Mockito.any())).thenReturn(cfyNodeInstList); - - when(cfyClient.startExecution(Matchers.<CloudifyExecutionRequest>any())) - .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException); - - String inputParamStr = "{\"tenant\": \"tenant1\", \"workflow\":\"upgrade\"}"; - - InputStream is = new ByteArrayInputStream(inputParamStr.getBytes()); - - String actualResult = subject.modifyDeployment("depId", mockedRequest, is); - assertTrue(actualResult.contains("execution_id1")); - - actualResult = subject.modifyDeployment("depId", mockedRequest, is); - assertTrue(actualResult.contains("error")); - - actualResult = subject.modifyDeployment("depId", mockedRequest, is); - assertTrue(actualResult.contains("error")); - - } - - @Test - public final void testGetServicesForType() throws Exception { - ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434"); - Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>(); - expectedSrvcIds.add(expectedSrvc); - ServiceRefList expectedSrvcRefList = new ServiceRefList(expectedSrvcIds, 1); - - when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any())) - .thenReturn(expectedSrvcRefList); - String actual = subject.getServicesForType(mockedRequest, "typeId1"); - assertTrue(actual.contains("typeId1")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testCreateDeployment() throws Exception { - DeploymentInput deployInput1 = new DeploymentInput("component1", "tag1", - "xyz1731-helm-1906", 1906, "blueprintId", null, "tenant1"); - - DeploymentInput deployInput2 = new DeploymentInput("component1", "tag1", - "xyz1731-helm-1906", 1906, null, null, "tenant1"); - - DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status"); - DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink); - - Collection<ServiceType> items = bpList2.items; - Stream<ServiceType> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream1); - - String actualResp0 = subject.createDeployment(mockedRequest, deployInput2); - assertTrue(actualResp0.contains("error")); - - StringBuffer expectedStrBuff = new StringBuffer(); - expectedStrBuff.append("http://oom.s2.com"); - when(mockedRequest.getRequestURL()).thenReturn(expectedStrBuff); - - when(deploymentHandlerClient.putDeployment(Matchers.anyString(), Matchers.anyString(), - Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError) - .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError) - .thenThrow(Exception.class); - - String actualResp = subject.createDeployment(mockedRequest, deployInput1); - assertTrue(actualResp.contains("component1")); - - actualResp = subject.createDeployment(mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.createDeployment(mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.createDeployment(mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.createDeployment(mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.createDeployment(mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - } - - @SuppressWarnings("unchecked") - @Test - public final void testUpdateDeployment() throws Exception { - - DeploymentInput deployInput1 = new DeploymentInput("component1", "tag1", - "xyz1731-helm-1906", 1906, "blueprintId", null, "tenant1"); - - DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status"); - DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink); - - Collection<ServiceType> items = bpList2.items; - Stream<ServiceType> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream1); - - when(deploymentHandlerClient.updateDeployment(Matchers.anyString(), Matchers.anyString(), - Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError) - .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError) - .thenThrow(Exception.class); - - String actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1); - assertTrue(actualResp.contains("req1")); - - actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - - actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1); - assertTrue(actualResp.contains("error")); - } - - @Test - public final void testGetExecutionByDeploymentId() throws Exception { - - CloudifyExecution cldExecution = - new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1", - "tenant1", "error", "execution_id1", null, false, false); - - List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); - - cldExecutionList.add(cldExecution); - - CloudifyExecutionList cloudifyExecutionList = - new CloudifyExecutionList(cldExecutionList, null); - - when(cfyClient.getExecutionsSummary(Mockito.any(), Mockito.any())) - .thenReturn(cloudifyExecutionList); - - String actualResult = - subject.getExecutionByDeploymentId("dep_id", "tenant1", mockedRequest); - assertTrue(actualResult.contains("execution_id1")); - } - - @Test - public final void testDeleteBlueprint() throws Exception { - String expected = "{\"202\": \"OK\"}"; - doNothing().doThrow(serviceTypeException).doThrow(Exception.class).when(inventoryClient) - .deleteServiceType(Matchers.anyString()); - - String actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse); - assertEquals(expected, actual); - - actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse); - assertTrue(actual.contains("error")); - - actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse); - assertTrue(actual.contains("error")); - } - - @Test - public final void testDeleteDeployment() throws Exception { - doNothing().doThrow(badReqError).doThrow(serverError).doThrow(downStrmError) - .doThrow(notFoundError).doThrow(Exception.class).when(deploymentHandlerClient) - .deleteDeployment(Matchers.anyString(), Matchers.anyString()); - - StringBuffer expectedStrBuff = new StringBuffer(); - expectedStrBuff.append("http://oom.s2.com"); - when(mockedRequest.getRequestURL()).thenReturn(expectedStrBuff); - - String actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse); - assertFalse(actual.contains("error")); - - actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse); - assertTrue(actual.contains("error")); - - actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse); - assertTrue(actual.contains("error")); - - actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse); - assertTrue(actual.contains("error")); - - actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse); - assertTrue(actual.contains("error")); - - actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse); - assertTrue(actual.contains("error")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testCancelExecution() throws Exception { - List<String> tenants = new ArrayList<String>(); - tenants.add("tenant1"); - - HttpHeaders httpHeader = new HttpHeaders(); - httpHeader.put("tenant", tenants); - - CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "cancel", - false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false); - - when(cfyClient.cancelExecution(Mockito.any(), Mockito.any(), Mockito.any())) - .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException); - - String actualResult = - subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse); - assertTrue(actualResult.contains("execution_id1")); - - actualResult = - subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse); - assertTrue(actualResult.contains("error")); - - actualResult = - subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse); - assertTrue(actualResult.contains("error")); - } - -} diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/ConsulControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/ConsulControllerTest.java index 3d71a2e..53657ed 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/ConsulControllerTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/ConsulControllerTest.java @@ -28,6 +28,8 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; +import javax.servlet.http.HttpServletRequest; + import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -37,14 +39,15 @@ import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.onap.ccsdk.dashboard.controller.ConsulController.ConsulDataItem; import org.onap.ccsdk.dashboard.core.MockUser; import org.onap.ccsdk.dashboard.core.MockitoTestSuite; -import org.onap.ccsdk.dashboard.model.ConsulDatacenter; -import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration; -import org.onap.ccsdk.dashboard.model.ConsulNodeInfo; -import org.onap.ccsdk.dashboard.model.ConsulServiceHealth; -import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; import org.onap.ccsdk.dashboard.model.RestResponseSuccess; +import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter; +import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration; +import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo; import org.onap.ccsdk.dashboard.rest.ConsulClient; import org.onap.portalsdk.core.domain.User; import org.onap.portalsdk.core.web.support.UserUtils; @@ -67,6 +70,8 @@ public class ConsulControllerTest extends MockitoTestSuite { MockUser mockUser = new MockUser(); HttpClientErrorException httpException; + String[] svcTags = {"cfytenantname=onap"}; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -87,7 +92,7 @@ public class ConsulControllerTest extends MockitoTestSuite { "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing", "This is a pgaas1_Service_ID health check", "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n", - "pgaas1_Service_ID", "pgaasServer1", 190199, 199395); + "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395); List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>(); expectedCnslSrvcHlth.add(consulSrvcHlth); @@ -118,7 +123,7 @@ public class ConsulControllerTest extends MockitoTestSuite { "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing", "This is a pgaas1_Service_ID health check", "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n", - "pgaas1_Service_ID", "pgaasServer1", 190199, 199395); + "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395); List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>(); expectedCnslSrvcHlth.add(consulSrvcHlth); @@ -160,7 +165,7 @@ public class ConsulControllerTest extends MockitoTestSuite { "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing", "This is a pgaas1_Service_ID health check", "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n", - "pgaas1_Service_ID", "pgaasServer1", 190199, 199395); + "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395); List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>(); expectedCnslSrvcHlth.add(consulSrvcHlth); @@ -193,123 +198,15 @@ public class ConsulControllerTest extends MockitoTestSuite { assertTrue(actualResult.contains("dc1")); } - @SuppressWarnings("unchecked") - @Test - public final void testRegisterService() throws Exception { - ConsulHealthServiceRegistration.EndpointCheck endPoint = - new ConsulHealthServiceRegistration.EndpointCheck("endpoint1", "interval1", - "description1", "name1"); - List<ConsulHealthServiceRegistration.EndpointCheck> endPointList = - new ArrayList<ConsulHealthServiceRegistration.EndpointCheck>(); - endPointList.add(endPoint); - - List<String> tagList = new ArrayList<String>(); - tagList.add("tag1"); - tagList.add("tag2"); - - ConsulHealthServiceRegistration.ConsulServiceRegistration servcReg = - new ConsulHealthServiceRegistration.ConsulServiceRegistration("id1", "name1", - "address1", "port1", tagList, endPointList); - List<ConsulHealthServiceRegistration.ConsulServiceRegistration> servcRegList = - new ArrayList<ConsulHealthServiceRegistration.ConsulServiceRegistration>(); - servcRegList.add(servcReg); - - ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(servcRegList); - - RestResponseSuccess expectedResp = new RestResponseSuccess("Registration yielded code 0"); - String expectedResult = objectMapper.writeValueAsString(expectedResp); - - String expectedStr = "Registration yielded code 0"; - when(consulClient.registerService(Matchers.<ConsulHealthServiceRegistration>any())) - .thenReturn(expectedStr).thenThrow(Exception.class).thenThrow(httpException); - - String actualResult = subject.registerService(mockedRequest, chsrObj); - assertTrue(actualResult.equals(expectedResult)); - - actualResult = subject.registerService(mockedRequest, chsrObj); - assertTrue(actualResult.contains("error")); - - actualResult = subject.registerService(mockedRequest, chsrObj); - assertTrue(actualResult.contains("error")); - } - - @Test - public final void testRegisterService_SrvcError() throws Exception { - ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(null); - - String actualResult = subject.registerService(mockedRequest, chsrObj); - assertTrue(actualResult.contains("error")); - } - - @Test - @Ignore - public final void testRegisterService_invalidSrvcError() throws Exception { - ConsulHealthServiceRegistration.EndpointCheck endPoint = - new ConsulHealthServiceRegistration.EndpointCheck("endpoint1", "interval1", - "description1", "name1"); - List<ConsulHealthServiceRegistration.EndpointCheck> endPointList = - new ArrayList<ConsulHealthServiceRegistration.EndpointCheck>(); - endPointList.add(endPoint); - - List<String> tagList = new ArrayList<String>(); - tagList.add("tag1"); - tagList.add("tag2"); - - ConsulHealthServiceRegistration.ConsulServiceRegistration servcReg = - new ConsulHealthServiceRegistration.ConsulServiceRegistration("id1", "name2", - "address2", "port1", tagList, endPointList); - List<ConsulHealthServiceRegistration.ConsulServiceRegistration> servcRegList = - new ArrayList<ConsulHealthServiceRegistration.ConsulServiceRegistration>(); - servcRegList.add(servcReg); - - ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(servcRegList); - - String actualResult = subject.registerService(mockedRequest, chsrObj); - assertTrue(actualResult.contains("error")); - } - - @Test - public final void testRegisterService_invalidEndptError() throws Exception { - ConsulHealthServiceRegistration.EndpointCheck endPoint = - new ConsulHealthServiceRegistration.EndpointCheck("", "", "description1", "name1"); - List<ConsulHealthServiceRegistration.EndpointCheck> endPointList = - new ArrayList<ConsulHealthServiceRegistration.EndpointCheck>(); - endPointList.add(endPoint); - - List<String> tagList = new ArrayList<String>(); - tagList.add("tag1"); - tagList.add("tag2"); - - ConsulHealthServiceRegistration.ConsulServiceRegistration servcReg = - new ConsulHealthServiceRegistration.ConsulServiceRegistration("id1", "", "", "port1", - tagList, endPointList); - List<ConsulHealthServiceRegistration.ConsulServiceRegistration> servcRegList = - new ArrayList<ConsulHealthServiceRegistration.ConsulServiceRegistration>(); - servcRegList.add(servcReg); - - ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(servcRegList); - - String actualResult = subject.registerService(mockedRequest, chsrObj); - assertTrue(actualResult.contains("error")); - } - - @SuppressWarnings("unchecked") @Test - public final void testDeregisterService() throws Exception { - RestResponseSuccess expectedResp = new RestResponseSuccess("Deregistration yielded code 0"); - String expectedResult = objectMapper.writeValueAsString(expectedResp); - - when(consulClient.deregisterService(Mockito.any())).thenReturn(0).thenThrow(Exception.class) - .thenThrow(httpException); - - String actualResult = subject.deregisterService(mockedRequest, "srvc1"); - assertTrue(actualResult.equals(expectedResult)); - - actualResult = subject.deregisterService(mockedRequest, "srvc1"); - assertTrue(actualResult.contains("error")); - - actualResult = subject.deregisterService(mockedRequest, "srvc1"); + public final void testGetItemListForPageWrapper() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + user.setId(1000L); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + String actualResult = + subject.getItemListForPageWrapper(mockedRequest, "dc1", ConsulController.ConsulDataItem.SERVICE_INFO); assertTrue(actualResult.contains("error")); + } - } diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerControllerTest.java index 6517b68..4833c12 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerControllerTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerControllerTest.java @@ -27,6 +27,8 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; +import javax.servlet.http.HttpServletRequest; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -88,46 +90,13 @@ public class DeploymentHandlerControllerTest extends MockitoTestSuite { @Test public final void testPutDeployment_create() throws Exception { DeploymentRequestObject expectReq = - new DeploymentRequestObject("dep1", "dep1", null, "tenant1", "create"); - + new DeploymentRequestObject("dep1", "dep1", "create", null, "tenant1"); + DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status"); DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink); - + when(restClient.putDeployment(Matchers.anyString(), Matchers.anyString(), - Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError) - .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError) - .thenThrow(Exception.class); - - String actualResp = subject.putDeployment(mockedRequest, expectReq); - assertTrue(actualResp.contains("req1")); - - actualResp = subject.putDeployment(mockedRequest, expectReq); - assertTrue(actualResp.contains("error")); - - actualResp = subject.putDeployment(mockedRequest, expectReq); - assertTrue(actualResp.contains("error")); - - actualResp = subject.putDeployment(mockedRequest, expectReq); - assertTrue(actualResp.contains("error")); - - actualResp = subject.putDeployment(mockedRequest, expectReq); - assertTrue(actualResp.contains("error")); - - actualResp = subject.putDeployment(mockedRequest, expectReq); - assertTrue(actualResp.contains("error")); - } - - @SuppressWarnings("unchecked") - @Test - public final void testPutDeployment_update() throws Exception { - DeploymentRequestObject expectReq = - new DeploymentRequestObject("dep1", "dep1", null, "tenant1", "update"); - - DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status"); - DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink); - - when(restClient.updateDeployment(Matchers.anyString(), Matchers.anyString(), - Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError) + Matchers.<DeploymentRequest>any(), Matchers.<HttpServletRequest>any()) ).thenReturn(expectResp).thenThrow(badReqError) .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError) .thenThrow(Exception.class); @@ -155,7 +124,7 @@ public class DeploymentHandlerControllerTest extends MockitoTestSuite { doNothing().doThrow(badReqError).doThrow(serverError).doThrow(downStrmError) .doThrow(notFoundError).doThrow(Exception.class).when(restClient) - .deleteDeployment(Matchers.anyString(), Matchers.anyString()); + .deleteDeployment(Matchers.anyString(), Matchers.anyString(), Matchers.<HttpServletRequest>any()); StringBuffer expectedStrBuff = new StringBuffer(); expectedStrBuff.append("http://oom.s2.com"); diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/InventoryControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/InventoryControllerTest.java index 01858ed..9cce55e 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/InventoryControllerTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/InventoryControllerTest.java @@ -31,6 +31,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -54,6 +56,7 @@ import org.onap.ccsdk.dashboard.core.MockitoTestSuite; import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException; import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceNotFoundException; import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; import org.onap.ccsdk.dashboard.model.inventory.Service; import org.onap.ccsdk.dashboard.model.inventory.ServiceList; import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams; @@ -63,10 +66,14 @@ import org.onap.ccsdk.dashboard.model.inventory.ServiceType; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList; import org.onap.ccsdk.dashboard.rest.CloudifyClient; import org.onap.ccsdk.dashboard.rest.InventoryClient; import org.onap.ccsdk.dashboard.util.DashboardProperties; import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.util.CacheManager; +import org.onap.portalsdk.core.util.SystemProperties; import org.onap.portalsdk.core.web.support.AppUtils; import org.onap.portalsdk.core.web.support.UserUtils; import org.powermock.api.mockito.PowerMockito; @@ -82,11 +89,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; @RunWith(PowerMockRunner.class) -@PrepareForTest({DashboardProperties.class}) public class InventoryControllerTest extends MockitoTestSuite { @Mock - private CloudifyClient restClient; + private CloudifyClient cfyClient; @Mock private InventoryClient inventoryClient; @@ -118,59 +124,63 @@ public class InventoryControllerTest extends MockitoTestSuite { HttpServletResponse mockedResponse; MockUser mockUser = new MockUser(); - ServiceList deplList = null; - Service deplItem = null; - ServiceType bpItem = null; - ServiceTypeList bpList = null; + ServiceTypeSummary bpItem, bpItem2 = null; + ServiceTypeSummaryList bpList, bpList2 = null; + ServiceType bpItemFull = null; + ServiceTypeList bpItemFullList = null; + ServiceTypeRequest bpUploadItem = null; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); objectMapper.registerModule(new Jdk8Module()); - getExpectedDeployments(); - getExpectedBueprints(); + getExpectedBlueprints(); createBpUploadItem(); mockedRequest = getMockedRequest(); mockedResponse = getMockedResponse(); + CacheManager testCache = new CacheManager(); + Map<String, List<ServiceTypeSummary>> bpPerOwner = new HashMap<String, List<ServiceTypeSummary>>(); + bpPerOwner.put("xyz1731", (List<ServiceTypeSummary>)bpList2.items); + testCache.putObject("owner_bp_map", bpPerOwner); + subject.setCacheManager(testCache); + /* + PowerMockito.mockStatic(SystemProperties.class); + Mockito + .when(SystemProperties.getProperty("cache_switch")) + .thenReturn("1"); + */ } - public void getExpectedDeployments() - throws JsonParseException, JsonMappingException, IOException { - - deplItem = new Service("dcae_dtiapi_1902", null, "1552335532348", "1552335532348", null, - "dummyVnfId", null, "dummyVnfType", "dummyLocation", "dcae_dtiapi_1902", null); - Collection<Service> items = new ArrayList<Service>(); - items.add(deplItem); - - String pageLinks = - "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}"; - ServiceList.PaginationLinks paginationLinks = - objectMapper.readValue(pageLinks, ServiceList.PaginationLinks.class); - int totalCount = 1; - deplList = new ServiceList(items, totalCount, paginationLinks); - - } - - public void getExpectedBueprints() + public void getExpectedBlueprints() throws JsonParseException, JsonMappingException, IOException { - bpItem = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906, + bpItem = new ServiceTypeSummary.Builder().application("app1").component("comp1"). + typeName("xyz1731-helm-1906").owner("xyz1731").typeVersion(1906).build(); + + bpItem2 = new ServiceTypeSummary("xyz1731", "xyz1731-helm-1906", 1906, "app1", "comp1", "123-456-789", + "342343", true); + bpItemFull = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906, "tosca_definitions_version: cloudify_dsl_1_3", "", "app1", "comp1").build(); - Collection<ServiceType> items = new ArrayList<ServiceType>(); + + Collection<ServiceTypeSummary> items = new ArrayList<ServiceTypeSummary>(); items.add(bpItem); + Collection<ServiceTypeSummary> items2 = new ArrayList<ServiceTypeSummary>(); + items2.add(bpItem2); + String pageLinks2 = "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}"; - ServiceTypeList.PaginationLinks paginationLinks = - objectMapper.readValue(pageLinks2, ServiceTypeList.PaginationLinks.class); + ServiceTypeSummaryList.PaginationLinks paginationLinks = + objectMapper.readValue(pageLinks2, ServiceTypeSummaryList.PaginationLinks.class); int totalCount = 1; - bpList = new ServiceTypeList(items, totalCount, paginationLinks); + bpList = new ServiceTypeSummaryList(items, totalCount, paginationLinks); + bpList2 = new ServiceTypeSummaryList(items2, totalCount, paginationLinks); } public void createBpUploadItem() { - bpUploadItem = ServiceTypeRequest.from(bpItem); + bpUploadItem = ServiceTypeRequest.from(bpItemFull); } @After @@ -178,465 +188,229 @@ public class InventoryControllerTest extends MockitoTestSuite { } @Test + public final void testGetOwnersByPage() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); + String result = subject.getServiceTypesByPage(mockedRequest); + assertTrue(result.contains("xyz")); + } + + @Test + public final void testGetAllServiceTypeNames() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); + String result = subject.getAllServiceTypeNames(mockedRequest); + assertTrue(result.contains("xyz")); + } + + @Test + public final void testGetAllServiceTypeIds() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); + String result = subject.getAllServiceTypeIds(mockedRequest); + assertTrue(result.contains("xyz")); + } + + @Test public final void testGetServiceTypesByPage() { User user = mockUser.mockUser(); user.setLoginId("tester"); MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - mockedRequest.addParameter("searchBy", "xyz"); + //mockedRequest.addParameter("searchBy", "xyz"); mockedRequest.addParameter("sortBy", "owner"); + // # 1st case Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); - - Collection<ServiceType> items = bpList.items; - - Stream<ServiceType> sampleStream1 = items.stream(); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); String result = subject.getServiceTypesByPage(mockedRequest); assertTrue(result.contains("xyz")); - - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - + + // # 2nd case HttpSession session = mockedRequest.getSession(); HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>(); comp_deploy_tab.put("comp1", true); - Set<String> userApps = new TreeSet<String>(); userApps.add("comp1"); - when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab); when(session.getAttribute("role_level")).thenReturn("app"); when(session.getAttribute("authComponents")).thenReturn(userApps); - Stream<ServiceType> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) + Stream<ServiceTypeSummary> sampleStream2 = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()) .thenReturn(sampleStream2); + /* + Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) + .thenReturn(sampleStream2); + */ String result2 = subject.getServiceTypesByPage(mockedRequest); assertTrue(result2.contains("xyz")); - } + } + @Test - public final void testGetServiceTypesByPage_appl() { + public final void testGetServiceTypesByPage_appDevUser() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - mockedRequest.addParameter("sortBy", "application"); - - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + HttpSession session = mockedRequest.getSession(); + HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>(); + comp_deploy_tab.put("comp1", true); + Set<String> userApps = new TreeSet<String>(); + userApps.add("comp1"); + when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab); + when(session.getAttribute("role_level")).thenReturn("app_dev"); + when(session.getAttribute("authComponents")).thenReturn(userApps); - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream); - Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); String result = subject.getServiceTypesByPage(mockedRequest); assertTrue(result.contains("xyz")); + } + + @Test + public final void testGetServiceTypesByPage_containsFilter() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + mockedRequest.addParameter("searchBy", "contains:xyz1731-helm-1906"); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream); - Stream<ServiceType> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream2); - String result2 = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result2.contains("xyz")); + String result = subject.getServiceTypesByPage(mockedRequest); + assertTrue(result.contains("error")); } + + @Test + public final void testGetServiceTypesByPage_AllFilters() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + mockedRequest.addParameter("searchBy", "serviceRef:xyz1731-helm-1906;app:app1;comp:comp1;owner:xyz1731;"); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); + + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> sampleStream = items.stream(); + Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream); + String result = subject.getServiceTypesByPage(mockedRequest); + assertTrue(result.contains("xyz")); + + } + @Test public final void testGetServiceTypesByPage_comp() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); mockedRequest.addParameter("sortBy", "component"); - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); + Collection<ServiceTypeSummary> items = bpList2.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); String result = subject.getServiceTypesByPage(mockedRequest); assertTrue(result.contains("xyz")); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<ServiceType> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream2); - String result2 = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result2.contains("xyz")); } @Test public final void testGetServiceTypesByPage_typeId() { + User user = mockUser.mockUser(); + user.setLoginId("tester"); MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); mockedRequest.addParameter("sortBy", "typeId"); - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); + Collection<ServiceTypeSummary> items = bpList2.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); String result = subject.getServiceTypesByPage(mockedRequest); assertTrue(result.contains("xyz")); - - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<ServiceType> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream2); - String result2 = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result2.contains("xyz")); } @Test public final void testGetServiceTypesByPage_typeName() { - + User user = mockUser.mockUser(); + user.setLoginId("tester"); MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); mockedRequest.addParameter("sortBy", "typeName"); - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); - + Collection<ServiceTypeSummary> items = bpList2.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); String result = subject.getServiceTypesByPage(mockedRequest); assertTrue(result.contains("xyz")); - - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<ServiceType> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream2); - String result2 = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result2.contains("xyz")); - } @Test public final void testGetServiceTypesByPage_typeVer() { - + User user = mockUser.mockUser(); + user.setLoginId("tester"); MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); mockedRequest.addParameter("sortBy", "typeVersion"); - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); + Collection<ServiceTypeSummary> items = bpList2.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); String result = subject.getServiceTypesByPage(mockedRequest); assertTrue(result.contains("xyz")); - - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<ServiceType> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream2); - String result2 = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result2.contains("xyz")); - } @Test public final void testGetServiceTypesByPage_created() { - + User user = mockUser.mockUser(); + user.setLoginId("tester"); MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); mockedRequest.addParameter("sortBy", "created"); - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream1 = items.stream(); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); + Collection<ServiceTypeSummary> items = bpList2.items; + Stream<ServiceTypeSummary> sampleStream1 = items.stream(); Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1); String result = subject.getServiceTypesByPage(mockedRequest); assertTrue(result.contains("xyz")); - - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<ServiceType> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream2); - String result2 = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result2.contains("xyz")); } - @Test - public final void testGetServiceTypesByPage_Auth() { - - User user = mockUser.mockUser(); - user.setLoginId("tester"); - MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - mockedRequest.addParameter("searchBy", "xyz"); - - Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream = items.stream(); - - HttpSession session = mockedRequest.getSession(); - HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>(); - comp_deploy_tab.put("comp1", true); - - Set<String> userApps = new TreeSet<String>(); - userApps.add("comp1"); - - when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab); - when(session.getAttribute("role_level")).thenReturn("ops"); - when(session.getAttribute("authComponents")).thenReturn(userApps); - - Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any())) - .thenReturn(sampleStream); - String result = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result.contains("xyz")); - } @SuppressWarnings("unchecked") @Test public final void testGetServiceTypesByPage_Exception() { - PowerMockito.mockStatic(DashboardProperties.class); - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream = items.stream(); - when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); when(inventoryClient.getServiceTypes()).thenThrow(RestClientException.class) - .thenThrow(httpException).thenReturn(sampleStream); + .thenThrow(httpException); String errResp = subject.getServiceTypesByPage(mockedRequest); assertTrue(errResp.contains("error")); errResp = subject.getServiceTypesByPage(mockedRequest); assertTrue(errResp.contains("error")); - - String result = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result.contains("xyz")); - } - - @Test - public final void testGetServiceTypesByPage_Filter() { - User user = mockUser.mockUser(); - user.setLoginId("tester"); - MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - mockedRequest.addParameter("searchBy", "xyz"); - PowerMockito.mockStatic(DashboardProperties.class); - Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user); - - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> sampleStream = items.stream(); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); - Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream); - - String result = subject.getServiceTypesByPage(mockedRequest); - assertTrue(result.contains("xyz")); } - @Test - public final void testGetServicesByPage_auth() throws IOException { - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest(); - mockedRequest1.addParameter("searchBy", "dti"); - Collection<Service> items = deplList.items; - - HttpSession session = mockedRequest1.getSession(); - HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>(); - comp_deploy_tab.put("dcae", true); - - Set<String> userApps = new TreeSet<String>(); - userApps.add("dcae"); - - when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab); - when(session.getAttribute("role_level")).thenReturn("app"); - when(session.getAttribute("authComponents")).thenReturn(userApps); - - Stream<Service> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1); - - String result1 = subject.getServicesByPage(mockedRequest1); - assertTrue(result1.contains("dti")); - - } - - @Test - public final void testGetServicesByPage_auth_ops() throws IOException { - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest(); - mockedRequest1.addParameter("searchBy", "dti"); - - Collection<Service> items = deplList.items; - - HttpSession session = mockedRequest1.getSession(); - HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>(); - comp_deploy_tab.put("dcae", true); - - Set<String> userApps = new TreeSet<String>(); - userApps.add("dcae"); - - when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab); - when(session.getAttribute("role_level")).thenReturn("ops"); - when(session.getAttribute("authComponents")).thenReturn(userApps); - - Stream<Service> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1); - - String result1 = subject.getServicesByPage(mockedRequest1); - assertTrue(result1.contains("dti")); - - } - - @Test - public final void testGetServicesByPage() throws IOException { - /* - * User user = mockUser.mockUser(); user.setLoginId("tester"); - */ - MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest(); - mockedRequest1.addParameter("searchBy", "dti"); - mockedRequest1.addParameter("sortBy", "deploymentRef"); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); - - Collection<Service> items = deplList.items; - - Stream<Service> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1); - - String result1 = subject.getServicesByPage(mockedRequest1); - assertTrue(result1.contains("dti")); - } - - @Test - public final void testGetServicesByPage_sort_serviceId() throws IOException { - - MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - mockedRequest.addParameter("sortBy", "serviceId"); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); - - Collection<Service> items = deplList.items; - - Stream<Service> sampleStream1 = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1); - - String result = subject.getServicesByPage(mockedRequest); - assertTrue(result.contains("dti")); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<Service> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream2); - - String result2 = subject.getServicesByPage(mockedRequest); - assertTrue(result2.contains("dti")); - } - - @Test - public final void testGetServicesByPage_sort_created() throws IOException { - MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - mockedRequest.addParameter("sortBy", "created"); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); - - Collection<Service> items = deplList.items; - - Stream<Service> sampleStream = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream); - - String result = subject.getServicesByPage(mockedRequest); - assertTrue(result.contains("dti")); - - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<Service> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream2); - - String result2 = subject.getServicesByPage(mockedRequest); - assertTrue(result2.contains("dti")); - - } - - @Test - public final void testGetServicesByPage_sort_modified() throws IOException { - - MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); - mockedRequest.addParameter("sortBy", "modified"); - - PowerMockito.mockStatic(DashboardProperties.class); - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("os"); - - Collection<Service> items = deplList.items; - - Stream<Service> sampleStream = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream); - - String result = subject.getServicesByPage(mockedRequest); - assertTrue(result.contains("dti")); - - Mockito - .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth")) - .thenReturn("auth"); - - Stream<Service> sampleStream2 = items.stream(); - Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream2); - - String result2 = subject.getServicesByPage(mockedRequest); - assertTrue(result2.contains("dti")); - } @SuppressWarnings("unchecked") @Test @@ -670,38 +444,36 @@ public class InventoryControllerTest extends MockitoTestSuite { .thenThrow(BlueprintParseException.class).thenThrow(httpException) .thenThrow(Exception.class).thenReturn(null); - String actual1 = subject.updateServiceTypeBlueprint(mockedRequest, bpItem); + String actual1 = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull); assertTrue(actual1.contains("error")); - String actual2 = subject.updateServiceTypeBlueprint(mockedRequest, bpItem); + String actual2 = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull); assertTrue(actual2.contains("error")); - String actual3 = subject.updateServiceTypeBlueprint(mockedRequest, bpItem); + String actual3 = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull); assertTrue(actual3.contains("error")); - String actual = subject.updateServiceTypeBlueprint(mockedRequest, bpItem); + String actual = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull); assertEquals(expected, actual); } @Test - public final void testDeleteService() throws Exception { - String expected = "{\"202\": \"OK\"}"; - doNothing().doThrow(serviceException).doThrow(Exception.class).when(inventoryClient) - .deleteService(Matchers.anyString()); - - String actual = subject.deleteService("srvcId", mockedRequest, mockedResponse); - assertEquals(expected, actual); - - actual = subject.deleteService("srvcId", mockedRequest, mockedResponse); - assertTrue(actual.contains("error")); - - actual = subject.deleteService("srvcId", mockedRequest, mockedResponse); - assertTrue(actual.contains("error")); - } - - @Test public final void testDeleteServiceType() throws Exception { - String expected = "{\"202\": \"OK\"}"; + //String expected = "{\"202\": \"OK\"}"; + String expected = "{\"204\": \"Blueprint deleted\"}"; + List<CloudifyDeployedTenant> deplForBp = new ArrayList<>(); + deplForBp.clear(); + Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any())) + .thenReturn(deplForBp); + + List<ServiceRef> srvcRefList = new ArrayList<>(); + srvcRefList.clear(); + int itemCnt = 0; + ServiceRefList mockSvcRefList = new ServiceRefList(srvcRefList, itemCnt); + + Mockito.when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any())) + .thenReturn(mockSvcRefList); + doNothing().doThrow(serviceTypeException).doThrow(Exception.class).when(inventoryClient) .deleteServiceType(Matchers.anyString()); @@ -715,10 +487,24 @@ public class InventoryControllerTest extends MockitoTestSuite { assertTrue(actual.contains("error")); } + @Test + public final void testDeleteServiceType_withDepl() throws Exception { + CloudifyDeployedTenant mockCfyDeplTen = + new CloudifyDeployedTenant("id1", "tenant", "45435435", "54543534"); + + List<CloudifyDeployedTenant> deplForBp = new ArrayList<>(); + deplForBp.add(mockCfyDeplTen); + Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any())) + .thenReturn(deplForBp); + + String actual = subject.deleteServiceType("srvcId", mockedRequest, mockedResponse); + assertTrue(actual.contains("error")); + } + @SuppressWarnings("unchecked") @Test public final void testViewServiceTypeBlueprintContentById() throws Exception { - Optional<ServiceType> expected = Optional.of(bpItem); + Optional<ServiceType> expected = Optional.of(bpItemFull); when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(expected) .thenThrow(httpException).thenThrow(Exception.class); diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/model/ControllerOpsToolsTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/model/ControllerOpsToolsTest.java deleted file mode 100644 index 001df8d..0000000 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/model/ControllerOpsToolsTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved. - * - * Modifications Copyright (C) 2019 IBM. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -package org.onap.ccsdk.dashboard.model; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class ControllerOpsToolsTest { - - ControllerOpsTools co; - private String id="123"; - private String url="http//google.com"; - - @Test - public void testControllerOpsTools() { - ControllerOpsTools co= new ControllerOpsTools(); - ControllerOpsTools co1= new ControllerOpsTools(id,url); - assertEquals("123",co1.getId()); - assertEquals("http//google.com",co1.getUrl()); - } - -} diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImplTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImplTest.java index a5c5cf8..68223da 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImplTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImplTest.java @@ -31,8 +31,14 @@ import static org.mockito.Mockito.when; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Ignore; @@ -43,28 +49,32 @@ import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.onap.ccsdk.dashboard.model.CloudifyBlueprint; -import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant; -import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList; -import org.onap.ccsdk.dashboard.model.CloudifyDeployment; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest; -import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse; -import org.onap.ccsdk.dashboard.model.CloudifyEvent; -import org.onap.ccsdk.dashboard.model.CloudifyEventList; -import org.onap.ccsdk.dashboard.model.CloudifyEventList.Metadata; -import org.onap.ccsdk.dashboard.model.CloudifyExecution; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; -import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; -import org.onap.ccsdk.dashboard.model.CloudifyNodeId; -import org.onap.ccsdk.dashboard.model.CloudifyNodeIdList; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstance; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceId; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList; -import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList; -import org.onap.ccsdk.dashboard.model.CloudifyTenantList; +import org.onap.ccsdk.dashboard.core.MockitoTestSuite; +import org.onap.ccsdk.dashboard.core.MockitoTestSuite.MockHttpServletRequestWrapper; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprint; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenantList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEvent; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList.Metadata; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeId; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstance; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceId; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPlugin; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList; import org.onap.ccsdk.dashboard.util.DashboardProperties; +import org.onap.portalsdk.core.util.CacheManager; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -83,23 +93,27 @@ import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; @RunWith(PowerMockRunner.class) @PrepareForTest({DashboardProperties.class}) -public class CloudifyRestClientImplTest { +public class CloudifyRestClientImplTest extends MockitoTestSuite { @Mock RestTemplate mockRest; @InjectMocks CloudifyRestClientImpl subject = new CloudifyRestClientImpl(); - - protected final ObjectMapper objectMapper = new ObjectMapper(); + + HttpServletRequest mockedRequest; + HttpServletResponse mockedResponse; + protected final static ObjectMapper objectMapper = new ObjectMapper(); @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); objectMapper.registerModule(new Jdk8Module()); PowerMockito.mockStatic(DashboardProperties.class); - when(DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_URL)).thenReturn("https://orcl.com"); + when(DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL)).thenReturn("https://orcl.com"); + CacheManager testCache = new CacheManager(); + subject.setCacheManager(testCache); this.subject.init(); } @@ -288,31 +302,10 @@ public class CloudifyRestClientImplTest { } @Test - public final void testGetTenantInfoFromDeploy() { - - CloudifyDeployedTenant cldDeplTenant = new CloudifyDeployedTenant("id1", "bp1", "tenant1"); - List<CloudifyDeployedTenant> cldDeplTenantItems = new ArrayList<CloudifyDeployedTenant>(); - cldDeplTenantItems.add(cldDeplTenant); - CloudifyDeployedTenantList cldDeployedTenantList = - new CloudifyDeployedTenantList(cldDeplTenantItems, null); - - ResponseEntity<CloudifyDeployedTenantList> response = - new ResponseEntity<CloudifyDeployedTenantList>(cldDeployedTenantList, HttpStatus.OK); - - when(mockRest.exchange(Matchers.contains("deployments"), Matchers.eq(HttpMethod.GET), - Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<CloudifyDeployedTenantList>>any())) - .thenReturn(response); - - CloudifyDeployedTenantList actualResults = subject.getTenantInfoFromDeploy("tenant1"); - assertTrue(actualResults.items.get(0).blueprint_id.equals("bp1")); - } - - @Test public void testGetExecutions() { CloudifyExecution cldExecution = - new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1", - "tenant1", "error", "execution_id1", null, false, false); + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, + "bp1", "id1","tenant1", "error", "execution_id1", null); List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); @@ -336,8 +329,8 @@ public class CloudifyRestClientImplTest { @Test public void testGetExecutionsSummary() { CloudifyExecution cldExecution = - new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1", - "tenant1", "error", "execution_id1", null, false, false); + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); @@ -361,8 +354,8 @@ public class CloudifyRestClientImplTest { @Test public void testStartExecution() { - CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install", - false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false); + CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "ended-at", "install", + false, "bp1", "id1", "tenant1", "error", "execution_id1", null); Map<String, Object> params = new HashMap<String, Object>(); params.put("key1", "value1"); @@ -378,29 +371,10 @@ public class CloudifyRestClientImplTest { } @Test - public void testUpdateDeployment() { - CloudifyDeploymentUpdateRequest cfyDeployUpdateReq = - new CloudifyDeploymentUpdateRequest("deployment_id", "update", false, false, - "node_instance_id1", "4", "1000", "image", 2, "my_container"); - - CloudifyDeploymentUpdateResponse cfyDeployUpdateResp = new CloudifyDeploymentUpdateResponse( - "terminated", "created_at", "update", false, "blueprint_id", "deployment_id", "", "id1", - null, "tenant1", "junit", false, "resource_availability"); - - when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(), - Matchers.<Class<CloudifyDeploymentUpdateResponse>>any())) - .thenReturn(cfyDeployUpdateResp); - - CloudifyDeploymentUpdateResponse actualResult = - subject.updateDeployment(cfyDeployUpdateReq); - assertTrue(actualResult.status.equals("terminated")); - } - - @Test @Ignore public void testCancelExecution() { - CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install", - false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false); + CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "end_at", "install", + false, "bp1", "id1", "tenant1", "error", "execution_id1", null); Map<String, Object> params = new HashMap<String, Object>(); params.put("key1", "value1"); @@ -421,7 +395,6 @@ public class CloudifyRestClientImplTest { } @Test - @Ignore public void testGetBlueprint() { CloudifyBlueprint cldBp = new CloudifyBlueprint("file1", "description1", "343242", "3423423", "id1", null); @@ -441,16 +414,39 @@ public class CloudifyRestClientImplTest { doReturn(response).when(mockRest).exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(), - Matchers.<Class<CloudifyBlueprintList>>any()); + Matchers.<ParameterizedTypeReference<CloudifyBlueprintList>>any()); CloudifyBlueprintList actualResult = subject.getBlueprint("id1", "tenant1"); assertTrue(actualResult.items.get(0).id.equals("id1")); } @Test - @Ignore public void testGetDeployments() { + CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant"); + List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>(); + cfyDeployItems.add(cldDeployment); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata); + + ResponseEntity<CloudifyDeploymentList> response = + new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any())) + .thenReturn(response); + + CloudifyDeploymentList actualResult = subject.getDeployments("tenant", 10, 0); + assertTrue(actualResult.items.get(0).id.equals("id")); + } + + @Test + public void testGetDeployments_from_cache() { CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id", "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant"); @@ -466,11 +462,380 @@ public class CloudifyRestClientImplTest { ResponseEntity<CloudifyDeploymentList> response = new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK); - when(mockRest.exchange(Matchers.contains("deploy"), Matchers.eq(HttpMethod.GET), - Matchers.<HttpEntity<?>>any(), Matchers.<Class<CloudifyDeploymentList>>any())) + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any())) .thenReturn(response); + + List<CloudifyDeployment> actualResult = subject.getDeployments("tenant", 10, 0, true, true); + assertTrue(actualResult.get(0).id.equals("id")); + } + + @Test + public void testGetDeploymentForBlueprint() { + CloudifyDeployedTenant cfyDepTenant = + new CloudifyDeployedTenant("id", "tenant", "created_at", "updated_at"); + List<CloudifyDeployedTenant> cfyDepTenantList = new ArrayList<>(); + cfyDepTenantList.add(cfyDepTenant); + + CloudifyDeployedTenantList.Metadata.Pagination pageObj = + new CloudifyDeployedTenantList.Metadata.Pagination(1, 0, 1); + CloudifyDeployedTenantList.Metadata metadata = new CloudifyDeployedTenantList.Metadata(pageObj); + + CloudifyDeployedTenantList cldDeployList = new CloudifyDeployedTenantList(cfyDepTenantList, metadata); - CloudifyDeploymentList actualResult = subject.getDeployments(); + ResponseEntity<CloudifyDeployedTenantList> response = + new ResponseEntity<CloudifyDeployedTenantList>(cldDeployList, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyDeployedTenantList>>any())) + .thenReturn(response); + + List<CloudifyDeployedTenant> actuals = subject.getDeploymentForBlueprint("bpId"); + assertTrue(actuals.get(0).id.equals("id")); + } + + @Test + public void testGetDeploymentResource() { + CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant"); + + List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>(); + cfyDeployItems.add(cldDeployment); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata); + + ResponseEntity<CloudifyDeploymentList> response = + new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any())) + .thenReturn(response); + + CloudifyDeployment actualResult = subject.getDeploymentResource("id", "tenant"); + assertTrue(actualResult.id.equals("id")); + } + + @Test + public void testGetNodeInstanceDetails() { + CloudifyNodeInstance cfyNodeInstance = new CloudifyNodeInstance("id1", null); + + List<CloudifyNodeInstance> cfyNodeInstanceItems = new ArrayList<CloudifyNodeInstance>(); + cfyNodeInstanceItems.add(cfyNodeInstance); + + CloudifyNodeInstanceList cfyNodeInstList = + new CloudifyNodeInstanceList(cfyNodeInstanceItems, null); + + ResponseEntity<CloudifyNodeInstanceList> response2 = + new ResponseEntity<CloudifyNodeInstanceList>(cfyNodeInstList, HttpStatus.OK); + when(mockRest.exchange(Matchers.contains("node-instances"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyNodeInstanceList>>any())) + .thenReturn(response2); + + CloudifyNodeInstanceList actualResult = + subject.getNodeInstanceDetails("id", "tenant"); + assertTrue(actualResult.items.get(0).id.equals("id1")); + } + + @Test + public void testGetNodeInstances() { + CloudifyNodeInstanceId cfyNodeInstance = new CloudifyNodeInstanceId("id1"); + + List<CloudifyNodeInstanceId> cfyNodeInstanceItems = new ArrayList<CloudifyNodeInstanceId>(); + cfyNodeInstanceItems.add(cfyNodeInstance); + + CloudifyNodeInstanceIdList cfyNodeInstList = + new CloudifyNodeInstanceIdList(cfyNodeInstanceItems, null); + + ResponseEntity<CloudifyNodeInstanceIdList> response2 = + new ResponseEntity<CloudifyNodeInstanceIdList>(cfyNodeInstList, HttpStatus.OK); + when(mockRest.exchange(Matchers.contains("node-instances"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyNodeInstanceIdList>>any())) + .thenReturn(response2); + + CloudifyNodeInstanceIdList actualResult = + subject.getNodeInstances("id", "tenant"); + assertTrue(actualResult.items.get(0).id.equals("id1")); + } + + + @Test + public void testGetExecutionsSummaryPerTenant() { + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); + + cldExecutionList.add(cldExecution); + + CloudifyExecutionList cloudifyExecutionList = + new CloudifyExecutionList(cldExecutionList, null); + + ResponseEntity<CloudifyExecutionList> response = + new ResponseEntity<CloudifyExecutionList>(cloudifyExecutionList, HttpStatus.OK); + + when(mockRest.exchange(Matchers.contains("include"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyExecutionList>>any())) + .thenReturn(response); + + CloudifyExecutionList actualResult = + subject.getExecutionsSummaryPerTenant("tenant1"); + assertTrue(actualResult.items.get(0).id.contains("id1")); + } + + @Test + public void testGetExecutionIdSummary() { + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + ResponseEntity<CloudifyExecution> response = + new ResponseEntity<CloudifyExecution>(cldExecution, HttpStatus.OK); + when(mockRest.exchange(Matchers.contains("include"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyExecution>>any())) + .thenReturn(response); + CloudifyExecution actuals = subject.getExecutionIdSummary("execution_id1", "tenant"); + assertTrue(actuals.id.contains("execution_id1")); + } + + @Test + public void testGetInstallExecutionSummary() { + CloudifyExecution cldExecution = + new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1", + "tenant1", "error", "execution_id1", null); + + List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>(); + + cldExecutionList.add(cldExecution); + + CloudifyExecutionList cloudifyExecutionList = + new CloudifyExecutionList(cldExecutionList, null); + + ResponseEntity<CloudifyExecutionList> response = + new ResponseEntity<CloudifyExecutionList>(cloudifyExecutionList, HttpStatus.OK); + + when(mockRest.exchange(Matchers.contains("include"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyExecutionList>>any())) + .thenReturn(response); + + CloudifyExecutionList actualResult = + subject.getInstallExecutionSummary("id1", "tenant1"); + assertTrue(actualResult.items.get(0).id.contains("id1")); + } + + @Test + public void testViewBlueprint() { + byte[] outArr = "Any String you want".getBytes(); + ResponseEntity<byte[]> response = + new ResponseEntity<byte[]>(outArr, HttpStatus.OK); + + doReturn(response).when(mockRest).exchange(Matchers.anyString(), + Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(), + Matchers.<Class<?>>any()); + + subject.viewBlueprint("tenant1", "id1"); + } + + @Test + public void testGetDeploymentNamesWithFilter() throws Exception { + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + //mockedRequest.addParameter("filters", filterStr); + //mockedRequest.addParameter("sort", "name"); + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + + Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet); + Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps); + + String tenantsList = + "{\"items\": [{\"id\": 1, \"dName\": null, \"name\": \"default_tenant\"}, {\"id\": 2, \"dName\": null, \"name\": \"dyh1b1902\"}], \"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}"; + CloudifyTenantList sampleData = null; + try { + sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class); + } catch (Exception e) { + } + + ResponseEntity<CloudifyTenantList> response1 = + new ResponseEntity<CloudifyTenantList>(sampleData, HttpStatus.OK); + + + CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant"); + + List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>(); + cfyDeployItems.add(cldDeployment); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata); + + ResponseEntity<CloudifyDeploymentList> response2 = + new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK); + + Mockito + .when(mockRest.exchange(Matchers.contains("tenants"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyTenantList>>any())) + .thenReturn(response1); + + Mockito.when(mockRest.exchange(Matchers.contains("deployments"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any())) + .thenReturn(response2); + + List<String> actual = subject.getDeploymentNamesWithFilter(mockedRequest); + assertTrue(actual.size() > 0); + } + + @Test + public void testGetDeploymentsWithFilter() throws Exception { + MockHttpServletRequestWrapper mockedRequest = getMockedRequest(); + //mockedRequest.addParameter("filters", filterStr); + //mockedRequest.addParameter("sort", "name"); + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + + Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet); + Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps); + + String tenantsList = + "{\"items\": [{\"id\": 1, \"dName\": null, \"name\": \"default_tenant\"}, {\"id\": 2, \"dName\": null, \"name\": \"dyh1b1902\"}], \"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}"; + CloudifyTenantList sampleData = null; + try { + sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class); + } catch (Exception e) { + } + + ResponseEntity<CloudifyTenantList> response1 = + new ResponseEntity<CloudifyTenantList>(sampleData, HttpStatus.OK); + + + CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant"); + + List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>(); + cfyDeployItems.add(cldDeployment); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata); + + ResponseEntity<CloudifyDeploymentList> response2 = + new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK); + + Mockito + .when(mockRest.exchange(Matchers.contains("tenants"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyTenantList>>any())) + .thenReturn(response1); + + Mockito.when(mockRest.exchange(Matchers.contains("deployments"), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any())) + .thenReturn(response2); + + List<CloudifyDeployment> actuals = subject.getDeploymentsWithFilter(mockedRequest); + assertTrue(actuals.size() > 0); + } + + @Test + public void testGetSecret() { + String secretTokenStr = + "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}"; + CloudifySecret sampleData = null; + try { + sampleData = objectMapper.readValue(secretTokenStr, CloudifySecret.class); + } catch (Exception e) { + + } + + ResponseEntity<CloudifySecret> response = + new ResponseEntity<CloudifySecret>(sampleData, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifySecret>>any())) + .thenReturn(response); + + CloudifySecret actuals = subject.getSecret("acl_key", "tenant"); + assertTrue(actuals.getKey().equals("acl_key")); + } + + @Test + public void testDeleteBlueprint() { + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.DELETE), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyBlueprint>>any())).thenReturn(null); + subject.deleteBlueprint("bp", "tenant"); + } + + @Test + public void testGetPlugins() { + CloudifyPlugin sampleData = + new CloudifyPlugin("plugin1", "202001", "linux", "linux_k8s_plugin", "20200801"); + + List<CloudifyPlugin> cfyPlugins = new ArrayList<CloudifyPlugin>(); + cfyPlugins.add(sampleData); + + CloudifyPluginList.Metadata.Pagination pageObj = + new CloudifyPluginList.Metadata.Pagination(1, 0, 1); + CloudifyPluginList.Metadata metadata = new CloudifyPluginList.Metadata(pageObj); + + CloudifyPluginList cfyPluginList = new CloudifyPluginList(cfyPlugins, metadata); + ResponseEntity<CloudifyPluginList> response = + new ResponseEntity<CloudifyPluginList>(cfyPluginList, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifyPluginList>>any())) + .thenReturn(response); + + CloudifyPluginList actuals = subject.getPlugins(); + assertTrue(actuals.items.get(0).package_name.equals("plugin1")); + } + + @Test + public void testGetDeploymentInputs() { + CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id", + "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant"); + + List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>(); + cfyDeployItems.add(cldDeployment); + + CloudifyDeploymentList.Metadata.Pagination pageObj = + new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1); + CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj); + + CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata); + + ResponseEntity<CloudifyDeploymentList> response = + new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any())) + .thenReturn(response); + + CloudifyDeploymentList actualResult = subject.getDeploymentInputs("id", "tenant"); assertTrue(actualResult.items.get(0).id.equals("id")); } + + } + diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImplTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImplTest.java index f90afa9..7d85196 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImplTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImplTest.java @@ -23,26 +23,30 @@ package org.onap.ccsdk.dashboard.rest; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.mockito.Mockito.when; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; -import org.json.JSONObject; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.onap.ccsdk.dashboard.model.ConsulDatacenter; -import org.onap.ccsdk.dashboard.model.ConsulNodeInfo; -import org.onap.ccsdk.dashboard.model.ConsulServiceHealth; -import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret; +import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter; +import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth; +import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo; import org.onap.ccsdk.dashboard.util.DashboardProperties; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; @@ -64,22 +68,36 @@ public class ConsulRestClientImplTest { @Mock RestTemplate mockRest; - + @InjectMocks - ConsulRestClientImpl subject = new ConsulRestClientImpl(); + ConsulRestClientImpl subject; + + String[] svcTags = {"cfytenantname=onap"}; + + protected final static ObjectMapper objectMapper = new ObjectMapper(); + static HttpClientErrorException httpException; - protected final ObjectMapper objectMapper = new ObjectMapper(); - HttpClientErrorException httpException; + @BeforeClass + public static void setUpBeforeClass() throws Exception { + httpException = new HttpClientErrorException(HttpStatus.FORBIDDEN, "statusText"); + objectMapper.registerModule(new Jdk8Module()); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - objectMapper.registerModule(new Jdk8Module()); - httpException = new HttpClientErrorException(HttpStatus.BAD_REQUEST, "statusText"); PowerMockito.mockStatic(DashboardProperties.class); - when(DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_CONSUL_URL)).thenReturn("https://invt.com"); - this.subject.init(); + when(DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CONSUL_URL)).thenReturn("https://cnsl-svc.com"); + when(DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL)).thenReturn("https://orcl-svc.com"); + when(DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME)).thenReturn("admin"); + when(DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS)).thenReturn("admin"); + subject.setConsul_acl_token("consul_acl_token_for_dash"); + subject.init(); } @After @@ -87,13 +105,54 @@ public class ConsulRestClientImplTest { } @Test + public final void testGetConsulAcl() { + String secretTokenStr = + "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}"; + CloudifySecret sampleData = null; + try { + sampleData = objectMapper.readValue(secretTokenStr, CloudifySecret.class); + } catch (Exception e) { + } + + ResponseEntity<CloudifySecret> response = + new ResponseEntity<CloudifySecret>(sampleData, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<CloudifySecret>>any())) + .thenReturn(response); + String actualSecretStr = subject.getConsulAcl(mockRest); + assertTrue(actualSecretStr.equals("acl_token_val")); + } + + @Test(expected = Exception.class) + public final void testCreateCfyRestTemplate() throws Exception { + String webapiUrl = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL); + String user = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME); + String pass = DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS); + URL url = null; + try { + url = new URL(webapiUrl); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + String urlScheme = webapiUrl.split(":")[0]; + subject.createCfyRestTemplate(url, user, pass, urlScheme); + } + + @Test public final void testGetServiceHealth() { ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00", "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing", "This is a pgaas1_Service_ID health check", - "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n", - "pgaas1_Service_ID", "pgaasServer1", 190199, 199395); + "OK Output:", + "pgaas1_Service_ID", "pgaasServer1", svcTags, 34234, 4234); + // new ConsulServiceHealth() List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>(); expectedCnslSrvcHlth.add(consulSrvcHlth); @@ -109,21 +168,47 @@ public class ConsulRestClientImplTest { assertTrue(actualCnslSrvcHlth.get(0).node.equals("cjlvmcnsl00")); } + @Test(expected = Exception.class) + public final void get_svc_health_rest_client_exception() { + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any())) + .thenThrow(httpException); + + subject.getServiceHealth("dc1", "srvc1"); + } + + @Test(expected = Exception.class) + public final void get_services_rest_client_exception() { + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<Map<String, Object>>>any())) + .thenThrow(httpException); + subject.getServices("dc1"); + } + @Test - @Ignore public final void testGetServices() { List<String> srvcIps = new ArrayList<String>(); srvcIps.add("135.91.224.136"); srvcIps.add("135.91.224.138"); ConsulServiceInfo consulSrvcInfo = new ConsulServiceInfo("pgaasServer1", srvcIps); + Map<String, Object> respObj = new HashMap<String, Object>(); + respObj.put("pgaasServer1", srvcIps); + List<ConsulServiceInfo> expectedCnslSrvcs = new ArrayList<ConsulServiceInfo>(); expectedCnslSrvcs.add(consulSrvcInfo); - // ResponseEntity<Map<String, Object>> response = new ResponseEntity<Map<String, - // Object>>(consulSrvcInfo); + ResponseEntity<Map<String, Object>> response = + new ResponseEntity<Map<String,Object>>(respObj, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<Map<String, Object>>>any())).thenReturn(response); - subject.getServices("dc1"); + List<ConsulServiceInfo> actualSvcList = subject.getServices("dc1"); + assertTrue(actualSvcList.get(0).name.equals("pgaasServer1")); } @Test @@ -146,13 +231,22 @@ public class ConsulRestClientImplTest { } + @Test(expected = Exception.class) + public final void get_nodes_rest_client_exception() { + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<List<ConsulNodeInfo>>>any())) + .thenThrow(httpException); + subject.getNodes("dc1"); + } + @Test public final void testGetNodeServicesHealth() { ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00", "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing", "This is a pgaas1_Service_ID health check", "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n", - "pgaas1_Service_ID", "pgaasServer1", 190199, 199395); + "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395); List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>(); expectedCnslSrvcHlth.add(consulSrvcHlth); @@ -170,6 +264,15 @@ public class ConsulRestClientImplTest { assertTrue(actualNodeHlthList.get(0).node.equals("cjlvmcnsl00")); } + @Test(expected = Exception.class) + public final void get_node_svc_rest_client_exception() { + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any())) + .thenThrow(httpException); + subject.getNodeServicesHealth("dc1", "nodeId1"); + } + @Test public final void testGetDatacenters() { ConsulDatacenter cnslDc = new ConsulDatacenter("dc1"); @@ -189,24 +292,45 @@ public class ConsulRestClientImplTest { assertTrue(actualDcList.get(0).name.equals("dc1")); } - @Test - @Ignore - public final void testRegisterService() { - fail("Not yet implemented"); // TODO + @Test(expected = Exception.class) + public final void get_dc_rest_client_exception() { + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<List<String>>>any())) + .thenThrow(httpException); + subject.getDatacenters(); } - + @Test - public final void testDeregisterService() { + public final void testGetServiceHealthByDeploymentId() { + ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00", + "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing", + "This is a pgaas1_Service_ID health check", + "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n", + "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395); - JSONObject jsonResp = new JSONObject(); + List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>(); + expectedCnslSrvcHlth.add(consulSrvcHlth); - ResponseEntity<JSONObject> result = new ResponseEntity<JSONObject>(jsonResp, HttpStatus.OK); - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT), - Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<JSONObject>>any())) - .thenReturn(result); + ResponseEntity<List<ConsulServiceHealth>> response = + new ResponseEntity<List<ConsulServiceHealth>>(expectedCnslSrvcHlth, HttpStatus.OK); - int actualCode = subject.deregisterService("service1"); - assertTrue(actualCode == 200); - } + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any())) + .thenReturn(response); + ConsulDeploymentHealth cdh = subject.getServiceHealthByDeploymentId("deploymentId"); + assertTrue(cdh.getNode().equals("cjlvmcnsl00")); + } + + @Test(expected = Exception.class) + public final void get_svc_health_by_depId_rest_client_exception() { + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any())) + .thenThrow(httpException); + subject.getServiceHealthByDeploymentId("deploymentId"); + } + } diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImplTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImplTest.java index 7bd085b..2024d72 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImplTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImplTest.java @@ -36,17 +36,20 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Matchers; import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.onap.ccsdk.dashboard.exceptions.BadRequestException; import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException; import org.onap.ccsdk.dashboard.exceptions.DownstreamException; import org.onap.ccsdk.dashboard.exceptions.ServerErrorException; import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException; +import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentLink; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks; import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentsListResponse; import org.onap.ccsdk.dashboard.util.DashboardProperties; +import org.onap.portalsdk.core.util.CacheManager; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -66,16 +69,21 @@ public class DeploymentHandlerClientImplTest { @Mock RestTemplate mockRest; + @Mock + CloudifyClient cfyClient; + @InjectMocks DeploymentHandlerClientImpl subject; @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); PowerMockito.mockStatic(DashboardProperties.class); - when(DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_DHANDLER_URL)).thenReturn("https://dplh.com"); + when(DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_DHANDLER_URL)).thenReturn("https://dplh.com"); + CacheManager testCache = new CacheManager(); + subject.setCacheManager(testCache); this.subject.init(); - } @After @@ -83,6 +91,21 @@ public class DeploymentHandlerClientImplTest { } @Test + public final void testCheckHealth() { + String expectStr = "DH mS health check"; + ResponseEntity<String> response = + new ResponseEntity<String>(expectStr, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<String>>any())).thenReturn(response) + .thenReturn(response); + + String actualStr = subject.checkHealth(); + assertTrue(actualStr.equals(expectStr)); + } + + @Test public final void testGetDeployments() { Collection<DeploymentLink> expectedDeplRefs = new ArrayList<DeploymentLink>(); expectedDeplRefs.add(new DeploymentLink("http://dplh.com/dpl1")); @@ -206,93 +229,6 @@ public class DeploymentHandlerClientImplTest { } @Test - public final void testUpdateDeployment() throws Exception { - DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null); - - DeploymentResponseLinks newDeplItemLink = - new DeploymentResponseLinks("selfUrl", "statusUrl"); - DeploymentResponse expectedDeplItem = new DeploymentResponse("req1", newDeplItemLink); - - ResponseEntity<DeploymentResponse> response = - new ResponseEntity<DeploymentResponse>(expectedDeplItem, HttpStatus.OK); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT), - Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())).thenReturn(response); - - DeploymentResponse actualResponse = subject.updateDeployment("dpl12", "tenant12", deplReq); - assertTrue(actualResponse.getRequestId().equals("req1")); - } - - @Test(expected = DownstreamException.class) - public final void testUpdateDeployment_downstreamError() throws Exception { - - DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null); - - HttpServerErrorException httpException = - new HttpServerErrorException(HttpStatus.BAD_GATEWAY, "statusText"); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT), - Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())) - .thenThrow(httpException); - - subject.updateDeployment("dpl12", "tenant12", deplReq); - - } - - @Test(expected = BadRequestException.class) - public final void testUpdateDeployment_badReqError() throws Exception { - - DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null); - - HttpClientErrorException httpException = - new HttpClientErrorException(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "statusText"); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT), - Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())) - .thenThrow(httpException); - - subject.updateDeployment("dpl12", "tenant12", deplReq); - - } - - @Test(expected = ServiceAlreadyExistsException.class) - public final void testUpdateDeployment_srvcExistError() throws Exception { - - DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null); - - HttpClientErrorException httpException = - new HttpClientErrorException(HttpStatus.CONFLICT, "statusText"); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT), - Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())) - .thenThrow(httpException); - - subject.updateDeployment("dpl12", "tenant12", deplReq); - - } - - @Test(expected = ServerErrorException.class) - public final void testUpdateDeployment_srvcError() throws Exception { - - DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null); - - HttpServerErrorException httpException = - new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "statusText"); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT), - Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())) - .thenThrow(httpException); - - subject.updateDeployment("dpl12", "tenant12", deplReq); - - } - - @Test public final void testDeleteDeployment() throws Exception { DeploymentResponseLinks newDeplItemLink = new DeploymentResponseLinks("selfUrl", "statusUrl"); @@ -305,6 +241,12 @@ public class DeploymentHandlerClientImplTest { Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())).thenReturn(response); + CloudifyDeployment cfyDepl = + new CloudifyDeployment("description", "blueprint_id", "created_at", "updated_at", + "id", null, null, null, null, null, null, null, "tenant_name"); + + when(cfyClient.getDeploymentResource(Matchers.anyString(), Matchers.anyString())).thenReturn(cfyDepl); + subject.deleteDeployment("deploymentId", "tenant"); } diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImplTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImplTest.java index d4c5e14..e0452d0 100644 --- a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImplTest.java +++ b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImplTest.java @@ -30,6 +30,9 @@ import static org.mockito.Mockito.when; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Stream; @@ -52,7 +55,11 @@ import org.onap.ccsdk.dashboard.model.inventory.ServiceType; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams; import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary; +import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList; import org.onap.ccsdk.dashboard.util.DashboardProperties; +import org.onap.portalsdk.core.util.CacheManager; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -84,9 +91,13 @@ public class RestInventoryClientImplTest { ServiceList deplListNext = null; Service deplItem = null; - ServiceType bpItem = null; - ServiceTypeList bpList = null; - ServiceTypeList bpListNext = null; + ServiceTypeSummary bpItem, bpItem2 = null; + ServiceTypeSummaryList bpList, bpList2 = null; + + ServiceType bpItemFull = null; + ServiceTypeList bpItemFullList = null; + + ServiceTypeSummaryList bpListNext = null; ServiceTypeRequest bpUploadItem = null; @@ -94,11 +105,13 @@ public class RestInventoryClientImplTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); objectMapper.registerModule(new Jdk8Module()); - getExpectedBueprints(); + getExpectedBlueprints(); getExpectedDeployments(); PowerMockito.mockStatic(DashboardProperties.class); - when(DashboardProperties.getControllerProperty("dev", - DashboardProperties.CONTROLLER_SUBKEY_INVENTORY_URL)).thenReturn("https://invt.com"); + when(DashboardProperties.getControllerProperty("site.primary", + DashboardProperties.SITE_SUBKEY_INVENTORY_URL)).thenReturn("https://invt.com"); + CacheManager testCache = new CacheManager(); + subject.setCacheManager(testCache); this.subject.init(); } @@ -122,96 +135,124 @@ public class RestInventoryClientImplTest { ServiceList.PaginationLinks paginationLinks2 = objectMapper.readValue(pageLinks2, ServiceList.PaginationLinks.class); - int totalCount = 2; - deplList = new ServiceList(items, totalCount, paginationLinks); + int totalCount = 1; + deplList = new ServiceList(items, totalCount, paginationLinks2); deplListNext = new ServiceList(items, totalCount, paginationLinks2); } - - public void getExpectedBueprints() + + public void getExpectedBlueprints() throws JsonParseException, JsonMappingException, IOException { - bpItem = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906, + + bpItem = new ServiceTypeSummary.Builder().application("app1").component("comp1"). + typeName("xyz1731-helm-1906").owner("xyz1731").typeVersion(1906).build(); + + bpItem2 = new ServiceTypeSummary("xyz1731", "xyz1731-helm-1906", 1906, "app1", "comp1", "123-456-789", + "342343", true); + bpItemFull = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906, "tosca_definitions_version: cloudify_dsl_1_3", "", "app1", "comp1").build(); - Collection<ServiceType> items = new ArrayList<ServiceType>(); - items.add(bpItem); + Collection<ServiceTypeSummary> items = new ArrayList<ServiceTypeSummary>(); + items.add(bpItem); + Collection<ServiceTypeSummary> items2 = new ArrayList<ServiceTypeSummary>(); + items2.add(bpItem2); + String pageLinks = - "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}"; + "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-service-types/?offset=25\"}}"; String pageLinks2 = "{\"previousLink\":null,\"nextLink\":null}"; - ServiceTypeList.PaginationLinks paginationLinks = - objectMapper.readValue(pageLinks, ServiceTypeList.PaginationLinks.class); - ServiceTypeList.PaginationLinks paginationLinks2 = - objectMapper.readValue(pageLinks2, ServiceTypeList.PaginationLinks.class); + ServiceTypeSummaryList.PaginationLinks paginationLinks = + objectMapper.readValue(pageLinks, ServiceTypeSummaryList.PaginationLinks.class); + ServiceTypeSummaryList.PaginationLinks paginationLinks2 = + objectMapper.readValue(pageLinks2, ServiceTypeSummaryList.PaginationLinks.class); int totalCount = 2; - bpList = new ServiceTypeList(items, totalCount, paginationLinks); - bpListNext = new ServiceTypeList(items, totalCount, paginationLinks2); + bpList = new ServiceTypeSummaryList(items, totalCount, paginationLinks); + bpList2 = new ServiceTypeSummaryList(items2, totalCount, paginationLinks); + bpListNext = new ServiceTypeSummaryList(items, totalCount, paginationLinks2); } @Test - @Ignore - public final void testInit() { - fail("Not yet implemented"); // TODO + public final void testCheckHealth() { + String expectStr = "Inventory mS health check"; + ResponseEntity<String> response = + new ResponseEntity<String>(expectStr, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<String>>any())).thenReturn(response) + .thenReturn(response); + + String actualStr = subject.checkHealth(); + assertTrue(actualStr.equals(expectStr)); } @Test public final void testGetServiceTypes() { - /* - * String serviceTypeStr = - * "{\"paginationLinks\":{\"previousLink\":null,\"nextLink\":null}},\"totalCount\":32,\"items\":[{\"owner\":\"xyz1731\",\"typeName\":\"xyz1731-helm-1906\",\"typeVersion\":1906,\"blueprintTemplate\":\"tosca_definitions_version: cloudify_dsl_1_3\\nimports:\\n - http://www.getcloudify.org/spec/cloudify/4.2/types.yaml\\n - http://dockercentral.it.att.com:8093/nexus/repository/rawcentral/com.att.dcae.controller/type_files/helm/3.0.1/helm-type.yaml\\ninputs:\\n deployment-description:\\n default: ''\\n chart-name:\\n default: ''\\n tiller-server:\\n default: ''\\n tiller-server-port:\\n default: ''\\n namespace:\\n default: ''\\n chart-repo-url:\\n default: http://32.68.14.161/charts\\n chart-version :\\n default: ''\\n config-url:\\n default: ''\\n config-format:\\n default: ''\\n tls-enable:\\n description: enable helm TSL\\n type: boolean\\n default: false\\n config-dir:\\n description: config dir\\n type: string\\n default: '/opt/manager/resources/'\\n stable-repo-url:\\n description: URL for stable repository\\n type: string\\n default: 'http://32.68.14.161/stable'\\nnode_templates:\\n ecompcomponent:\\n type: onap.nodes.component\\n properties:\\n tiller-server-ip: { get_input: tiller-server }\\n tiller-server-port: { get_input: tiller-server-port }\\n component-name: { get_input: chart-name }\\n chart-repo-url: { concat: [ 'http://', { get_secret: controller_helm_user }, ':', { get_secret: controller_helm_password }, '@', { get_input: chart-repo-url } ] }\\n chart-version: { get_input: chart-version }\\n namespace: { get_input: namespace }\\n config-url: { concat: [ 'http://', { get_secret: controller_helm_user }, ':', { get_secret: controller_helm_password }, '@', { get_input: config-url } ] }\\n config-format: { get_input: config-format}\\n tls-enable: { get_input: tls-enable}\\n ca: { get_secret: ca_value}\\n cert: { get_secret: cert_value}\\n key: { get_secret: key_value}\\n config-dir: { get_input: config-dir}\\n stable-repo-url: { concat: [ 'http://', { get_secret: controller_helm_user }, ':', { get_secret: controller_helm_password }, '@', { get_input: stable-repo-url } ] }\\noutputs:\\n ecompcomponent-helm-output:\\n description: helm value and helm history\\n value:\\n helm-value: { get_attribute: [ecompcomponent, current-helm-value] }\\n helm-history: { get_attribute: [ecompcomponent, helm-history] }\",\"serviceIds\":[],\"vnfTypes\":[],\"serviceLocations\":[],\"asdcServiceId\":\"\",\"asdcResourceId\":\"\",\"asdcServiceURL\":null,\"application\":\"ECOMP\",\"component\":\"controller\",\"typeId\":\"72b8577a-5043-43ab-9aa5-6808b8f53967\",\"selfLink\":{\"rel\":\"self\",\"href\":\"https://ecompc-invt-dev-s5.ecomp.idns.cip.att.com:30123/dcae-service-types/72b8577a-5043-43ab-9aa5-6808b8f53967\"},\"created\":1551214264536,\"deactivated\":null}]" - * ; ServiceTypeList sampleData = null; try { sampleData = - * objectMapper.readValue(serviceTypeStr, ServiceTypeList.class); } catch - * (Exception e) { } - */ - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> expectedResult = items.stream(); - - ResponseEntity<ServiceTypeList> response = - new ResponseEntity<ServiceTypeList>(bpList, HttpStatus.OK); - - ResponseEntity<ServiceTypeList> response2 = - new ResponseEntity<ServiceTypeList>(bpListNext, HttpStatus.OK); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> expectedResult = items.stream(); + + ResponseEntity<ServiceTypeSummaryList> response = + new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK); + + ResponseEntity<ServiceTypeSummaryList> response2 = + new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK); when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<ServiceTypeList>>any())).thenReturn(response) + Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response) .thenReturn(response2); - Stream<ServiceType> actualResult = subject.getServiceTypes(); + Stream<ServiceTypeSummary> actualResult = subject.getServiceTypes(); assertNotNull(actualResult); assertTrue(expectedResult.count() == actualResult.count()); } @Test + public final void testCacheServiceTypes() { + ResponseEntity<ServiceTypeSummaryList> response = + new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK); + + ResponseEntity<ServiceTypeSummaryList> response2 = + new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK); + + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response) + .thenReturn(response2); + + subject.cacheServiceTypes(); + } + + @Test public final void testGetServiceTypesServiceTypeQueryParams() { ServiceTypeQueryParams qryParms = new ServiceTypeQueryParams.Builder() .asdcResourceId("asdcResourceId").asdcServiceId("asdcServiceId").onlyActive(true) .onlyLatest(false).serviceId("serviceId").serviceLocation("serviceLocation") .typeName("typeName").vnfType("vnfType").build(); - Collection<ServiceType> items = bpList.items; - Stream<ServiceType> expectedResult = items.stream(); + Collection<ServiceTypeSummary> items = bpList.items; + Stream<ServiceTypeSummary> expectedResult = items.stream(); - ResponseEntity<ServiceTypeList> response = - new ResponseEntity<ServiceTypeList>(bpList, HttpStatus.OK); + ResponseEntity<ServiceTypeSummaryList> response = + new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK); - ResponseEntity<ServiceTypeList> response2 = - new ResponseEntity<ServiceTypeList>(bpListNext, HttpStatus.OK); + ResponseEntity<ServiceTypeSummaryList> response2 = + new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK); when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<ServiceTypeList>>any())).thenReturn(response) + Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response) .thenReturn(response2); - Stream<ServiceType> actualResult = subject.getServiceTypes(qryParms); + Stream<ServiceTypeSummary> actualResult = subject.getServiceTypes(qryParms); assertNotNull(actualResult); assertTrue(expectedResult.count() == actualResult.count()); } @Test public final void testGetServiceType() { - Optional<ServiceType> expectedResult = Optional.of(bpItem); + Optional<ServiceType> expectedResult = Optional.of(bpItemFull); ResponseEntity<ServiceType> response = - new ResponseEntity<ServiceType>(bpItem, HttpStatus.OK); + new ResponseEntity<ServiceType>(bpItemFull, HttpStatus.OK); when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceType>>any())) @@ -222,140 +263,87 @@ public class RestInventoryClientImplTest { } @Test - public final void testAddServiceTypeServiceType() { - - when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(), - Matchers.<Class<ServiceType>>any())).thenReturn(bpItem); - - ServiceType actualResult = subject.addServiceType(bpItem); - assertTrue(actualResult.getTypeName().contains("xyz")); - } - - @Test - public final void testAddServiceTypeServiceTypeRequest() { - ServiceTypeRequest srvcReq = ServiceTypeRequest.from(bpItem); - - when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(), - Matchers.<Class<ServiceType>>any())).thenReturn(bpItem); - - ServiceType actualResult = subject.addServiceType(srvcReq); - assertTrue(actualResult.getTypeName().contains("xyz")); - } - - @Test - public final void testDeleteServiceType() throws Exception { - ResponseEntity<ApiResponseMessage> response = - new ResponseEntity<ApiResponseMessage>(HttpStatus.OK); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.DELETE), - Matchers.<HttpEntity<?>>any(), - Matchers.<ParameterizedTypeReference<ApiResponseMessage>>any())).thenReturn(response); - - subject.deleteServiceType("4243234"); - } - - @Test - public final void testGetServices() { - - Collection<Service> items = deplList.items; - Stream<Service> expectedResult = items.stream(); - + public final void testGetServicesForType() throws Exception { + String typeId = "44234234"; + ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434"); + Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>(); + expectedSrvcIds.add(expectedSrvc); + ServiceRefList expectedSvcRefList = new ServiceRefList(expectedSrvcIds, 1); ResponseEntity<ServiceList> response = new ResponseEntity<ServiceList>(deplList, HttpStatus.OK); - ResponseEntity<ServiceList> response2 = - new ResponseEntity<ServiceList>(deplListNext, HttpStatus.OK); - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceList>>any())) - .thenReturn(response).thenReturn(response2); - - Stream<Service> actualResult = subject.getServices(); - assertNotNull(actualResult); - assertTrue(expectedResult.count() == actualResult.count()); - - } - - @Test - public final void testGetServicesForType() { - ResponseEntity<ServiceList> response = - new ResponseEntity<ServiceList>(deplList, HttpStatus.OK); - - ResponseEntity<ServiceList> response2 = - new ResponseEntity<ServiceList>(deplListNext, HttpStatus.OK); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), - Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceList>>any())) - .thenReturn(response).thenReturn(response2); - ServiceQueryParams qryParms = new ServiceQueryParams.Builder().typeId("typeId").build(); - - ServiceRefList actualResult = subject.getServicesForType(qryParms); - assertTrue(actualResult.items.size() == 2); - ServiceRef actualSrvcItem = (ServiceRef) actualResult.items.toArray()[0]; - assertTrue(actualSrvcItem.getServiceId().contains("dtiapi")); - + .thenReturn(response); + + ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build(); + ServiceRefList actualSvcRefList = subject.getServicesForType(qryParams); + assertTrue(actualSvcRefList.totalCount == expectedSvcRefList.totalCount); } - + @Test - public final void testGetServicesServiceQueryParams() { - ServiceQueryParams qryParms = new ServiceQueryParams.Builder().typeId("typeId") - .vnfId("vnfId").vnfLocation("vnfLocation").vnfType("vnfType") - .componentType("componentType").shareable(false).created("43443423").build(); - - Collection<Service> items = deplList.items; - Stream<Service> expectedResult = items.stream(); - - ResponseEntity<ServiceList> response = - new ResponseEntity<ServiceList>(deplList, HttpStatus.OK); - - ResponseEntity<ServiceList> response2 = - new ResponseEntity<ServiceList>(deplListNext, HttpStatus.OK); - - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), - Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceList>>any())) - .thenReturn(response).thenReturn(response2); + public final void testAddServiceTypeServiceType() { - Stream<Service> actualResult = subject.getServices(qryParms); - assertTrue(expectedResult.count() == actualResult.count()); - } + when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(), + Matchers.<Class<ServiceType>>any())).thenReturn(bpItemFull); - @Test - public final void testGetService() { - Optional<Service> expectedResult = Optional.of(deplItem); + ResponseEntity<ServiceTypeSummaryList> response = + new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK); - ResponseEntity<Service> response = new ResponseEntity<Service>(deplItem, HttpStatus.OK); + ResponseEntity<ServiceTypeSummaryList> response2 = + new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK); when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), - Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<Service>>any())) - .thenReturn(response); - - Optional<Service> actualResult = subject.getService("432432423"); - assertTrue( - expectedResult.get().getDeploymentRef().equals(actualResult.get().getDeploymentRef())); + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response) + .thenReturn(response2); + + ServiceType actualResult = subject.addServiceType(bpItemFull); + assertTrue(actualResult.getTypeName().contains("xyz")); } @Test - public final void testPutService() { + public final void testAddServiceTypeServiceTypeRequest() { + ServiceTypeRequest srvcReq = ServiceTypeRequest.from(bpItemFull); - ResponseEntity<Service> response = new ResponseEntity<Service>(deplItem, HttpStatus.OK); + when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(), + Matchers.<Class<ServiceType>>any())).thenReturn(bpItemFull); + + ResponseEntity<ServiceTypeSummaryList> response = + new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK); - when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT), - Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<Service>>any())) - .thenReturn(response); + ResponseEntity<ServiceTypeSummaryList> response2 = + new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK); - subject.putService("423423", deplItem); + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response) + .thenReturn(response2); + ServiceType actualResult = subject.addServiceType(srvcReq); + assertTrue(actualResult.getTypeName().contains("xyz")); } @Test - public final void testDeleteService() throws Exception { + public final void testDeleteServiceType() throws Exception { ResponseEntity<ApiResponseMessage> response = new ResponseEntity<ApiResponseMessage>(HttpStatus.OK); when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.DELETE), Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ApiResponseMessage>>any())).thenReturn(response); + + ResponseEntity<ServiceTypeSummaryList> response1 = + new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK); + + ResponseEntity<ServiceTypeSummaryList> response2 = + new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK); - subject.deleteService("4243234"); + when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET), + Matchers.<HttpEntity<?>>any(), + Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response1) + .thenReturn(response2); + + subject.deleteServiceType("4243234"); } } diff --git a/ccsdk-app-os/create_table.sql b/ccsdk-app-os/create_table.sql index 9c89ffd..837c813 100644 --- a/ccsdk-app-os/create_table.sql +++ b/ccsdk-app-os/create_table.sql @@ -1144,4 +1144,7 @@ INSERT INTO dashboard_pg_db_common.fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDE Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_api'); Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (2,'menu_api'); Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (3,'menu_api'); -Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_api');
\ No newline at end of file +Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_api'); + +INSERT INTO dashboard_pg_db_common.fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC) + VALUES (30015,'Cloudify Plugins', 30011, 50,'ecd#/iplug', 'menu_inventory', 'Y','N/A','N/A','N/A','N/A','APP','N',NULL);
\ No newline at end of file diff --git a/ccsdk-app-os/pom.xml b/ccsdk-app-os/pom.xml index 7b71941..8c8b017 100644 --- a/ccsdk-app-os/pom.xml +++ b/ccsdk-app-os/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-parent</artifactId> - <version>1.3.2-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-os</artifactId> - <version>1.3.2-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>war</packaging> <name>ONAP Operations Manager Dashboard app</name> <description>CCSDK Dashboard Web Application for external release</description> @@ -68,7 +68,7 @@ <finalName>${project.artifactId}-${build.version}</finalName> <plugins> - <!-- Compile to Java 1.8 class output format --> + <!-- Compile to Java 1.8 class output format --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> @@ -111,6 +111,14 @@ <overlay> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-overlay</artifactId> + <excludes> + <exclude>app/ccsdk/home/api_view.html</exclude> + <exclude>app/ccsdk/home/ecd_router.js</exclude> + <exclude>app/ccsdk/home/executions_view.html</exclude> + <exclude>app/ccsdk/home/executions-view-controller.js</exclude> + <exclude>app/ccsdk/home/ecd_spa.html</exclude> + <exclude>app/ccsdk/home/ecd-style.css</exclude> + </excludes> </overlay> <overlay> <groupId>org.onap.portal.sdk</groupId> diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppConfig.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppConfig.java index 807ae78..665e0da 100644 --- a/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppConfig.java +++ b/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppConfig.java @@ -21,18 +21,16 @@ package org.onap.portalapp.conf; import java.util.ArrayList; import java.util.List; - -import org.onap.portalapp.lm.FusionLicenseManagerImpl; import org.onap.portalapp.login.LoginStrategyImpl; import org.onap.portalapp.controller.core.SingleSignOnController; import org.onap.portalapp.controller.sample.ElasticSearchController; import org.onap.portalapp.controller.sample.PostDroolsController; +import org.onap.portalapp.interceptor.AuthenticationInterceptor; +import org.onap.portalapp.interceptor.AuthorizationInterceptor; import org.onap.portalapp.scheduler.LogRegistry; import org.onap.portalsdk.core.auth.LoginStrategy; import org.onap.portalsdk.core.conf.AppConfig; import org.onap.portalsdk.core.conf.Configurable; -// import org.onap.portalsdk.core.lm.FusionLicenseManager; -// import org.onap.portalsdk.core.lm.FusionLicenseManagerUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.objectcache.AbstractCacheManager; import org.onap.portalsdk.core.scheduler.CoreRegister; @@ -54,6 +52,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; + /** * ECOMP Portal SDK sample application. ECOMP Portal SDK core AppConfig class to * reuse interceptors, view resolvers and other features defined there. @@ -75,6 +74,8 @@ public class ExternalAppConfig extends AppConfig implements Configurable { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ExternalAppConfig.class); + private static final String HEALTH = "/health*"; + @Configuration @Import(SystemProperties.class) static class InnerConfiguration { @@ -133,6 +134,16 @@ public class ExternalAppConfig extends AppConfig implements Configurable { return definitions; } + @Bean + public AuthenticationInterceptor authenticationInterceptor() { + return new AuthenticationInterceptor(); + } + + @Bean + public AuthorizationInterceptor authorizationInterceptor() { + return new AuthorizationInterceptor(); + } + /** * Adds request interceptors to the specified registry by calling * {@link AppConfig#addInterceptors(InterceptorRegistry)}, but excludes @@ -140,6 +151,8 @@ public class ExternalAppConfig extends AppConfig implements Configurable { */ @Override public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/nb-api/**"); + registry.addInterceptor(authorizationInterceptor()).addPathPatterns("/nb-api/**"); super.setExcludeUrlPathsForSessionTimeout("/login_external", "*/login_external.htm", "login", "/login.htm", "/api*", "/single_signon.htm", "/single_signon", "/health*", "/nb-api/**"); @@ -171,4 +184,5 @@ public class ExternalAppConfig extends AppConfig implements Configurable { public LoginStrategy loginStrategy() { return new LoginStrategyImpl(); } + } diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppInitializer.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppInitializer.java index 9c6b95e..2624e2f 100644 --- a/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppInitializer.java +++ b/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppInitializer.java @@ -19,11 +19,31 @@ */ package org.onap.portalapp.conf; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + import org.onap.ccsdk.dashboard.util.DashboardProperties; import org.onap.portalsdk.core.conf.AppInitializer; +import org.onap.portalsdk.core.logging.format.AlarmSeverityEnum; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.web.context.WebApplicationContext; public class ExternalAppInitializer extends AppInitializer { + /* + @Override + protected WebApplicationContext createServletApplicationContext() { + WebApplicationContext context = super.createServletApplicationContext(); + try { + ((ConfigurableEnvironment) context.getEnvironment()).setActiveProfiles("onap"); + } catch (Exception e) { + System.out.println("Unable to set the active profile" + e.getMessage()); + //throw e; + } + return context; + } +*/ @Override protected Class<?>[] getRootConfigClasses() { return super.getRootConfigClasses(); diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/HibernateMappingLocations.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/HibernateMappingLocations.java index 673fc8d..844ae36 100644 --- a/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/HibernateMappingLocations.java +++ b/ccsdk-app-os/src/main/java/org/onap/portalapp/conf/HibernateMappingLocations.java @@ -43,8 +43,8 @@ public class HibernateMappingLocations implements HibernateMappingLocatable { // a leading slash gets stripped so don't bother. // new ClassPathResource("../fusion/orm/Fusion.hbm.xml"), // This is a COPY to work around a bug in the 1.1.0 release. - new ClassPathResource("../fusion/orm/Fusion.hbm.xml"), - new ClassPathResource("../oom-app.hbm.xml")}; + new ClassPathResource("../fusion/orm/Fusion.hbm.xml")}; + //new ClassPathResource("../oom-app.hbm.xml")}; } /* diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthenticationInterceptor.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthenticationInterceptor.java new file mode 100644 index 0000000..206f364 --- /dev/null +++ b/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthenticationInterceptor.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.portalapp.interceptor; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +//import javax.xml.bind.DatatypeConverter; +import java.util.Base64; + +import org.apache.http.HttpStatus; +import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.service.UserProfileService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +public class AuthenticationInterceptor implements HandlerInterceptor { + + @Autowired + private UserProfileService userSvc; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String authString = request.getHeader("Authorization"); + try { + if(authString == null || authString.isEmpty()) + { + response.setStatus(HttpStatus.SC_UNAUTHORIZED); + response.sendError(HttpStatus.SC_UNAUTHORIZED, "Authentication information is missing"); + return false; //Do not continue with request + } else { + String decodedAuth = ""; + String[] authParts = authString.split("\\s+"); + String authInfo = authParts[1]; + byte[] bytes = null; + bytes = Base64.getDecoder().decode(authInfo); + //DatatypeConverter.parseBase64Binary(authInfo); + decodedAuth = new String(bytes,StandardCharsets.UTF_8); + String[] authen = decodedAuth.split(":"); + + if (authen.length > 1) { + User user = userSvc.getUserByLoginId(authen[0]); + if (user == null) { + response.sendError(HttpStatus.SC_UNAUTHORIZED, "Un-authorized to perform this operation"); + return false; + } +/* ResponseEntity<String> getResponse = + userSrvc.checkUserExists(authen[0], authen[1]); + if (getResponse.getStatusCode().value() != 200) { + response.sendError(HttpStatus.SC_UNAUTHORIZED, "Un-authorized to perform this operation"); + return false; + }*/ + } else { + return false; + } + } + } catch (Exception e) { + try { + response.sendError(HttpStatus.SC_UNAUTHORIZED, e.getMessage()); + } catch (IOException e1) { + return false; + } + return false; + } + return true; //Continue with request + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + //Ignore + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + //Ignore + } +} diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthorizationInterceptor.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthorizationInterceptor.java new file mode 100644 index 0000000..2f3362b --- /dev/null +++ b/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthorizationInterceptor.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.portalapp.interceptor; + +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class AuthorizationInterceptor implements HandlerInterceptor { + + protected final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Set<String> userRoleSet = new HashSet<String>(); + Set<String> userApps = new TreeSet<>(); + userRoleSet.add("Standard User"); + userRoleSet.add("ECOMPC_DCAE_WRITE"); + userApps.add("dcae"); + request.setAttribute("userRoles", userRoleSet); + request.setAttribute("userApps", userApps); + return true; //Continue with request + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + //Ignore + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + //Ignore + } +} diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/login/LoginStrategyImpl.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/login/LoginStrategyImpl.java index b628772..d7c9ab7 100644 --- a/ccsdk-app-os/src/main/java/org/onap/portalapp/login/LoginStrategyImpl.java +++ b/ccsdk-app-os/src/main/java/org/onap/portalapp/login/LoginStrategyImpl.java @@ -20,22 +20,129 @@ package org.onap.portalapp.login; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.onap.portalsdk.core.auth.LoginStrategy; +import org.onap.portalsdk.core.command.LoginBean; +import org.onap.portalsdk.core.domain.Role; +import org.onap.portalsdk.core.domain.RoleFunction; +import org.onap.portalsdk.core.domain.User; +import org.onap.portalsdk.core.domain.FusionObject.Parameters; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.menu.MenuProperties; import org.onap.portalsdk.core.onboarding.exception.PortalAPIException; import org.onap.portalsdk.core.onboarding.util.CipherUtil; import org.onap.portalsdk.core.onboarding.util.PortalApiConstants; import org.onap.portalsdk.core.onboarding.util.PortalApiProperties; +import org.onap.portalsdk.core.service.DataAccessService; +import org.onap.portalsdk.core.service.LoginService; +import org.onap.portalsdk.core.service.RoleService; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.portalsdk.core.web.support.AppUtils; +import org.onap.portalsdk.core.web.support.UserUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.ModelAndView; public class LoginStrategyImpl extends LoginStrategy { EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LoginStrategyImpl.class); + @Autowired + private LoginService loginService; + + @Autowired + private RoleService roleService; + + @Override + public ModelAndView doExternalLogin(HttpServletRequest request, HttpServletResponse response) throws IOException { + + invalidateExistingSession(request); + + LoginBean commandBean = new LoginBean(); + String loginId = request.getParameter("loginId"); + String password = request.getParameter("password"); + commandBean.setLoginId(loginId); + commandBean.setLoginPwd(password); + //commandBean.setUserid(loginId); + commandBean = loginService.findUser(commandBean, + (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap()); + List<RoleFunction> roleFunctionList = roleService.getRoleFunctions(loginId); + + if (commandBean.getUser() == null) { + String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage() + : "login.error.external.invalid - User name and/or password incorrect"; + Map<String, String> model = new HashMap<>(); + model.put("error", loginErrorMessage); + return new ModelAndView("login_external", "model", model); + } else { + // store the currently logged in user's information in the session + UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(), + commandBean.getBusinessDirectMenu(), + SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_BACKDOOR), roleFunctionList); + // set the user's max role level in session + final String adminRole = "System Administrator"; + final String standardRole = "Standard User"; + final String readRole = "Read Access"; + final String writeRole = "Write Access"; + + String maxRole = ""; + String authType = "READ"; + String accessLevel = "app"; + + Predicate<Role> adminRoleFilter = + p -> p.getName() != null && p.getName().equalsIgnoreCase(adminRole); + + Predicate<Role> writeRoleFilter = + p -> p.getName() != null && (p.getName().equalsIgnoreCase(writeRole) || p.getName().equalsIgnoreCase(standardRole)); + + Predicate<Role> readRoleFilter = + p -> p.getName() != null && (p.getName().equalsIgnoreCase(readRole) ); + + if (UserUtils.getUserSession(request) != null) { + @SuppressWarnings("unchecked") + Collection<org.onap.portalsdk.core.domain.Role> userRoles = + UserUtils.getRoles(request).values(); + if (userRoles.stream().anyMatch(adminRoleFilter) ) { + maxRole = "admin"; + } else if (userRoles.stream().anyMatch(writeRoleFilter) ) { + maxRole = "write"; + } else if (userRoles.stream().anyMatch(readRoleFilter) ) { + maxRole = "read"; + } + switch(maxRole) { + case "admin": + authType = "ADMIN"; + accessLevel = "ops"; + break; + case "write": + authType = "WRITE"; + accessLevel = "dev"; + break; + case "read": + authType = "READ"; + accessLevel = "dev"; + break; + default: + accessLevel = "app"; + } + } + AppUtils.getSession(request).setAttribute("role_level", accessLevel); + AppUtils.getSession(request).setAttribute("auth_role", authType); + initateSessionMgtHandler(request); + // user has been authenticated, now take them to the welcome page + return new ModelAndView("redirect:welcome"); + } + } + @Override public ModelAndView doLogin(HttpServletRequest request, HttpServletResponse response) throws Exception { diff --git a/ccsdk-app-os/src/main/resources/portal.properties b/ccsdk-app-os/src/main/resources/portal.properties index 88ef37c..1ab01ef 100644 --- a/ccsdk-app-os/src/main/resources/portal.properties +++ b/ccsdk-app-os/src/main/resources/portal.properties @@ -27,6 +27,9 @@ portal.api.prefix = /api max.idle.time = 5
user.attribute.name = user_attribute
+# CSP Global Log On for single sign on
+ecomp_redirect_url = https://webtest.csp.att.com/ecompportal/
+
# URL of the ECOMP Portal REST API
ecomp_rest_url = http://portal.api.simpledemo.openecomp.org/ecompportal/auxapi
diff --git a/ccsdk-app-os/src/main/resources/swagger.json b/ccsdk-app-os/src/main/resources/swagger.json index 9335e72..7a02e5a 100644 --- a/ccsdk-app-os/src/main/resources/swagger.json +++ b/ccsdk-app-os/src/main/resources/swagger.json @@ -2,14 +2,14 @@ "swagger": "2.0", "info": { "description": "API to manage deployment of microservices using blueprints.", - "version": "1.3.0", + "version": "1.4.0", "title": "DCAE Dashboard API", "contact": { "email": "rp5662@att.com" } }, "host": "dcae-dashboard:8080", - "basePath": "/ccsdk-app/nb-api", + "basePath": "/ccsdk-app/nb-api/v2", "tags": [ { "name": "Blueprints", @@ -22,10 +22,6 @@ { "name": "Tenants", "description": "Query Cloudify Tenants" - }, - { - "name": "Components", - "description": "Query on-boarded components" } ], "schemes": [ @@ -61,73 +57,12 @@ } } }, - "/components": { - "get": { - "tags": [ - "Components" - ], - "summary": "Lists all application components", - "description": "Query all components from database", - "operationId": "List Components", - "produces": [ - "application/json" - ], - "parameters": [], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Component" - } - } - }, - "400": { - "description": "Invalid status value" - } - } - }, - "post": { - "tags": [ - "Components" - ], - "summary": "add an application component", - "description": "Insert a component into database", - "operationId": "Add Component", - "consumes": [ - "application/json" - ], - "parameters": [ - { - "in": "body", - "name": "body", - "description": "New component input", - "required": true, - "schema": { - "$ref": "#/definitions/ComponentInput" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "object" - } - }, - "400": { - "description": "Invalid status value" - } - } - } - }, "/deployments": { "get": { "tags": [ "Deployments" ], - "summary": "Lists all Deployments", + "summary": "List all Deployments", "description": "Query all deployments or Service objects from Inventory", "operationId": "List Deployments", "produces": [ @@ -287,7 +222,7 @@ "tags": [ "Deployments" ], - "summary": "Gets a Deployment", + "summary": "Get a Deployment", "description": "Query a deployment or Service object from Inventory", "operationId": "Get Deployment", "produces": [ @@ -318,51 +253,6 @@ } } }, - "/deployments/{deploymentId}/update": { - "put": { - "tags": [ - "Deployments" - ], - "summary": "Update an existing deployment", - "description": "Dispatch a request to Deployment handler mS to use Cloudify deployment update operation ", - "operationId": "Update Deployment", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "name": "deploymentId", - "in": "path", - "description": "ID of deployment to update", - "required": true, - "type": "string" - }, - { - "in": "body", - "name": "body", - "description": "Inputs to initiate a deployment: blueprint ID from inventory, Cloudify tenant name, blueprint inputs", - "required": true, - "schema": { - "$ref": "#/definitions/DeploymentInput" - } - } - ], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Deployment not found" - }, - "405": { - "description": "Validation exception" - } - } - } - }, "/deployments/{deploymentId}/executions": { "get": { "tags": [ @@ -622,56 +512,6 @@ } } } - }, - "/blueprints/findByName": { - "get": { - "tags": [ - "Blueprints" - ], - "summary": "Find a blueprint by a name pattern", - "description": "Fetch the blueprint objects from inventory whose names match a string pattern", - "operationId": "Get Blueprint", - "produces": [ - "application/json" - ], - "parameters": [ - { - "name": "name", - "in": "query", - "description": "name pattern to filter by", - "required": true, - "type": "string" - }, - { - "name": "_include", - "in": "query", - "description": "blueprint object properties need to be considered for filter", - "required": false, - "type": "array", - "items": { - "type": "string", - "enum": [ - "typeName", - "typeId", - "typeVersion" - ], - "default": "typeName" - }, - "collectionFormat": "multi" - } - ], - "responses": { - "200": { - "description": "List of `DCAEServiceType` objects", - "schema": { - "$ref": "#/definitions/InlineResponse200" - } - }, - "400": { - "description": "Invalid tag value" - } - } - } } }, "responses": { @@ -694,22 +534,6 @@ } } }, - "Component": { - "type": "object", - "properties": { - "compId": { - "type": "integer" - }, - "cname": { - "type": "string", - "description": "component namespace name" - }, - "dname": { - "type": "string", - "description": "component display name" - } - } - }, "ComponentInput": { "type": "object", "properties": { @@ -1218,4 +1042,4 @@ "description": "Find out more about Swagger", "url": "http://swagger.io" } -} +}
\ No newline at end of file diff --git a/ccsdk-app-os/src/main/webapp/WEB-INF/conf/dashboard.properties b/ccsdk-app-os/src/main/webapp/WEB-INF/conf/dashboard.properties index 9e221cd..a43f85c 100644 --- a/ccsdk-app-os/src/main/webapp/WEB-INF/conf/dashboard.properties +++ b/ccsdk-app-os/src/main/webapp/WEB-INF/conf/dashboard.properties @@ -21,24 +21,25 @@ # Properties for the ONAP Controller Dashboard webapp -# Set to true to use local copies of controller data -controller.mock.data = false +# dashboard.properties -# for ONAP or other type -controller.type = os +# Properties for the Dashboard webapp +# YAML would represent this more elegantly, but Spring likes properties. +# Controllers - a key for each set of properties "key.propKey" below. controller.env = dev -# YAML would represent this more elegantly, but Spring likes properties. -controller.key.list = dev +controller.site.list = primary -dev.name = Local -dev.url = https://dashboard.onap.svc.cluster.local/api/v3.1 -dev.inventory.url = https://inventory.onap.svc.cluster.local:8443/ -dev.dhandler.url = https://dplh.onap.svc.cluster.local:8443/ -dev.consul.url = https://cnsl.onap.svc.cluster.local:9500/ +site.primary.name = mtn23a +site.primary.cloudify.url = https://eom-orcl-d14.ecomp.idns.cip.att.com/api/v3.1 +site.primary.consul.url = https://eom-cnsl-d14.ecomp.idns.cip.att.com:9500/ +site.primary.inventory.url = https://eom-invt-d14.ecomp.idns.cip.att.com:30123 +site.primary.dhandler.url = https://eom-dplh-d14.ecomp.idns.cip.att.com:30125/ +site.primary.dbcl.url = https://ecompc-dbclgui-dev-s5.ecomp.idns.cip.att.com:30162/dmaap-bc-app/doLogin +site.primary.feed_m.url = https://feedM.com +site.primary.cloudify.username = admin +site.primary.cloudify.password = Cloudify_local +site.primary.cloudify.is_encrypted = false -dev.username = admin -dev.password = admin -dev.is_encrypted = false diff --git a/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp b/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp index b0b63dd..f54662f 100644 --- a/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp +++ b/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp @@ -24,6 +24,9 @@ final String appDisplayName = SystemProperties.containsProperty(SystemProperties.APP_DISPLAY_NAME)
? SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME)
: SystemProperties.APP_DISPLAY_NAME;
+ String signUpPage = "signup.htm";
+ String signupUrl = (request.isSecure() ? "https://" : "http://") + request.getServerName() + ":"
+ + request.getServerPort() + request.getContextPath() + "/" + signUpPage;
%>
<html>
@@ -73,6 +76,30 @@ margin-left: auto;
margin-right: auto;
}
+ .formIn {
+ width: 200px;
+ height:25px;
+ border-radius: 4px;
+ font-size:18px;
+ padding-left:5px;
+ background-color: #f1ecec;
+ }
+ #regLink {
+ background: #0081a4;
+ border-radius: 3px;
+ padding: 4px;
+ font-size: large;
+ font-weight: bold;
+ text-decoration: none;
+ color: black;
+ }
+ #formDiv {
+ background-color: #0081a4b0;
+ width: 300px;
+ margin-left: auto;
+ margin-right: auto;
+ padding-bottom: 10px;
+ }
</style>
</head>
<body>
@@ -81,19 +108,20 @@ <h2>
<%=appDisplayName%>
</h2>
- <br />
- <form action="login_external" method="POST">
- <label for="loginId">Login ID:</label>
- <input id="loginId" name="loginId" type="text" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;" maxlength="30">
- <br/>
- <br/>
- <label for="password">Password:</label>
- <input id="password" name="password" type="password" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"
- maxlength="30" >
- <br />
- <br />
- <input id="loginBtn" type="submit" alt="Login" value="Login">
- </form>
+ <div id="formDiv">
+ <form action="login_external" method="POST">
+ <h3> Login </h3>
+ <input class="formIn" id="loginId" name="loginId" type="text" maxlength="30" placeholder="User ID">
+ <br>
+ <br>
+ <input class="formIn" id="password" name="password" type="password" maxlength="30" placeholder="Password">
+ <br>
+ <br>
+ <input id="loginBtn" type="submit" alt="Login" value="LOG IN" style="width: 200px; font-weight: bolder;">
+ </form>
+ <br>
+ <p>Not registered yet? <a id="regLink" href="<%=signupUrl%>">Sign up</a></p>
+ </div>
</div>
<br />
<br />
diff --git a/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/signup.jsp b/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/signup.jsp new file mode 100644 index 0000000..421f72a --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/signup.jsp @@ -0,0 +1,128 @@ +<%@ page import="org.onap.portalsdk.core.util.SystemProperties"%> +<!DOCTYPE html> +<% + // Name is defined by app; do not throw if missing + final String appDisplayName = SystemProperties.containsProperty(SystemProperties.APP_DISPLAY_NAME) + ? SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME) + : SystemProperties.APP_DISPLAY_NAME; + String loginPage = "login_external.htm"; + String loginUrl = (request.isSecure() ? "https://" : "http://") + request.getServerName() + ":" + + request.getServerPort() + request.getContextPath() + "/" + loginPage; +%> +<html> +<head> +<meta charset="ISO-8859-1"> +<title>Sign up / Register</title> +<style> + html { + font-family: Verdana, Arial, Helvetica, sans-serif; + } + body { + padding-top: 15px; + } + .logo { + position: fixed; + left: 15px; + top: 15px; + z-index: -1; + } + .loginError { + font-size: 18px; + color: red; + text-align: center; + } + .login { + font-size: 16px; + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; + width: 100%; + } + .login input[type=submit] { + font-size: 16px; + } + .terms { + font-size: 10px; + text-align: center; + margin-left: auto; + margin-right: auto; + } + .terms a { + font-size: 10px; + text-align: center; + margin-left: auto; + margin-right: auto; + } + .formIn { + width: 200px; + height:25px; + border-radius: 4px; + font-size:18px; + padding-left:5px; + background-color: #f1ecec; + } + #regLink { + background: #0081a4; + border-radius: 3px; + padding: 4px; + font-size: large; + font-weight: bold; + text-decoration: none; + color: black; + } + #formDiv { + background-color: #0081a4b0; + width: 300px; + margin-left: auto; + margin-right: auto; + padding-bottom: 10px; + } + </style> + +</head> +<body> + <div class="login"> + <img src="app/ccsdk/images/onap_logo_2257x496.png" style="height: 150px;" /> + <h2> + <%=appDisplayName%> + </h2> + <div id="formDiv"> + <form action="signup" method="POST"> + <h3>Sign Up</h3> + <input id="first" class="formIn" name="first" type="text" maxlength="30" placeholder="First Name"> + <br/> + <br/> + <input id="last" class="formIn" name="last" type="text" maxlength="30" placeholder="Last Name"> + <br/> + <br/> + <input id="loginId" class="formIn" name="loginId" type="text" maxlength="30" placeholder="User ID"> + <br/> + <br/> + <input id="password" class="formIn" name="password" type="password" maxlength="30" placeholder="Password"> + <br /> + <br /> + <input id="email" class="formIn" name="email" type="text" maxlength="30" placeholder="Email"> + <br /> + <br /> + <input id="loginBtn" type="submit" alt="Login" value="SIGN UP" style="width: 200px; font-weight: bolder;"> + </form> + <br> + <p>Already registered? <a id="regLink" href="<%=loginUrl%>"> Login</a></p> + </div> + </div> + <br /> + <br /> + <div class="loginError">${model.error}</div> + <br /> + <br /> + <br /> + <div id="footer"> + <div class="terms"> + <p class="copyright-text"> + © 2020 ONAP. The Linux Foundation. + </p> + </div> + </div> +</body> +</html>
\ No newline at end of file diff --git a/ccsdk-app-os/src/main/webapp/WEB-INF/oom-app-definitions.xml b/ccsdk-app-os/src/main/webapp/WEB-INF/oom-app-definitions.xml new file mode 100644 index 0000000..5fcc6c8 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/WEB-INF/oom-app-definitions.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + =============LICENSE_START========================================================= + + ================================================================================= + 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========================================================= + + ECOMP is a trademark and service mark of AT&T Intellectual Property. + --> + +<!DOCTYPE tiles-definitions PUBLIC + "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" + "http://tiles.apache.org/dtds/tiles-config_3_0.dtd"> +<tiles-definitions> + + <!-- Main page for the single-page app --> + <definition name="ecd_home_tdkey" template="/app/ccsdk/home/oom_spa.html"/> + <definition name="welcome" + template="/app/fusion/scripts/DS2-view-models/welcome.html" /> +</tiles-definitions> diff --git a/ccsdk-app-overlay/src/main/webapp/WEB-INF/oom-app.hbm.xml b/ccsdk-app-os/src/main/webapp/WEB-INF/oom-app.hbm.xml index b302346..b302346 100644 --- a/ccsdk-app-overlay/src/main/webapp/WEB-INF/oom-app.hbm.xml +++ b/ccsdk-app-os/src/main/webapp/WEB-INF/oom-app.hbm.xml diff --git a/ccsdk-app-os/src/main/webapp/api-specs.html b/ccsdk-app-os/src/main/webapp/api-specs.html index e5c5dfc..9a7d498 100644 --- a/ccsdk-app-os/src/main/webapp/api-specs.html +++ b/ccsdk-app-os/src/main/webapp/api-specs.html @@ -1500,7 +1500,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc <ul class="toc-list-h1"> <li> - <a href="#dcae-dashboard-api" class="toc-h1 toc-link" data-title="DCAE Dashboard API v1.0.0">DCAE Dashboard API v1.0.0</a> + <a href="#dcae-dashboard-api" class="toc-h1 toc-link" data-title="DCAE Dashboard API v1.4.0">DCAE Dashboard API v1.4.0</a> </li> @@ -1510,27 +1510,22 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc <ul class="toc-list-h2"> <li> - <a href="#find-all-blueprint-templates" class="toc-h2 toc-link" data-title="">Find all blueprint templates</a> + <a href="#list-blueprints" class="toc-h2 toc-link" data-title="">List Blueprints</a> </li> <li> - <a href="#create-upload-a-new-blueprint-template" class="toc-h2 toc-link" data-title="">Create/Upload a new blueprint template</a> + <a href="#create-blueprint" class="toc-h2 toc-link" data-title="">Create Blueprint</a> </li> <li> - <a href="#delete-a-blueprint-template" class="toc-h2 toc-link" data-title="">Delete a blueprint template</a> + <a href="#delete-blueprint" class="toc-h2 toc-link" data-title="">Delete Blueprint</a> </li> <li> - <a href="#get-services-mapped-to-a-blueprint-template" class="toc-h2 toc-link" data-title="">Get Services mapped to a blueprint template</a> - - </li> - - <li> - <a href="#find-a-blueprint-by-a-name-pattern" class="toc-h2 toc-link" data-title="">Find a blueprint by a name pattern</a> + <a href="#get-deployments-for-a-blueprint" class="toc-h2 toc-link" data-title="">Get Deployments for a blueprint</a> </li> @@ -1544,47 +1539,42 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc <ul class="toc-list-h2"> <li> - <a href="#lists-all-deployments" class="toc-h2 toc-link" data-title="">Lists all Deployments</a> - - </li> - - <li> - <a href="#initiate-a-deployment--install--operation-for-an-application-or-service" class="toc-h2 toc-link" data-title="">Initiate a deployment (install) operation for an application or service</a> + <a href="#list-deployments" class="toc-h2 toc-link" data-title="">List Deployments</a> </li> <li> - <a href="#initiate-an-uninstall-operation-for-an-application-or-service" class="toc-h2 toc-link" data-title="">Initiate an uninstall operation for an application or service</a> + <a href="#create-deployment" class="toc-h2 toc-link" data-title="">Create Deployment</a> </li> <li> - <a href="#upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin" class="toc-h2 toc-link" data-title="">Upgrade or Rollback an existing deployment using Cloudify Helm plugin</a> + <a href="#delete-deployment" class="toc-h2 toc-link" data-title="">Delete Deployment</a> </li> <li> - <a href="#gets-a-deployment" class="toc-h2 toc-link" data-title="">Gets a Deployment</a> + <a href="#upgrade_rollback-deployment" class="toc-h2 toc-link" data-title="">Upgrade_Rollback Deployment</a> </li> <li> - <a href="#update-an-existing-deployment" class="toc-h2 toc-link" data-title="">Update an existing deployment</a> + <a href="#get-deployment" class="toc-h2 toc-link" data-title="">Get Deployment</a> </li> <li> - <a href="#deployment-execution-status" class="toc-h2 toc-link" data-title="">Deployment execution status</a> + <a href="#deployment-status" class="toc-h2 toc-link" data-title="">Deployment Status</a> </li> <li> - <a href="#deployment-health-status" class="toc-h2 toc-link" data-title="">Deployment health status</a> + <a href="#deployment-health" class="toc-h2 toc-link" data-title="">Deployment health</a> </li> <li> - <a href="#deployment-inputs" class="toc-h2 toc-link" data-title="">Deployment inputs</a> + <a href="#deployment-inputs" class="toc-h2 toc-link" data-title="">Deployment Inputs</a> </li> @@ -1598,26 +1588,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc <ul class="toc-list-h2"> <li> - <a href="#lists-all-cloudify-tenants" class="toc-h2 toc-link" data-title="">Lists all Cloudify Tenants</a> - - </li> - - </ul> - - </li> - - <li> - <a href="#dcae-dashboard-api-components" class="toc-h1 toc-link" data-title="Components">Components</a> - - <ul class="toc-list-h2"> - - <li> - <a href="#lists-all-application-components" class="toc-h2 toc-link" data-title="">Lists all application components</a> - - </li> - - <li> - <a href="#add-an-application-component" class="toc-h2 toc-link" data-title="">add an application component</a> + <a href="#list-tenants" class="toc-h2 toc-link" data-title="">List Tenants</a> </li> @@ -1636,11 +1607,6 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc </li> <li> - <a href="#tocscomponent" class="toc-h2 toc-link" data-title="">Component</a> - - </li> - - <li> <a href="#tocscomponentinput" class="toc-h2 toc-link" data-title="">ComponentInput</a> </li> @@ -1747,7 +1713,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc <div class="page-wrapper"> <div class="dark-box"></div> <div class="content"> - <h1 id="dcae-dashboard-api">DCAE Dashboard API v1.0.0</h1> + <h1 id="dcae-dashboard-api">DCAE Dashboard API v1.4.0</h1> <blockquote> <p>Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.</p> </blockquote> @@ -1755,16 +1721,16 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc <p>Base URLs:</p> <ul> <li> -<p><a href="https://dcae-dashboard:8080/ccsdk-app/nb-api">https://dcae-dashboard:8080/ccsdk-app/nb-api</a></p> +<p><a href="https://dcae-dashboard:8080/ccsdk-app/nb-api/v2">https://dcae-dashboard:8080/ccsdk-app/nb-api/v2</a></p> </li> <li> -<p><a href="http://dcae-dashboard:8080/ccsdk-app/nb-api">http://dcae-dashboard:8080/ccsdk-app/nb-api</a></p> +<p><a href="http://dcae-dashboard:8080/ccsdk-app/nb-api/v2">http://dcae-dashboard:8080/ccsdk-app/nb-api/v2</a></p> </li> </ul> <p>Email: <a href="mailto:rp5662@att.com">Support</a></p> <h1 id="dcae-dashboard-api-blueprints">Blueprints</h1> <p>Query blueprint information</p> -<h2 id="find-all-blueprint-templates">Find all blueprint templates</h2> +<h2 id="list-blueprints">List Blueprints</h2> <p><a id="opIdList Blueprints"></a></p> <blockquote> <p>Code samples</p> @@ -1774,7 +1740,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints'</span>, params={ <span class="hljs-string">'pageNum'</span>: <span class="hljs-string">'string'</span>, <span class="hljs-string">'viewPerPage'</span>: <span class="hljs-string">'string'</span> }, headers = headers) @@ -1782,13 +1748,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints?pageNum=string&viewPerPage=string \ +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints?pageNum=string&viewPerPage=string \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>GET /blueprints</code></p> +<p><em>Find all blueprint templates</em></p> <p>Fetch the blueprints data from inventory</p> -<h3 id="find-all-blueprint-templates-parameters">Parameters</h3> +<h3 id="list-blueprints-parameters">Parameters</h3> <table> <thead> <tr> @@ -1917,13 +1884,13 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints?pageNum=stri }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span> + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span> } ] } </code></pre> -<h3 id="find-all-blueprint-templates-responses">Responses</h3> +<h3 id="list-blueprints-responses">Responses</h3> <table> <thead> <tr> @@ -1951,7 +1918,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints?pageNum=stri <aside class="success"> This operation does not require authentication </aside> -<h2 id="create-upload-a-new-blueprint-template">Create/Upload a new blueprint template</h2> +<h2 id="create-blueprint">Create Blueprint</h2> <p><a id="opIdCreate Blueprint"></a></p> <blockquote> <p>Code samples</p> @@ -1962,7 +1929,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints'</span>, params={ +r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints'</span>, params={ }, headers = headers) @@ -1970,12 +1937,13 @@ r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-a </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \ +curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints \ -H <span class="hljs-string">'Content-Type: application/json'</span> \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>POST /blueprints</code></p> +<p><em>Create/Upload a new blueprint template</em></p> <p>Upload a new blueprint template into inventory</p> <blockquote> <p>Body parameter</p> @@ -1989,7 +1957,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \ <span class="hljs-attr">"component"</span>: <span class="hljs-string">"string"</span> } </code></pre> -<h3 id="create-upload-a-new-blueprint-template-parameters">Parameters</h3> +<h3 id="create-blueprint-parameters">Parameters</h3> <table> <thead> <tr> @@ -2081,13 +2049,13 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \ }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span> + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span> } ] } </code></pre> -<h3 id="create-upload-a-new-blueprint-template-responses">Responses</h3> +<h3 id="create-blueprint-responses">Responses</h3> <table> <thead> <tr> @@ -2115,14 +2083,14 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \ <aside class="success"> This operation does not require authentication </aside> -<h2 id="delete-a-blueprint-template">Delete a blueprint template</h2> +<h2 id="delete-blueprint">Delete Blueprint</h2> <p><a id="opIdDelete Blueprint"></a></p> <blockquote> <p>Code samples</p> </blockquote> <pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests -r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}'</span>, params={ +r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId}'</span>, params={ ) @@ -2130,12 +2098,13 @@ r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId} +curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId} </code></pre> <p><code>DELETE /blueprints/{typeId}</code></p> +<p><em>Delete a blueprint template</em></p> <p>Delete a blueprint template from inventory</p> -<h3 id="delete-a-blueprint-template-parameters">Parameters</h3> +<h3 id="delete-blueprint-parameters">Parameters</h3> <table> <thead> <tr> @@ -2156,7 +2125,7 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId} </tr> </tbody> </table> -<h3 id="delete-a-blueprint-template-responses">Responses</h3> +<h3 id="delete-blueprint-responses">Responses</h3> <table> <thead> <tr> @@ -2178,14 +2147,14 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId} <aside class="success"> This operation does not require authentication </aside> -<h2 id="get-services-mapped-to-a-blueprint-template">Get Services mapped to a blueprint template</h2> +<h2 id="get-deployments-for-a-blueprint">Get Deployments for a blueprint</h2> <p><a id="opIdGet Deployments for a blueprint"></a></p> <blockquote> <p>Code samples</p> </blockquote> <pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/services'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId}/services'</span>, params={ ) @@ -2193,12 +2162,13 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/services +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId}/services </code></pre> <p><code>GET /blueprints/{typeId}/services</code></p> +<p><em>Get Services mapped to a blueprint template</em></p> <p>Get Deployment References existing for a blueprint</p> -<h3 id="get-services-mapped-to-a-blueprint-template-parameters">Parameters</h3> +<h3 id="get-deployments-for-a-blueprint-parameters">Parameters</h3> <table> <thead> <tr> @@ -2219,7 +2189,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/ser </tr> </tbody> </table> -<h3 id="get-services-mapped-to-a-blueprint-template-responses">Responses</h3> +<h3 id="get-deployments-for-a-blueprint-responses">Responses</h3> <table> <thead> <tr> @@ -2241,189 +2211,9 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/ser <aside class="success"> This operation does not require authentication </aside> -<h2 id="find-a-blueprint-by-a-name-pattern">Find a blueprint by a name pattern</h2> -<p><a id="opIdGet Blueprint"></a></p> -<blockquote> -<p>Code samples</p> -</blockquote> -<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests -headers = { - <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> -} - -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/findByName'</span>, params={ - <span class="hljs-string">'name'</span>: <span class="hljs-string">'string'</span> -}, headers = headers) - -<span class="hljs-keyword">print</span> r.json() - -</code></pre> -<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/findByName?name=string \ - -H <span class="hljs-string">'Accept: application/json'</span> - -</code></pre> -<p><code>GET /blueprints/findByName</code></p> -<p>Fetch the blueprint objects from inventory whose names match a string pattern</p> -<h3 id="find-a-blueprint-by-a-name-pattern-parameters">Parameters</h3> -<table> -<thead> -<tr> -<th>Name</th> -<th>In</th> -<th>Type</th> -<th>Required</th> -<th>Description</th> -</tr> -</thead> -<tbody> -<tr> -<td>name</td> -<td>query</td> -<td>string</td> -<td>true</td> -<td>name pattern to filter by</td> -</tr> -<tr> -<td>_include</td> -<td>query</td> -<td>array[string]</td> -<td>false</td> -<td>blueprint object properties need to be considered for filter</td> -</tr> -</tbody> -</table> -<h4 id="enumerated-values">Enumerated Values</h4> -<table> -<thead> -<tr> -<th>Parameter</th> -<th>Value</th> -</tr> -</thead> -<tbody> -<tr> -<td>_include</td> -<td>typeName</td> -</tr> -<tr> -<td>_include</td> -<td>typeId</td> -</tr> -<tr> -<td>_include</td> -<td>typeVersion</td> -</tr> -</tbody> -</table> -<blockquote> -<p>Example responses</p> -</blockquote> -<blockquote> -<p>200 Response</p> -</blockquote> -<pre class="highlight tab tab-json"><code>{ - <span class="hljs-attr">"links"</span>: { - <span class="hljs-attr">"previousLink"</span>: { - <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"uri"</span>: <span class="hljs-string">"http://example.com"</span>, - <span class="hljs-attr">"uriBuilder"</span>: {}, - <span class="hljs-attr">"rels"</span>: [ - <span class="hljs-string">"string"</span> - ], - <span class="hljs-attr">"params"</span>: { - <span class="hljs-attr">"property1"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"property2"</span>: <span class="hljs-string">"string"</span> - }, - <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> - }, - <span class="hljs-attr">"nextLink"</span>: { - <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"uri"</span>: <span class="hljs-string">"http://example.com"</span>, - <span class="hljs-attr">"uriBuilder"</span>: {}, - <span class="hljs-attr">"rels"</span>: [ - <span class="hljs-string">"string"</span> - ], - <span class="hljs-attr">"params"</span>: { - <span class="hljs-attr">"property1"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"property2"</span>: <span class="hljs-string">"string"</span> - }, - <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> - } - }, - <span class="hljs-attr">"totalCount"</span>: <span class="hljs-number">0</span>, - <span class="hljs-attr">"items"</span>: [ - { - <span class="hljs-attr">"owner"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"typeName"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"typeVersion"</span>: <span class="hljs-number">0</span>, - <span class="hljs-attr">"blueprintTemplate"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"serviceIds"</span>: [ - <span class="hljs-string">"string"</span> - ], - <span class="hljs-attr">"vnfTypes"</span>: [ - <span class="hljs-string">"string"</span> - ], - <span class="hljs-attr">"serviceLocations"</span>: [ - <span class="hljs-string">"string"</span> - ], - <span class="hljs-attr">"asdcServiceId"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"asdcResourceId"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"asdcServiceURL"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"typeId"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"selfLink"</span>: { - <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"uri"</span>: <span class="hljs-string">"http://example.com"</span>, - <span class="hljs-attr">"uriBuilder"</span>: {}, - <span class="hljs-attr">"rels"</span>: [ - <span class="hljs-string">"string"</span> - ], - <span class="hljs-attr">"params"</span>: { - <span class="hljs-attr">"property1"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"property2"</span>: <span class="hljs-string">"string"</span> - }, - <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> - }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span> - } - ] -} -</code></pre> -<h3 id="find-a-blueprint-by-a-name-pattern-responses">Responses</h3> -<table> -<thead> -<tr> -<th>Status</th> -<th>Meaning</th> -<th>Description</th> -<th>Schema</th> -</tr> -</thead> -<tbody> -<tr> -<td>200</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td> -<td>List of <code>DCAEServiceType</code> objects</td> -<td><a href="#schemainlineresponse200">InlineResponse200</a></td> -</tr> -<tr> -<td>400</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td> -<td>Invalid tag value</td> -<td>None</td> -</tr> -</tbody> -</table> -<aside class="success"> -This operation does not require authentication -</aside> <h1 id="dcae-dashboard-api-deployments">Deployments</h1> <p>Manage deployments</p> -<h2 id="lists-all-deployments">Lists all Deployments</h2> +<h2 id="list-deployments">List Deployments</h2> <p><a id="opIdList Deployments"></a></p> <blockquote> <p>Code samples</p> @@ -2433,7 +2223,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments'</span>, params={ <span class="hljs-string">'pageNum'</span>: <span class="hljs-string">'string'</span>, <span class="hljs-string">'viewPerPage'</span>: <span class="hljs-string">'string'</span> }, headers = headers) @@ -2441,13 +2231,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=string&viewPerPage=string \ +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments?pageNum=string&viewPerPage=string \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>GET /deployments</code></p> +<p><em>List all Deployments</em></p> <p>Query all deployments or Service objects from Inventory</p> -<h3 id="lists-all-deployments-parameters">Parameters</h3> +<h3 id="list-deployments-parameters">Parameters</h3> <table> <thead> <tr> @@ -2498,8 +2289,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"typeLink"</span>: { <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>, @@ -2549,8 +2340,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>, <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>, @@ -2562,7 +2353,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str } ] </code></pre> -<h3 id="lists-all-deployments-responses">Responses</h3> +<h3 id="list-deployments-responses">Responses</h3> <table> <thead> <tr> @@ -2587,7 +2378,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str </tr> </tbody> </table> -<h3 id="lists-all-deployments-responseschema">Response Schema</h3> +<h3 id="list-deployments-responseschema">Response Schema</h3> <p>Status Code <strong>200</strong></p> <table> <thead> @@ -2834,7 +2625,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str <aside class="success"> This operation does not require authentication </aside> -<h2 id="initiate-a-deployment--install--operation-for-an-application-or-service">Initiate a deployment (install) operation for an application or service</h2> +<h2 id="create-deployment">Create Deployment</h2> <p><a id="opIdCreate Deployment"></a></p> <blockquote> <p>Code samples</p> @@ -2845,7 +2636,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments'</span>, params={ +r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments'</span>, params={ }, headers = headers) @@ -2853,12 +2644,13 @@ r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-a </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \ +curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments \ -H <span class="hljs-string">'Content-Type: application/json'</span> \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>POST /deployments</code></p> +<p><em>Initiate a deployment (install) operation for an application or service</em></p> <p>Controller sends the blueprint and required inputs to Deployment Handler microservice to initiate the deployment process</p> <blockquote> <p>Body parameter</p> @@ -2873,7 +2665,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \ <span class="hljs-attr">"inputs"</span>: {} } </code></pre> -<h3 id="initiate-a-deployment--install--operation-for-an-application-or-service-parameters">Parameters</h3> +<h3 id="create-deployment-parameters">Parameters</h3> <table> <thead> <tr> @@ -2909,7 +2701,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \ } } </code></pre> -<h3 id="initiate-a-deployment--install--operation-for-an-application-or-service-responses">Responses</h3> +<h3 id="create-deployment-responses">Responses</h3> <table> <thead> <tr> @@ -2937,7 +2729,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \ <aside class="success"> This operation does not require authentication </aside> -<h2 id="initiate-an-uninstall-operation-for-an-application-or-service">Initiate an uninstall operation for an application or service</h2> +<h2 id="delete-deployment">Delete Deployment</h2> <p><a id="opIdDelete Deployment"></a></p> <blockquote> <p>Code samples</p> @@ -2947,7 +2739,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}'</span>, params={ +r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}'</span>, params={ <span class="hljs-string">'tenant'</span>: <span class="hljs-string">'string'</span> }, headers = headers) @@ -2955,13 +2747,14 @@ r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}?tenant=string \ +curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}?tenant=string \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>DELETE /deployments/{deploymentId}</code></p> +<p><em>Initiate an uninstall operation for an application or service</em></p> <p>Controller sends the deployment reference to Deployment Handler microservice to initiate the uninstall process</p> -<h3 id="initiate-an-uninstall-operation-for-an-application-or-service-parameters">Parameters</h3> +<h3 id="delete-deployment-parameters">Parameters</h3> <table> <thead> <tr> @@ -2997,7 +2790,7 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploym </blockquote> <pre class="highlight tab tab-json"><code><span class="hljs-string">"string"</span> </code></pre> -<h3 id="initiate-an-uninstall-operation-for-an-application-or-service-responses">Responses</h3> +<h3 id="delete-deployment-responses">Responses</h3> <table> <thead> <tr> @@ -3025,7 +2818,7 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploym <aside class="success"> This operation does not require authentication </aside> -<h2 id="upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin">Upgrade or Rollback an existing deployment using Cloudify Helm plugin</h2> +<h2 id="upgrade_rollback-deployment">Upgrade_Rollback Deployment</h2> <p><a id="opIdUpgrade/Rollback Deployment"></a></p> <blockquote> <p>Code samples</p> @@ -3035,7 +2828,7 @@ headers = { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}'</span>, params={ +r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}'</span>, params={ }, headers = headers) @@ -3043,11 +2836,12 @@ r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId} \ +curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId} \ -H <span class="hljs-string">'Content-Type: application/json'</span> </code></pre> <p><code>PUT /deployments/{deploymentId}</code></p> +<p><em>Upgrade or Rollback an existing deployment using Cloudify Helm plugin</em></p> <p>Upgrade or Rollback an existing deployment using Cloudify Helm plugin</p> <blockquote> <p>Body parameter</p> @@ -3061,7 +2855,7 @@ curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment <span class="hljs-attr">"workflow"</span>: <span class="hljs-string">"string"</span> } </code></pre> -<h3 id="upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin-parameters">Parameters</h3> +<h3 id="upgrade_rollback-deployment-parameters">Parameters</h3> <table> <thead> <tr> @@ -3089,7 +2883,7 @@ curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment </tr> </tbody> </table> -<h3 id="upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin-responses">Responses</h3> +<h3 id="upgrade_rollback-deployment-responses">Responses</h3> <table> <thead> <tr> @@ -3123,7 +2917,7 @@ curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment <aside class="success"> This operation does not require authentication </aside> -<h2 id="gets-a-deployment">Gets a Deployment</h2> +<h2 id="get-deployment">Get Deployment</h2> <p><a id="opIdGet Deployment"></a></p> <blockquote> <p>Code samples</p> @@ -3133,7 +2927,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}'</span>, params={ }, headers = headers) @@ -3141,13 +2935,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId} \ +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId} \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>GET /deployments/{deploymentId}</code></p> +<p><em>Get a Deployment</em></p> <p>Query a deployment or Service object from Inventory</p> -<h3 id="gets-a-deployment-parameters">Parameters</h3> +<h3 id="get-deployment-parameters">Parameters</h3> <table> <thead> <tr> @@ -3191,8 +2986,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"typeLink"</span>: { <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>, @@ -3242,8 +3037,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>, <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>, @@ -3255,7 +3050,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment } ] </code></pre> -<h3 id="gets-a-deployment-responses">Responses</h3> +<h3 id="get-deployment-responses">Responses</h3> <table> <thead> <tr> @@ -3280,7 +3075,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment </tr> </tbody> </table> -<h3 id="gets-a-deployment-responseschema">Response Schema</h3> +<h3 id="get-deployment-responseschema">Response Schema</h3> <p>Status Code <strong>200</strong></p> <table> <thead> @@ -3527,106 +3322,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment <aside class="success"> This operation does not require authentication </aside> -<h2 id="update-an-existing-deployment">Update an existing deployment</h2> -<p><a id="opIdUpdate Deployment"></a></p> -<blockquote> -<p>Code samples</p> -</blockquote> -<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests -headers = { - <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> -} - -r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/update'</span>, params={ - -}, headers = headers) - -<span class="hljs-keyword">print</span> r.json() - -</code></pre> -<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/update \ - -H <span class="hljs-string">'Content-Type: application/json'</span> - -</code></pre> -<p><code>PUT /deployments/{deploymentId}/update</code></p> -<p>Dispatch a request to Deployment handler mS to use Cloudify deployment update operation</p> -<blockquote> -<p>Body parameter</p> -</blockquote> -<pre class="highlight tab tab-json"><code>{ - <span class="hljs-attr">"component"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"tag"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"blueprintId"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"blueprintName"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"blueprintVersion"</span>: <span class="hljs-number">0</span>, - <span class="hljs-attr">"tenant"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"inputs"</span>: {} -} -</code></pre> -<h3 id="update-an-existing-deployment-parameters">Parameters</h3> -<table> -<thead> -<tr> -<th>Name</th> -<th>In</th> -<th>Type</th> -<th>Required</th> -<th>Description</th> -</tr> -</thead> -<tbody> -<tr> -<td>deploymentId</td> -<td>path</td> -<td>string</td> -<td>true</td> -<td>ID of deployment to update</td> -</tr> -<tr> -<td>body</td> -<td>body</td> -<td><a href="#schemadeploymentinput">DeploymentInput</a></td> -<td>true</td> -<td>Inputs to initiate a deployment: blueprint ID from inventory, Cloudify tenant name, blueprint inputs</td> -</tr> -</tbody> -</table> -<h3 id="update-an-existing-deployment-responses">Responses</h3> -<table> -<thead> -<tr> -<th>Status</th> -<th>Meaning</th> -<th>Description</th> -<th>Schema</th> -</tr> -</thead> -<tbody> -<tr> -<td>400</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td> -<td>Invalid ID supplied</td> -<td>None</td> -</tr> -<tr> -<td>404</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.4">Not Found</a></td> -<td>Deployment not found</td> -<td>None</td> -</tr> -<tr> -<td>405</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.5">Method Not Allowed</a></td> -<td>Validation exception</td> -<td>None</td> -</tr> -</tbody> -</table> -<aside class="success"> -This operation does not require authentication -</aside> -<h2 id="deployment-execution-status">Deployment execution status</h2> +<h2 id="deployment-status">Deployment Status</h2> <p><a id="opIdDeployment Status"></a></p> <blockquote> <p>Code samples</p> @@ -3636,7 +3332,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/executions'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/executions'</span>, params={ <span class="hljs-string">'tenant'</span>: <span class="hljs-string">'string'</span> }, headers = headers) @@ -3644,13 +3340,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/executions?tenant=string \ +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/executions?tenant=string \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>GET /deployments/{deploymentId}/executions</code></p> +<p><em>Deployment execution status</em></p> <p>Query deployment workflow execution status</p> -<h3 id="deployment-execution-status-parameters">Parameters</h3> +<h3 id="deployment-status-parameters">Parameters</h3> <table> <thead> <tr> @@ -3695,7 +3392,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment } ] </code></pre> -<h3 id="deployment-execution-status-responses">Responses</h3> +<h3 id="deployment-status-responses">Responses</h3> <table> <thead> <tr> @@ -3720,7 +3417,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment </tr> </tbody> </table> -<h3 id="deployment-execution-status-responseschema">Response Schema</h3> +<h3 id="deployment-status-responseschema">Response Schema</h3> <p>Status Code <strong>200</strong></p> <table> <thead> @@ -3787,7 +3484,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment <aside class="success"> This operation does not require authentication </aside> -<h2 id="deployment-health-status">Deployment health status</h2> +<h2 id="deployment-health">Deployment health</h2> <p><a id="opIdDeployment health"></a></p> <blockquote> <p>Code samples</p> @@ -3797,7 +3494,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/health'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/health'</span>, params={ }, headers = headers) @@ -3805,13 +3502,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/health \ +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/health \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>GET /deployments/{deploymentId}/health</code></p> +<p><em>Deployment health status</em></p> <p>Query consul for service health using deployment ID filter</p> -<h3 id="deployment-health-status-parameters">Parameters</h3> +<h3 id="deployment-health-parameters">Parameters</h3> <table> <thead> <tr> @@ -3847,7 +3545,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment <span class="hljs-attr">"serviceName"</span>: <span class="hljs-string">"string"</span> } </code></pre> -<h3 id="deployment-health-status-responses">Responses</h3> +<h3 id="deployment-health-responses">Responses</h3> <table> <thead> <tr> @@ -3869,7 +3567,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment <aside class="success"> This operation does not require authentication </aside> -<h2 id="deployment-inputs">Deployment inputs</h2> +<h2 id="deployment-inputs">Deployment Inputs</h2> <p><a id="opIdDeployment Inputs"></a></p> <blockquote> <p>Code samples</p> @@ -3879,7 +3577,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/inputs'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/inputs'</span>, params={ <span class="hljs-string">'tenant'</span>: <span class="hljs-string">'string'</span> }, headers = headers) @@ -3887,11 +3585,12 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/inputs?tenant=string \ +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/inputs?tenant=string \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>GET /deployments/{deploymentId}/inputs</code></p> +<p><em>Deployment inputs</em></p> <p>Get blueprint inputs used to create deployment</p> <h3 id="deployment-inputs-parameters">Parameters</h3> <table> @@ -3960,7 +3659,7 @@ This operation does not require authentication </aside> <h1 id="dcae-dashboard-api-tenants">Tenants</h1> <p>Query Cloudify Tenants</p> -<h2 id="lists-all-cloudify-tenants">Lists all Cloudify Tenants</h2> +<h2 id="list-tenants">List Tenants</h2> <p><a id="opIdList Tenants"></a></p> <blockquote> <p>Code samples</p> @@ -3970,7 +3669,7 @@ headers = { <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> } -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants'</span>, params={ +r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/tenants'</span>, params={ }, headers = headers) @@ -3978,11 +3677,12 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap </code></pre> <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \ +curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/tenants \ -H <span class="hljs-string">'Accept: application/json'</span> </code></pre> <p><code>GET /tenants</code></p> +<p><em>Lists all Cloudify Tenants</em></p> <p>Query all Tenant names from Cloudify</p> <blockquote> <p>Example responses</p> @@ -3996,7 +3696,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \ } ] </code></pre> -<h3 id="lists-all-cloudify-tenants-responses">Responses</h3> +<h3 id="list-tenants-responses">Responses</h3> <table> <thead> <tr> @@ -4021,7 +3721,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \ </tr> </tbody> </table> -<h3 id="lists-all-cloudify-tenants-responseschema">Response Schema</h3> +<h3 id="list-tenants-responseschema">Response Schema</h3> <p>Status Code <strong>200</strong></p> <table> <thead> @@ -4053,207 +3753,6 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \ <aside class="success"> This operation does not require authentication </aside> -<h1 id="dcae-dashboard-api-components">Components</h1> -<p>Query on-boarded components</p> -<h2 id="lists-all-application-components">Lists all application components</h2> -<p><a id="opIdList Components"></a></p> -<blockquote> -<p>Code samples</p> -</blockquote> -<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests -headers = { - <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span> -} - -r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/components'</span>, params={ - -}, headers = headers) - -<span class="hljs-keyword">print</span> r.json() - -</code></pre> -<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/components \ - -H <span class="hljs-string">'Accept: application/json'</span> - -</code></pre> -<p><code>GET /components</code></p> -<p>Query all components from database</p> -<blockquote> -<p>Example responses</p> -</blockquote> -<blockquote> -<p>200 Response</p> -</blockquote> -<pre class="highlight tab tab-json"><code>[ - { - <span class="hljs-attr">"compId"</span>: <span class="hljs-number">0</span>, - <span class="hljs-attr">"cname"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"dname"</span>: <span class="hljs-string">"string"</span> - } -] -</code></pre> -<h3 id="lists-all-application-components-responses">Responses</h3> -<table> -<thead> -<tr> -<th>Status</th> -<th>Meaning</th> -<th>Description</th> -<th>Schema</th> -</tr> -</thead> -<tbody> -<tr> -<td>200</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td> -<td>successful operation</td> -<td>Inline</td> -</tr> -<tr> -<td>400</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td> -<td>Invalid status value</td> -<td>None</td> -</tr> -</tbody> -</table> -<h3 id="lists-all-application-components-responseschema">Response Schema</h3> -<p>Status Code <strong>200</strong></p> -<table> -<thead> -<tr> -<th>Name</th> -<th>Type</th> -<th>Required</th> -<th>Restrictions</th> -<th>Description</th> -</tr> -</thead> -<tbody> -<tr> -<td><em>anonymous</em></td> -<td>[<a href="#schemacomponent">Component</a>]</td> -<td>false</td> -<td>none</td> -<td>none</td> -</tr> -<tr> -<td>» compId</td> -<td>integer</td> -<td>false</td> -<td>none</td> -<td>none</td> -</tr> -<tr> -<td>» cname</td> -<td>string</td> -<td>false</td> -<td>none</td> -<td>component namespace name</td> -</tr> -<tr> -<td>» dname</td> -<td>string</td> -<td>false</td> -<td>none</td> -<td>component display name</td> -</tr> -</tbody> -</table> -<aside class="success"> -This operation does not require authentication -</aside> -<h2 id="add-an-application-component">add an application component</h2> -<p><a id="opIdAdd Component"></a></p> -<blockquote> -<p>Code samples</p> -</blockquote> -<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests -headers = { - <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>, - <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'*/*'</span> -} - -r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/components'</span>, params={ - -}, headers = headers) - -<span class="hljs-keyword">print</span> r.json() - -</code></pre> -<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span> -curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/components \ - -H <span class="hljs-string">'Content-Type: application/json'</span> \ - -H <span class="hljs-string">'Accept: */*'</span> - -</code></pre> -<p><code>POST /components</code></p> -<p>Insert a component into database</p> -<blockquote> -<p>Body parameter</p> -</blockquote> -<pre class="highlight tab tab-json"><code>{ - <span class="hljs-attr">"cname"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"dname"</span>: <span class="hljs-string">"string"</span> -} -</code></pre> -<h3 id="add-an-application-component-parameters">Parameters</h3> -<table> -<thead> -<tr> -<th>Name</th> -<th>In</th> -<th>Type</th> -<th>Required</th> -<th>Description</th> -</tr> -</thead> -<tbody> -<tr> -<td>body</td> -<td>body</td> -<td><a href="#schemacomponentinput">ComponentInput</a></td> -<td>true</td> -<td>New component input</td> -</tr> -</tbody> -</table> -<blockquote> -<p>Example responses</p> -</blockquote> -<blockquote> -<p>200 Response</p> -</blockquote> -<h3 id="add-an-application-component-responses">Responses</h3> -<table> -<thead> -<tr> -<th>Status</th> -<th>Meaning</th> -<th>Description</th> -<th>Schema</th> -</tr> -</thead> -<tbody> -<tr> -<td>200</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td> -<td>successful operation</td> -<td>Inline</td> -</tr> -<tr> -<td>400</td> -<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td> -<td>Invalid status value</td> -<td>None</td> -</tr> -</tbody> -</table> -<h3 id="add-an-application-component-responseschema">Response Schema</h3> -<aside class="success"> -This operation does not require authentication -</aside> <h1 id="schemas">Schemas</h1> <h2 id="tocstenant">Tenant</h2> <p><a id="schematenant"></a></p> @@ -4283,50 +3782,6 @@ This operation does not require authentication </tr> </tbody> </table> -<h2 id="tocscomponent">Component</h2> -<p><a id="schemacomponent"></a></p> -<pre class="highlight tab tab-json"><code>{ - <span class="hljs-attr">"compId"</span>: <span class="hljs-number">0</span>, - <span class="hljs-attr">"cname"</span>: <span class="hljs-string">"string"</span>, - <span class="hljs-attr">"dname"</span>: <span class="hljs-string">"string"</span> -} - -</code></pre> -<h3 id="properties">Properties</h3> -<table> -<thead> -<tr> -<th>Name</th> -<th>Type</th> -<th>Required</th> -<th>Restrictions</th> -<th>Description</th> -</tr> -</thead> -<tbody> -<tr> -<td>compId</td> -<td>integer</td> -<td>false</td> -<td>none</td> -<td>none</td> -</tr> -<tr> -<td>cname</td> -<td>string</td> -<td>false</td> -<td>none</td> -<td>component namespace name</td> -</tr> -<tr> -<td>dname</td> -<td>string</td> -<td>false</td> -<td>none</td> -<td>component display name</td> -</tr> -</tbody> -</table> <h2 id="tocscomponentinput">ComponentInput</h2> <p><a id="schemacomponentinput"></a></p> <pre class="highlight tab tab-json"><code>{ @@ -4430,8 +3885,8 @@ This operation does not require authentication }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span> + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span> } ] } @@ -4597,8 +4052,8 @@ This operation does not require authentication }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"typeLink"</span>: { <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>, @@ -4648,8 +4103,8 @@ This operation does not require authentication }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>, <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>, @@ -4810,8 +4265,8 @@ This operation does not require authentication }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"typeLink"</span>: { <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>, @@ -4861,8 +4316,8 @@ This operation does not require authentication }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>, <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>, @@ -5024,8 +4479,8 @@ This operation does not require authentication }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>, <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>, <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>, @@ -5232,8 +4687,8 @@ This operation does not require authentication }, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span> }, - <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>, - <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span> + <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>, + <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span> } </code></pre> diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/api_view.html b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/api_view.html new file mode 100644 index 0000000..7561c73 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/api_view.html @@ -0,0 +1,5 @@ +<div id="page-content"> + <iframe scrolling="yes" frameborder="0" style="width:100%; height: 800px;" + ng-src="api-specs.html"> + </iframe> +</div>
\ No newline at end of file diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/app-router.js b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/app-router.js new file mode 100644 index 0000000..10337ba --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/app-router.js @@ -0,0 +1,105 @@ +/******************************************************************************* + * =============LICENSE_START========================================================= + * + * ================================================================================= + * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +appDS2.config(function($routeProvider) { + $routeProvider + .when('/api', { + templateUrl: 'app/ccsdk/home/api_view.html', + controller : '' + }) + .when('/api-spec', { + templateUrl: 'app/ccsdk/home/rest-api-spec.html', + controller : 'apiDocsController' + }) + .when('/ibp', { + templateUrl: 'app/ccsdk/inventory/inventory_blueprint_table.html', + controller : 'inventoryBlueprintTableController' + }) + .when('/ibp/:bpId', { + templateUrl: 'app/ccsdk/inventory/inventory_blueprint_table.html', + controller : 'inventoryBlueprintTableController' + }) + .when('/idep', { + templateUrl: 'app/ccsdk/cloudify/deployment_table.html', + controller : 'deploymentTableController' + }) + .when('/idep/:depId', { + templateUrl: 'app/ccsdk/cloudify/deployment_table.html', + controller : 'deploymentTableController' + }) + .when('/iplug', { + templateUrl: 'app/ccsdk/cloudify/plugin_table.html', + controller : 'PluginsTableController' + }) + .when('/sh', { + templateUrl: 'app/ccsdk/consul/service_health_table.html', + controller : 'serviceHealthTableController' + }) + .when('/nh', { + templateUrl: 'app/ccsdk/consul/node_table.html', + controller : 'nodeTableController' + }) + .when('/dc', { + templateUrl: 'app/ccsdk/consul/datacenter_table.html', + controller : 'datacenterTableController' + }) + .when('/profile/:profileId', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html', + controller: 'selfProfileController' + }) + .when('/profile_search', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html', + controller : "profileSearchCtrlDS2" + }) + .when('/post_search', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/post.html', + controller: 'postController' + }) + .when('/self_profile', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html', + controller: 'selfProfileController' + }) + .when('/role_list', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html', + controller : 'adminController' + }) + .when('/role_function_list', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html', + controller : "adminController" + }) + .when('/jcs_admin', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html', + controller: 'adminController' + }) + .when('/admin_menu_edit', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html', + controller: 'AdminMenuEditController' + }) + .when('/usage_list', { + templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/usage.html', + controller: 'usageListControllerDS2' + }) + .otherwise({ + templateUrl: 'app/ccsdk/home/executions_view.html', + controller : 'executionsViewController' + }) + ; + +});
\ No newline at end of file diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions-view-controller.js b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions-view-controller.js new file mode 100644 index 0000000..fd2dd79 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions-view-controller.js @@ -0,0 +1,415 @@ +appDS2.controller('executionsViewController', + function($scope, $rootScope, ControllerService, $modal, ExecutionService, + InventoryDeploymentService, DeploymentService, InventoryBlueprintService, + InventoryExecutionService, localStorageService, $log, $interval) { + + var coll = document.getElementsByClassName("collapsible"); + var i; + for (i = 0; i < coll.length; i++) { + coll[i].addEventListener("click", function() { + this.classList.toggle("active"); + var content = this.nextElementSibling; + if (content.style.display === "" || content.style.display === "block") { + content.style.display = "none"; + content.style.maxHeight = null; + } else { + content.style.display = "block"; + content.style.maxHeight = content.scrollHeight + "px"; + } + }); + } + var stop; + $scope.ecdapp = {}; + $scope.ecdapp.isDataLoading = false; + $scope.ecdapp.appLabel = ""; + $scope.ecdapp.bpCount = 0; + $scope.ecdapp.depCount = 0; + $scope.ecdapp.pluginCount = 0; + $scope.ecdapp.filterByUser = true; + $scope.ecdapp.searchByBp = 'owner:' + $scope.userId + ';'; + $scope.ecdapp.searchByDep = 'owner:' + $scope.userId + ';'; + $scope.ecdapp.bpObjList = []; + $scope.ecdapp.depObjList = []; + $scope.ecdapp.currentBpId = ''; + $scope.ecdapp.currentDep; + $scope.ecdapp.isBpDataLoading = false; + $scope.ecdapp.isDepDataLoading = false; + $scope.ecdapp.isPluginDataLoading = false; + $scope.ecdapp.isExecDataLoading = false; + $scope.ecdapp.level_options = { + "off":"Group", + "on":"User" + }; + $scope.ecdapp.inv_query_options = { + "off":"Off", + "on":"On" + }; + + $scope.ecdapp.showingMoreFilters = false; + + $scope.ecdapp.toggleMoreFilters = function() { + $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters; + }; + $scope.ecdapp.availableStatus = + ['pending','started','cancelling','force_cancelling','cancelled','terminated','failed']; + $scope.ecdapp.selectedStatus = 'started'; + $scope.ecdapp.level_switch = { + value: true + }; + $scope.ecdapp.inv_load = { + value: false + }; + + $scope.ecdapp.currentPage = 1; + $scope.ecdapp.viewPerPage = 10; + $scope.ecdapp.selectedTenant = ''; + $scope.ecdapp.execId = ''; + + var debug = false; + + $scope.ecdapp.resetFilters = function() { + $scope.ecdapp.selectedTenant = ''; + $scope.ecdapp.selectedStatus = ''; + }; + + $scope.ecdapp.extendedfilterSrch = function() { + $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters; + $scope.ecdapp.searchExecTable(); + }; + + $scope.ecdapp.searchExecTable = function() { + $scope.ecdapp.currentPage = 1; + $scope.ecdapp.viewPerPage = 10; + if ($scope.ecdapp.execId != '') { + getExecutionForId(); + } else { + if ($scope.ecdapp.selectedTenant == '') { + getActiveExecutions(); + } else { + getPerTenantExecutions(); + } + } + }; + + $scope.ecdapp.toggleUserFilt = function() { + if ($scope.ecdapp.level_switch.value) { + $scope.ecdapp.searchByBp = 'owner:' + $scope.userId + ';'; + $scope.ecdapp.searchByDep = 'owner:' + $scope.userId + ';'; + } else { + $scope.ecdapp.searchByBp = null; + $scope.ecdapp.searchByDep = null; + } + getBlueprintsCount(); + getDeploymentsCount(); + }; + + $scope.$watch('ecdapp.inv_load["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + if (newValue === true) { + $scope.ecdapp.toggleUserFilt(); + $scope.ecdapp.searchExecTable(); + stop = $interval( function(){ $scope.ecdapp.toggleUserFilt(); $scope.ecdapp.searchExecTable(); }, 60000, 100, false); + } else { + $scope.ecdapp.stopLoading(); + } + } + }, true); + + $scope.ecdapp.stopLoading = function() { + if (angular.isDefined(stop)) { + $interval.cancel(stop); + stop = undefined; + } + }; + + var getTenants = function() { + var tenantStr = localStorageService.get('tenants'); + if (!tenantStr) { + ControllerService.getTenants() + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("executionsViewController.getTenants failed: " + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + } else { + var tenants = []; + for (var tenIndx = 0; tenIndx < jsonObj.items.length; tenIndx++) { + tenants.push(jsonObj.items[tenIndx].name); + } + localStorageService.set('tenants', JSON.stringify(tenants)); + $scope.ecdapp.availableTenants = tenants; + } + }, function(error) { + $log.error("executionsViewController.loadTable failed: " + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + }); + } else { + $scope.ecdapp.availableTenants = JSON.parse(tenantStr); + } + getActiveExecutions(); + }; + + var getAppLabel = function() { + var label = localStorageService.get('appLabel'); + if (!label) { + ControllerService.getAppLabel().then(function(jsonObj) { + if (debug) { + $log.debug("Controller.getAppLabel succeeded: " + JSON.stringify(jsonObj)); + } + localStorageService.set('appLabel', JSON.stringify(jsonObj)); + $scope.ecdapp.appLabel = jsonObj; + }, function(error) { + $log.error("Controller.getAppLabel failed: " + error); + }); + } else { + $scope.ecdapp.appLabel = JSON.parse(label); + } + }; + + var getBlueprintsCount = function() { + $scope.ecdapp.bpObjList = []; + $scope.ecdapp.currentBpId = ''; + $scope.ecdapp.isBpDataLoading = true; + InventoryBlueprintService.getBlueprintIdsList($scope.ecdapp.searchByBp).then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("execViewCtlr.getBlueprintsCount failed: " + + jsonObj.error); + $scope.ecdapp.bpCount = 0; + $scope.ecdapp.isBpDataLoading = false; + $scope.ecdapp.bpObjList = []; + } else { + $scope.ecdapp.bpCount = jsonObj.totalItems; + $scope.ecdapp.bpObjList = jsonObj.items; + $scope.ecdapp.isBpDataLoading = false; + } + }, + function(error) { + $log.error("execViewCtlr.getBlueprintsCount failed: " + + error); + $scope.ecdapp.bpCount = 0; + $scope.ecdapp.bpObjList = []; + $scope.ecdapp.isBpDataLoading = false; + }); + }; + + $scope.ecdapp.updateDepl = function() { + $scope.ecdapp.currentDep = ''; + if ($scope.ecdapp.currentBpId != '') { + $scope.ecdapp.isDeplDataLoading = true; + $scope.ecdapp.depObjList = []; + $scope.ecdapp.execData = []; + var srvcIds = []; + var srvcTypIds = []; + srvcTypIds.push($scope.ecdapp.currentBpId); + InventoryBlueprintService.getDeploymentForBp(srvcTypIds) + .then(function(jsonObj) { + if (jsonObj.error) { + $scope.ecdapp.depObjList = []; + $scope.ecdapp.isDeplDataLoading = false; + } else { + for (var typIndx = 0; typIndx < jsonObj.length; typIndx++) { + for (var depIndx = 0; depIndx < jsonObj[typIndx].serviceRefList.items.length; depIndx++) { + srvcIds.push(jsonObj[typIndx].serviceRefList.items[depIndx]); + } + } + $scope.ecdapp.depObjList = srvcIds; + //$scope.ecdapp.currentDep = $scope.ecdapp.depObjList[0]; + $scope.ecdapp.isDeplDataLoading = false; + } + }, function(error) { + $log.error("inventoryBlueprintController.updateTable failed: " + error); + bpDepls = []; + $scope.ecdapp.isDeplDataLoading = false; + }); + } + }; + $scope.ecdapp.copyStringToClipboard = function(str) { + // Create new element + var el = document.createElement('textarea'); + // Set value (string to be copied) + el.value = str; + // Set non-editable to avoid focus and move outside of view + el.setAttribute('readonly', ''); + el.style = {position: 'absolute', left: '-9999px'}; + document.body.appendChild(el); + // Select text inside element + el.select(); + // Copy text to clipboard + document.execCommand('copy'); + // Remove temporary element + document.body.removeChild(el); + }; + + $scope.ecdapp.updateExec = function() { + if ($scope.ecdapp.currentDep != '') { + $scope.ecdapp.isExecDataLoading = true; + $scope.ecdapp.resetFilters(); + var currentDeplId = $scope.ecdapp.currentDep.split(":")[0]; + var currentDeplTenant = $scope.ecdapp.currentDep.split(":")[1]; + InventoryExecutionService.getExecutionsByDeployment(currentDeplId, + currentDeplTenant, + 1, + 1000).then( + function(jsonObj) { + if (jsonObj.error) { + $scope.ecdapp.execData = []; + $scope.ecdapp.isExecDataLoading = false; + } else { + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.execData = jsonObj.items; + $scope.ecdapp.isExecDataLoading = false; + } + }, function(error) { + $log.error("execViewCtlr.updateExec failed: " + error); + $scope.ecdapp.isExecDataLoading = false; + }); + } + }; + + var getActiveExecutions = function() { + $scope.ecdapp.isExecDataLoading = true; + InventoryExecutionService.getActiveExecutions($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage) + .then( + function(jsonObj) { + if (jsonObj.error) { + $scope.ecdapp.execData = []; + $scope.ecdapp.isExecDataLoading = false; + } else { + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.execData = jsonObj.items; + $scope.ecdapp.isExecDataLoading = false; + } + }, function(error) { + $log.error("execViewCtlr.updateExec failed: " + error); + $scope.ecdapp.isExecDataLoading = false; + }); + }; + + var getPerTenantExecutions = function() { + $scope.ecdapp.isExecDataLoading = true; + InventoryExecutionService.getExecutionsByTenant($scope.ecdapp.selectedTenant, + $scope.ecdapp.selectedStatus, $scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage) + .then( + function(jsonObj) { + if (jsonObj.error) { + $scope.ecdapp.execData = []; + $scope.ecdapp.isExecDataLoading = false; + } else { + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.execData = jsonObj.items; + $scope.ecdapp.isExecDataLoading = false; + } + }, function(error) { + $log.error("execViewCtlr.updateExec failed: " + error); + $scope.ecdapp.isExecDataLoading = false; + }); + }; + + var getExecutionForId = function() { + $scope.ecdapp.isExecDataLoading = true; + InventoryExecutionService.getExecutionsById($scope.ecdapp.execId, + $scope.ecdapp.selectedTenant, $scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage) + .then( + function(jsonObj) { + if (jsonObj.error) { + $scope.ecdapp.execData = []; + $scope.ecdapp.isExecDataLoading = false; + } else { + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.execData = jsonObj.items; + $scope.ecdapp.isExecDataLoading = false; + } + }, function(error) { + $log.error("execViewCtlr.getExecutionsById failed: " + error); + $scope.ecdapp.isExecDataLoading = false; + }); + }; + /** + * Invoked at first page load AND when + * user clicks on the B2B pagination control. + */ + $scope.pageChangeHandler = function(page) { + $scope.ecdapp.currentPage = page; + if ($scope.ecdapp.selectedTenant != '') { + getPerTenantExecutions(); + } + } + + var getDeploymentsCount = function() { + $scope.ecdapp.isDepDataLoading = true; + $scope.ecdapp.execData = []; + InventoryDeploymentService.getDeploymentCount($scope.ecdapp.searchByDep).then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("execViewCtlr.getDeploymentscount failed: " + + jsonObj.error); + $scope.ecdapp.depCount = 0; + $scope.ecdapp.depObjList = []; + } else { + $scope.ecdapp.depCount = jsonObj.totalItems; + $scope.ecdapp.depObjList = jsonObj.items; + $scope.ecdapp.isDepDataLoading = false; + } + }, + function(error) { + $log.error("execViewCtlr.getDeploymentscount failed: " + + error); + $scope.ecdapp.isDepDataLoading = false; + $scope.ecdapp.depCount = 0; + }); + }; + + var getPluginsCount = function() { + $scope.ecdapp.isPluginDataLoading = true; + ControllerService.getPluginsCount().then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("execViewCtlr.getPluginsCount failed: " + + jsonObj.error); + $scope.ecdapp.isPluginDataLoading = false; + $scope.ecdapp.pluginCount = 0; + } else { + $scope.ecdapp.pluginCount = jsonObj.totalItems; + $scope.ecdapp.isPluginDataLoading = false; + } + }, + function(error) { + $log.error("execViewCtlr.getPluginsCount failed: " + + error); + $scope.ecdapp.pluginCount = 0; + $scope.ecdapp.isPluginDataLoading = false; + }); + }; + var getOwners = function() { + InventoryBlueprintService.getOwnersList().then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("execViewCtlr.getOwnersList failed: " + + jsonObj.error); + $scope.ecdapp.bpOwners = []; + } else { + $scope.ecdapp.bpOwners = jsonObj; + localStorageService.set('bpOwners', JSON.stringify(jsonObj)); + } + }, + function(error) { + $log.error("execViewCtlr.getOwnersList failed: " + + error); + $scope.ecdapp.bpOwners = []; + }); + }; + + // Initialize the page + getTenants(); + getAppLabel(); + getBlueprintsCount(); + getDeploymentsCount(); + getOwners(); + getPluginsCount(); + getActiveExecutions(); + $scope.$on('$destroy', function() { + $scope.ecdapp.stopLoading(); + }); +}); diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions_view.html b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions_view.html new file mode 100644 index 0000000..09d9814 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions_view.html @@ -0,0 +1,377 @@ +<div id="page-content"> + <br> + <h4 class="heading-page" id="controllers">Dashboard</h4> + <hr class="lite"> + <div class="span3 form-row btn-switch-label" style="margin-top: -60px;float: right;"> + <div class="tooltip" b2b-tooltip trigger="focus"> + <a href="javascript:void(0)" class="tooltip-element" data-placement="left" role="button" + style="text-decoration: none; margin-right: 10px;"> + Access Type + <div class="arrow"></div> + </a> + <div class="tooltip-wrapper" role="tooltip" aria-live="polite" aria-atomic="false" style="z-index:1111"> + <div class="tooltip-size-control"> + <div class="helpertext" tabindex="-1" role="tooltip" id="tooltiptext1"> + <div class="popover-title">My Dashboard</div> + <div class="popover-content"> + <p>Toggle access type selection between logged in user's data or user role group data.</p> + <strong class="hidden-spoken">Double tap to close help message.</strong> + </div> + </div> + </div> + </div> + </div> + <!-- <span aria-hidden="true">Access level</span>--> + <div b2b-switches-v2 id="switch1" style="margin-top: -5px;" ng-model="ecdapp.level_switch.value" options="ecdapp.level_options" ng-disabled="allDisabled" ng-change="ecdapp.toggleUserFilt()"> + </div> + </div> + <div class="span3 form-row btn-switch-label"> + <div class="tooltip" b2b-tooltip trigger="focus"> + <a href="javascript:void(0)" class="tooltip-element" data-placement="left" role="button" + style="text-decoration: none; margin-right: 10px;"> + Auto Refresh + <div class="arrow"></div> + </a> + <div class="tooltip-wrapper" role="tooltip" aria-live="polite" aria-atomic="false" style="z-index:1111"> + <div class="tooltip-size-control"> + <div class="helpertext" tabindex="-1" role="tooltip" id="tooltiptext1"> + <div class="popover-title">Reload data automatically</div> + </div> + </div> + </div> + </div> + <!-- <span aria-hidden="true">Access level</span>--> + <div b2b-switches-v2 id="switch2" ng-model="ecdapp.inv_load.value" options="ecdapp.inv_query_options" > + </div> + </div> + <button title="Expand/Collapse Tiles Container" class="collapsible"></button> + <div class="content"> + <div class="b2b-card-container"> + <div class="row"> + <div class="span3 b2b-card-wid"> + <div class="b2b-cards" style="border-radius: 8px;text-shadow: 1px 1px 7px #0574ac;border: 1px solid gray;border-top: 5px solid #0574ac;"> + <div ng-show="ecdapp.isBpDataLoading" class="ng-scope ng-hide"> + <div class="span" style="margin-bottom: 5px;"> + <i class="icon-spinner small" role="img"></i> + </div> + </div> + <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;"> + <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" > + <span class="arrow"></span> + </a> + <span class="tooltip-wrapper"> + <span class="tooltip-size-control"> + <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Aggregate count of blueprints for user/role set</span> + <span class="popover-content"> + <span>Navigation link to blueprints Inventory screen</span> + <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong> + </span> + </span> + </span> + </span> + </span> + <a ng-if="ecdapp.level_switch.value" href="ecd#/ibp/owner:{{userId}}"> + <div class="b2b-card-header"> + <i class="icon-documents-document" role="img" style="font-size: 35px;margin-top: -20px;margin-left: -20px;"></i> + <span class="b2b-title" > {{ecdapp.bpCount}} </span> + </div> + <div class="b2b-card-content" + style="text-align: center;"> + BLUEPRINTS + </div> + </a> + <a ng-if="!ecdapp.level_switch.value" href="ecd#/ibp/owner:group"> + <div class="b2b-card-header"> + <i class="icon-documents-document" role="img" style="margin-top: -20px; + margin-left: -20px; font-size: 35px"></i> + <span class="b2b-title" > {{ecdapp.bpCount}} </span> + </div> + <div class="b2b-card-content" + style="text-align: center;"> + BLUEPRINTS + </div> + </a> + </div> + </div> + <div class="span3 b2b-card-wid"> + <div class="b2b-cards" style="text-shadow: 1px 1px 7px #008744;border-radius:8px;border: 1px solid gray;border-top: 5px solid #008744;"> + <div ng-show="ecdapp.isDepDataLoading" class="ng-scope ng-hide"> + <div class="span" style="margin-bottom: 5px;"> + <i class="icon-spinner small" role="img"></i> + </div> + </div> + <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;"> + <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" > + <span class="arrow"></span> + </a> + <span class="tooltip-wrapper"> + <span class="tooltip-size-control"> + <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Aggregate count of deployments for user/role set</span> + <span class="popover-content"> + <span>Navigation link to cloudify deployments Inventory screen</span> + <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong> + </span> + </span> + </span> + </span> + </span> + <a ng-if="ecdapp.level_switch.value" href="ecd#/idep/owner:{{userId}}"> + <div class="b2b-card-header"> + <i class="icon-misc-business" role="img" style="margin-top: -20px; + margin-left: -20px; font-size: 35px"></i> + <span class="b2b-title"> {{ecdapp.depCount}} </span> + </div> + <div class="b2b-card-content" + style="text-align: center;"> + DEPLOYMENTS + </div> + </a> + <a ng-if="!ecdapp.level_switch.value" href="ecd#/idep/owner:group"> + <div class="b2b-card-header"> + <i class="icon-misc-business" role="img" style="font-size: 35px;margin-top: -20px;margin-left: -20px;"></i> + <span class="b2b-title"> {{ecdapp.depCount}} </span> + </div> + <div class="b2b-card-content" + style="text-align: center;"> + DEPLOYMENTS + </div> + </a> + </div> + </div> + <div class="span3 b2b-card-wid"> + <div class="b2b-cards" style="text-shadow: 1px 1px 7px #e7d81e;border-radius:8px;border: 1px solid gray;border-top: 5px solid #e7d81e;"> + <div ng-show="ecdapp.isPluginDataLoading" class="ng-scope ng-hide"> + <div class="span" style="margin-bottom: 5px;"> + <i class="icon-spinner small" role="img"></i> + </div> + </div> + <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;"> + <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" > + <span class="arrow"></span> + </a> + <span class="tooltip-wrapper"> + <span class="tooltip-size-control"> + <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Aggregate count of cloudify plugins</span> + <span class="popover-content"> + <span>Navigation link to cloudify plugins screen</span> + <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong> + </span> + </span> + </span> + </span> + </span> + <a href="ecd#/iplug"> + <div class="b2b-card-header"> + <i class="icon-controls-gear" role="img" style="font-size: 35px;margin-top: -20px;margin-left: -20px;"></i> + <span class="b2b-title"> {{ecdapp.pluginCount}} </span> + </div> + <div class="b2b-card-content" + style="text-align: center;"> + PLUGINS + </div> + </a> + </div> + </div> + </div> + </div> + <div class="span9 row-nowrap" style="margin-bottom: 10px; float: right; margin-top: -30px;"> + <div class="span6 form-row"> + <div class="span12 field-group"> + <input class="span12" list="bpList" type="input" ng-model="ecdapp.currentBpId" ng-change="ecdapp.updateDepl()" placeholder="Blueprints"/> + <span class="tooltip" style="float: right; margin-top: -30px;" b2b-tooltip> + <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" > + <span class="arrow"></span> + </a> + <span class="tooltip-wrapper"> + <span class="tooltip-size-control"> + <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Blueprints list</span> + <span class="popover-content"> + <span>autocomplete dropdown list of blueprints, a selection will trigger deployment list query</span> + <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong> + </span> + </span> + </span> + </span> + </span> + <datalist id="bpList"> + <option ng-repeat="d in ecdapp.bpObjList" value="{{d.typeId}}">{{d.typeName}}</option> + </datalist> + </div> + </div> + <div class="span1 form-row"> + <div ng-show="ecdapp.isDeplDataLoading" class="ng-scope ng-hide"> + <div class="span" style="margin-bottom: 5px;"> + <i class="icon-spinner small" role="img"></i> + </div> + </div> + </div> + <div class="span6 form-row"> + <!-- <label for="depl">Deployments</label>--> + + <div class="span12 field-group"> + <input id="depInput" class="span12" list="depList" type="input" ng-model="ecdapp.currentDep" ng-change="ecdapp.updateExec()" placeholder="Deployments"/> + <span class="tooltip" style="float: right; margin-top: -30px;" b2b-tooltip> + <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" > + <span class="arrow"></span> + </a> + <span class="tooltip-wrapper"> + <span class="tooltip-size-control"> + <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Deployments list</span> + <span class="popover-content"> + <span>autocomplete dropdown list of deployments, a selection will trigger deployment executions query</span> + <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong> + </span> + </span> + </span> + </span> + </span> + <datalist id="depList"> + <option ng-repeat="d in ecdapp.depObjList" value="{{d.id}}:{{d.tenant_name}}">{{d.id}}</option> + </datalist> + </div> + </div> + </div> + </div> + <div ng-hide="ecdapp.errMsg" style="margin-top: 40px;border: 1px solid gray;border-radius: 5px;padding: 10px;clear: both;border-top: 2px solid #0d2dca;"> + <label for="executions-table">Executions</label> + <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;"> + <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" > + <span class="arrow"></span> + </a> + <span class="tooltip-wrapper"> + <span class="tooltip-size-control"> + <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Executions summary table</span> + <span class="popover-content"> + <span>Current active executions are displayed by default. Use the search box to specify additional query filters for deployment executions. A deployment selection will automatically trigger a refresh of the executions table.</span> + <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong> + </span> + </span> + </span> + </span> + </span> + <div id="button-search-row" style="float: right;width: 50%;"> + <div class="advanced-search"> + <input tabindex="0" style="padding-left: 50px;" + placeholder="Enter search filters from the dropdown menu" + class="advanced-search-input" type="text"></input> + <button type="button" id="show-menu-filters" + class="btn dropdown-toggle" + ng-click="ecdapp.toggleMoreFilters()" data-toggle="dropdown" + title="More Filters"> + <i class="icon-controls-down"></i> + </button> + </div> + <div class="menu-filters" ng-show="ecdapp.showingMoreFilters" style="width: 40%;"> + <div class="group"> + <label class="col-sm-3 control-label">Execution ID: </label> <input + tabindex="0" class="advanced-search-input" type="text" + title="Search by execution ID" + ng-model="ecdapp.execId"></input> + </div> + <div class="group"> + <label class="col-sm-3 control-label">Tenants: </label> + <div class="field-group"> + <select class="span12" name="tenant" b2b-dropdown placeholder-text="Select Tenant" ng-model="ecdapp.selectedTenant"> + <option b2b-dropdown-list option-repeat="d in ecdapp.availableTenants" value="{{d}}">{{d}}</option> + </select> + </div> + </div> + <div class="group"> + <label class="col-sm-3 control-label">Status: </label> + <div class="field-group"> + <select class="span12" name="status" b2b-dropdown placeholder-text="Select status" ng-model="ecdapp.selectedStatus"> + <option b2b-dropdown-list option-repeat="d in ecdapp.availableStatus" value="{{d}}">{{d}}</option> + </select> + </div> + </div> + <div class="group" style="float: right;"> + <button tabindex="-1" class="btn btn-small" + title="Reset Filters" type="button" + ng-click="ecdapp.resetFilters()"> + <i class="icon-arrows-update-refresh-sync"></i> + </button> + <button tabindex="1" class="btn btn-small" + title="Filtered search" type="button" + ng-click="ecdapp.extendedfilterSrch()"> + <i class="icon-controls-magnifyingglass"></i> + </button> + </div> + </div> + </div> + <hr class="lite" style="margin-top: 20px;"> + <div ng-show="ecdapp.isExecDataLoading" class="ng-scope ng-hide"> + <div class="span" style="margin-bottom: 5px;"> + <i class="icon-spinner small" role="img"></i> + </div> + </div> + <div b2b-table id="executions-table" class="b2b-table-div" + table-data="ecdapp.execData" search-string="ecdapp.searchString" + current-page="ecdapp.currentPageIgnored" + next-sort="ecdapp.nextSortIgnored"> + <table> + <thead b2b-table-row type="header"> + <tr id="th-header-row"> + <th b2b-table-header key="index"></th> + <th b2b-table-header key="deployment_id">Deployment</th> + <th b2b-table-header key="workflow_id">Workflow</th> + <th b2b-table-header key="created_at">Created</th> + <th b2b-table-header key="ended_at">Ended</th> + <th b2b-table-header key="tenant_name">Tenant</th> + <th b2b-table-header key="status">Status</th> + </tr> + </thead> + <tbody b2b-table-row type="body" + ng-repeat="rowData in ecdapp.execData"> + <tr id="tr-rowData"> + <td b2b-table-body> + <div class="id-tooltip"><span>ID</span> + <div class="wrapper"> + <button style="border-radius: 5px;margin-right: 20px;font-weight: lighter;border: 1px solid black;" + ng-click="ecdapp.copyStringToClipboard(rowData.id)" class="">Copy ID</button> + <span class="id-tooltiptext">{{rowData.id}}</span> + </div> + </div> + </td> + <!-- <td b2b-table-body>ID</td>--> + <td b2b-table-body> + <a href="ecd#/idep/tenant:{{rowData.tenant_name}};serviceRef:{{rowData.deployment_id}}"> + {{rowData.deployment_id}} + </a> + </td> + <td b2b-table-body ng-bind="rowData.workflow_id" /> + <td b2b-table-body ng-bind="rowData.created_at" /> + <td b2b-table-body ng-bind="rowData.ended_at" /> + <td b2b-table-body ng-bind="rowData.tenant_name" /> + <!-- <td b2b-table-body ng-bind="rowData.id" />--> + <td b2b-table-body ng-if="rowData.status == 'pending'" > + <span class="ng-scope" style="background-color: #edef8e;padding: 5px;border-radius: 3px; opacity: 0.6; font-weight: bold;">waiting to start</span></td> + <td b2b-table-body ng-if="rowData.status == 'started'" > + <span class="ng-scope" style="background-color: ##f0fd2e;padding: 5px;border-radius: 3px; opacity: 0.6; font-weight: bold;">in-progress</span></td> + <td b2b-table-body ng-if="rowData.status == 'cancelling'" > + <span class="ng-scope" style="background-color: #cabdbd;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">cancel in progress</span></td> + <td b2b-table-body ng-if="rowData.status == 'force_cancelling'" > + <span class="ng-scope" style="background-color: #cabdbd;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;"">force-cancelling in progress</span> </td> + <td b2b-table-body ng-if="rowData.status == 'cancelled'" > + <span class="ng-scope" style="background-color: #9a9690;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">cancelled</span> + </td> + <td b2b-table-body ng-if="rowData.status == 'terminated'" > + <span class="ng-scope" style="background-color: #62d826;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">successful</span> + </td> + <td b2b-table-body ng-if="rowData.status == 'failed'"> + <span class="ng-scope" style="background-color: #fd2e2e;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">failed</span> + </td> + </tr> + </tbody> + </table> + </div> + <div b2b-pagination="" total-pages="ecdapp.totalPages" + current-page="ecdapp.currentPageNum" + click-handler="pageChangeHandler" role="navigation"></div> + </div> +</div>
\ No newline at end of file diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom-style.css b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom-style.css new file mode 100644 index 0000000..df3e489 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom-style.css @@ -0,0 +1,658 @@ +/* Styles for ECOMP Controller Dashboard */ + +.content-container { + min-height: 650px; + width: calc(100% - 50px); +} + +.ecd-error-message { + font-size: 14px; + font-weight: bold; + color: red; +} + +.ecd-icon-display { + font-size: 18px; +} + +.ecd-icon-action { + font-size: 18px; +} + +.ecd-icon-action:hover { + color: red; + text-decoration: none; +} + +.selected { + background-color:#abb5e6; + color:black; + font-weight:bold; +} +.red-background { + background-color: #ff0000b3; + } +.green-background { + background-color: #bbf0bb; + } +.td-error { + border-top: 2px dotted red; + border-bottom: 2px dotted red; + background-color: rgb(210, 190, 190); + } +.menu { + display: none; + z-index: 1000; + border: 1px dotted; + border-radius: 5px; + padding: 10px; + width: 40%; + background: azure; + position: fixed; + overflow: scroll; + background: slategray; + color: white; + right: 20px; +} + +.show-menu { + z-index: 800; +} + +#show-menu { + display: none; +} + +#show-menu:checked ~ .menu { + display: block; +} + +#show-menu:checked ~ .show-menu { + color: blue; +} + +.menu-off { + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 700; + display: none; +} + +.menu-off { + display: none; +} + +#show-menu:checked ~ .menu-off { + display: block; +} + +#show-menu:checked ~ .show-menu { + display: none; +} + +.menu-off input[type=checkbox]:checked ~ .menu { + display: none; +} + +.menu-off input[type=checkbox]:checked ~ .show-menu { + display: block; +} + +.menu-filters { + display: block; + z-index: 1000; + border: 1px dotted; + border-radius: 5px; + padding: 10px; + width: 48%; + background: #ffffff; + position: absolute; + overflow: scroll; +} + +.show-menu-filters { + z-index: 800; + color: blue; +} + +#show-menu-filters[aria-expanded="true"] ~ .menu-filters { + display: block; +} + +#show-menu-filters:checked ~ .show-menu-filters { + color: blue; +} + +.menu-filters-off { + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 700; + display: none; +} + +.menu-filters-off { + display: none; +} + +#show-menu-filters:checked ~ .menu-filters-off { + display: block; +} + +#show-menu-filters:checked ~ .show-menu-filters { + display: none; +} + +.menu-filters-off input[type=checkbox]:checked ~ .menu-filters { + display: none; +} + +.menu-filters-off input[type=checkbox]:checked ~ .show-menu-filters { + display: block; +} + +.ui-select-match .btn { + font-size: 1.5rem; + padding: 5px; +} + +.ui-select-multiple.ui-select-bootstrap .ui-select-match .close { + font-size: 1.0em; + margin-left: 10px; +} +.advanced-search { + display: block; + position: relative; +} + +.advanced-search .btn{ + box-shadow: none; + position: absolute; + top: 5px; + right: 3px; + min-width: 10px; + width: 25px; + height: 25px; + padding: 1px 1px 1px 1px; + +} + +.advanced-search i { + position: relative; + top: 0px; + right: 0px; + width: 20px; + height: 20px; + padding: 0px 0px 0px 0px; + margin: 0px 0px 0px 0px; +} + +.advanced-search-input { + padding: 10px 19px 9px 18px; + font-size: 1.5rem; + border-radius: 8px; + width: 100%; +} +td > .btn-group { + min-width: 0; + width: auto; +} + +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + z-index: 1000; + display: none; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + top: 30px; + left: -10px; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} + +.dropdown-menu li { + margin-bottom: 5px; +} + +.dropdown-menu li div { + padding-left: 5px; +} + +.dropdown-menu li div i { + margin-right: 5px; +} + +td > .btn-group > .btn { + min-width: 0; + color: #0568ae; +} + +td > .btn-group > .btn> i { + font-size: 30px; +} + +li > a.active { + font-weight: bolder; + outline: thin dotted #666; +} + +tr:hover { + background-color: #f2f2f2; +} + +tr:focus { + background-color: #f2f2f2; +} + +.modalwrapper.modal-docked .modal-jumbo { + max-height: 100%; + height: 100%; + overflow: hidden; + top: 0; + width: 100%; + max-width: 100%; +} + +#addAppDiv { + padding-left: 10px; + background: lightgray; + border-radius: 5px; + padding-bottom: 15px; +} + +.field-group.error .error-msg { + color: red; + display: block; + font-size: 14px; + line-height: 14px; + font-family: "Omnes-ATT-W02-Medium"; + position: relative; + padding-left: 18px; + margin-top: 10px; +} + +.heading-page { + margin-bottom: 20px; +} + +.footer-container { + top: 25px; +} +.b2b-dragdrop { + padding: 10px; +} + +.my-tooltip { + position: relative; + display: inline; +} + +.id-tooltip { + position: relative; + display: inline; +} + +.id-tooltip > .id-tooltiptext, .id-tooltip > .wrapper { + display: flex; + visibility: hidden; + width: 400px; + background-color: #dbdde3; + white-space: pre-line; + border-radius: 6px; + padding: 10px; + position: absolute; + bottom: 25%; + left: 80%; + transition: opacity 0.3s; + border: 1px solid gray; +} + +.id-tooltip:hover > .id-tooltiptext, .id-tooltip:hover > .wrapper { + pointer-events: auto; + visibility: visible; + opacity: 1; +} +.wrapper > .id-tooltiptext { + overflow-y: auto; + max-height: 400px; + display: block; + clear: both; +} + +.id-tooltip .id-tooltiptext::after { + content: ""; + position: absolute; + top: 40%; + right: 100%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent #544f4f transparent transparent; +} + +.wrapper { + position:relative; +} + +.my-tooltip > .my-tooltiptext, .my-tooltip > .wrapper { + visibility: hidden; + width: 600px; + background-color: #647dd6; + color: #fff; + white-space: pre-line; + border-radius: 6px; + padding: 10px; + position: absolute; + z-index: 1; + bottom: 90%; + left: -5%; + opacity: 0; + transition: opacity 0.3s; + overflow: visible; +} + +.my-tooltip .my-tooltiptext::after { + content: ""; + position: absolute; + top: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: #555 transparent transparent transparent; +} + +.my-tooltip:hover > .my-tooltiptext, .my-tooltip:hover > .wrapper { + pointer-events: auto; + visibility: visible; + opacity: 1; +} +.wrapper > .my-tooltiptext { + overflow-y: auto; + max-height: 400px; + display: block; + clear: both; +} + +.stat_tooltip { + position: relative; + display: inline-block; + top: -10px; +} + +.gen_tooltip { + display: inline-block; + position: relative; +} + +.gen_tooltip .gen_tooltiptext_r { + visibility: hidden; + width: 250px; + background-color: #647dd6; + color: #000; + text-align: center; + border-radius: 2px; + border: 1px solid rgba(0, 0, 0, .15); + padding: 5px 0; + position: absolute; + z-index: 100; + left: 110%; + top: -50%; +} + +.gen_tooltip .gen_tooltiptext_r::after { + content: ""; + position: absolute; + top: 50%; + right: 100%; /* to the left of tooltip */ + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: transparent #fff transparent transparent; +} + +.gen_tooltip:hover .gen_tooltiptext_r { + visibility: visible; +} + +.stat_tooltip .stat_tooltiptext, .stat_tooltip .wrapper { + visibility: hidden; + width: 500px; + background-color: #c8d1f0; + color: #000; + text-align: left; + border-radius: 6px; + border: 1px solid rgba(0, 0, 0, .15); + padding: 5px 0; + position: absolute; + z-index: 100; + bottom: 100%; + height: 200px; +} + +.stat_tooltip .stat_tooltiptext::after, .stat_tooltip .wrapper::after { + content: ""; + position: absolute; + top: 100%; + left: 4%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: rgba(0, 0, 0, .15) transparent transparent transparent; +} + +.stat_tooltip:hover .stat_tooltiptext, .stat_tooltip:hover .wrapper { + visibility: visible; +} + +.stat_tooltip .wrapper .clip-btn-div { + display: inline; + left: 50px; + top: 80px; +} + +.b2b-card-container { + background-color: #ffffff; +} + +.b2b-cards { + transition: .5s; + opacity: .7; +} +.b2b-cards a { + text-decoration: none; +} + +.b2b-cards:hover { + box-shadow: 0px 0px 20px 10px #eccc5e; + text-shadow: none !important; + background-color: #ffffff !important; + opacity: 1; + +} + +.b2b-cards .tooltip { + visibility: hidden; +} + +.b2b-cards:hover .tooltip { + visibility: visible; +} + +.b2b-cards .b2b-card-footer-flyout { + visibility: hidden; +} + +.b2b-cards:hover .b2b-card-footer-flyout { + visibility: visible; +} +.b2b-card-header { + text-align: center; +} + +.b2b-card-header i { + font-size: 35px; +} +.b2b-card-container .b2b-title { + font-size: 50px; +} +.b2b-card-content { + text-align: center; +} + +.collapsible { + color: #2196F3; + cursor: pointer; + padding: 18px; + width: 100%; + border: none; + outline: none; + font-size: 25px; + font-weight: bolder; + background-color: #ffffff; + height: 2px; + margin-top: -30px; +} + +.collapsible:after { + content: "\2796"; + color: #2196F3; + float: right; + margin-left: 5px; +} + +.collapsible.active:after { + content: '\02795'; +} + +.content { + padding: 0 18px; + height: auto; + display: block; + transition: max-height 0.2s ease-out; + +} diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_spa.html b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom_spa.html index fabb450..378ddfe 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_spa.html +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom_spa.html @@ -36,15 +36,16 @@ <script src="app/fusion/external/angular-1.4.13/angular-sanitize.js"></script> <script src="app/fusion/external/angular-1.4.13/angular-touch.js"></script> <script src="app/fusion/external/jquery/dist/jquery.min.js"></script> - <!--<script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>--> <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script> <!-- Third-party scripts from app --> - <!-- https://github.com/jeremyfa/yaml.js --> <script src="app/ccsdk/external/bootstrap.min.js" type="text/javascript"></script> <script src="app/ccsdk/external/yaml.js" type="text/javascript"></script> - + <script src="app/ccsdk/external/index.js" type="text/javascript"></script> + <script src="app/ccsdk/external/select.js" type="text/javascript"></script> + <script src="app/ccsdk/external/angular-local-storage.js" type="text/javascript"></script> <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.js"></script> + <!-- Tweaked CSS --> <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css"> <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css"> @@ -54,7 +55,9 @@ <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ecomp-ionicons.css"> <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css"> - + <link rel="stylesheet" type="text/css" href="app/ccsdk/external/select.css"> + <link rel="stylesheet" href="app/ccsdk/home/oom-style.css"/> + <!-- main app --> <script src="app/ccsdk/home/modal-service.js"></script> <script src="app/ccsdk/home/appDS2.js"></script> @@ -73,31 +76,20 @@ <script src="app/ccsdk/home/controller-service.js"></script> <script src="app/ccsdk/home/executions-view-controller.js"></script> <script src="app/ccsdk/home/api-docs-controller.js"></script> - <!-- - <script src="app/ccsdk/home/tree-view-controller.js"></script> - <script src="app/ccsdk/home/tree-view-directive.js"></script> - <script src="app/ccsdk/home/oom-instances-controller.js"></script> - <script src="app/ccsdk/home/http-interceptor.js"></script> - --> - <link rel="stylesheet" href="app/ccsdk/home/tree-view-style.css"/> - <link rel="stylesheet" href="app/ccsdk/home/oom-style.css"/> <!-- Cloudify --> - <script src="app/ccsdk/cloudify/blueprint-service.js"></script> <script src="app/ccsdk/cloudify/deployment-service.js"></script> - <script src="app/ccsdk/cloudify/execution-service.js"></script> - <script src="app/ccsdk/cloudify/tosca-table-controller.js"></script> - <script src="app/ccsdk/cloudify/blueprint-controllers.js"></script> <script src="app/ccsdk/cloudify/deployment-controllers.js"></script> - <script src="app/ccsdk/cloudify/execution-table-controller.js"></script> - + <script src="app/ccsdk/cloudify/execution-service.js"></script> + <script src="app/ccsdk/cloudify/plugin-table-controller.js"></script> + <script src="app/ccsdk/cloudify/plugin-service.js"></script> + <!--Inventory--> <script src="app/ccsdk/inventory/blueprint-service.js"></script> - <script src="app/ccsdk/inventory/deployment-service.js"></script> - <script src="app/ccsdk/inventory/execution-service.js"></script> <script src="app/ccsdk/inventory/blueprint-controllers.js"></script> - <script src="app/ccsdk/inventory/deployment-controllers.js"></script> - + <script src="app/ccsdk/inventory/deployment-service.js"></script> + <script src="app/ccsdk/inventory/execution-service.js"></script> + <!-- Consul --> <script src="app/ccsdk/consul/service-health-service.js"></script> <script src="app/ccsdk/consul/service-controllers.js"></script> @@ -106,9 +98,6 @@ <script src="app/ccsdk/consul/node-services-controller.js"></script> <script src="app/ccsdk/consul/datacenter-table-controller.js"></script> <script src="app/ccsdk/consul/datacenter-health-service.js"></script> - - <!-- Ops --> - <script src="app/ccsdk/ops/tabs-view-controller.js"></script> <!-- user admin pages --> <script src="app/fusion/scripts/DS2-services/adminService.js"></script> @@ -127,7 +116,7 @@ <script src="app/fusion/scripts/DS2-controllers/fn-menu-add-popup-controller.js"></script> <!-- main page --> - <script src="app/ccsdk/home/oom-router.js"></script> + <script src="app/ccsdk/home/app-router.js"></script> <style> .csep-root1{ @@ -147,14 +136,12 @@ </head> <body class="appBody" ng-app="abs"> <!-- double quotation marks are required for the popup templates - values are string literals --> - <div ng-include src="'app/ccsdk/home/oom_popup_templates.html'"></div> - <div ng-include src="'app/ccsdk/home/oom_instances_popup.html'"></div> - <div ng-include src="'app/ccsdk/cloudify/blueprint_popups.html'"></div> + <div ng-include src="'app/ccsdk/home/ecd_popup_templates.html'"></div> <div ng-include src="'app/ccsdk/cloudify/deployment_popups.html'"></div> <div ng-include src="'app/ccsdk/inventory/inventory_blueprint_popups.html'"></div> - <div ng-include src="'app/ccsdk/inventory/inventory_deployment_popups.html'"></div> - <div ng-include src="'app/ccsdk/inventory/inventory_execution_popups.html'"></div> - <div ng-include src="'app/ccsdk/consul/service_popups.html'"></div> + <div ng-include src="'app/ccsdk/inventory/inventory_execution_popups.html'"></div> + <div ng-include src="'app/ccsdk/inventory/inventory_deployment_popups.html'"></div> + <div ng-include src="'app/ccsdk/consul/service_popups.html'"></div> <div ng-include src="'app/ccsdk/consul/node_popups.html'"></div> <div ds2-header id="header" class="header-container"></div> <div ds2-menu id="menu-container" class="menu-container"></div> diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/ecomp.png b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/ecomp.png Binary files differnew file mode 100644 index 0000000..b355f10 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/ecomp.png diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_16x16.ico b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_16x16.ico Binary files differnew file mode 100644 index 0000000..8eb0495 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_16x16.ico diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_32x32.ico b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_32x32.ico Binary files differnew file mode 100644 index 0000000..e434286 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_32x32.ico diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_logo_2257x496.png b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_logo_2257x496.png Binary files differnew file mode 100644 index 0000000..36ee1f5 --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_logo_2257x496.png diff --git a/ccsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ecomp-ionicons.css b/ccsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ecomp-ionicons.css index 8a27586..88bab24 100644 --- a/ccsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ecomp-ionicons.css +++ b/ccsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ecomp-ionicons.css @@ -56,7 +56,7 @@ .icon-misc-trash:before, .icon-misc-pen:before, .ion-navicon:before, -.icon-primary-close:before, .close:before, .reset-field:before, +.icon-primary-close:before, .reset-field:before, .icon-datanetwork-softwareasaservice:before, .icon-datanetwork-messaging2:before, .icon-controls-settingsconnectedactivity:before, @@ -184,7 +184,7 @@ .icon-content-star:before { content: "\f24e"; } -.icon-primary-close:before, .close:before, .reset-field:before { content: "\f129"; } +.icon-primary-close:before, .reset-field:before { content: "\f129"; } .icon-datanetwork-softwareasaservice:before { content: "\f40c"; } diff --git a/ccsdk-app-os/src/main/webapp/index.jsp b/ccsdk-app-os/src/main/webapp/index.jsp new file mode 100644 index 0000000..e02bb6b --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/index.jsp @@ -0,0 +1,5 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<%-- Redirected because we can't set the welcome page to a virtual URL. --%> +<%-- Forward to the intended start page to reduce frustration for new users. --%> +<c:redirect url="/ecd"></c:redirect> diff --git a/ccsdk-app-os/src/main/webapp/manifest.jsp b/ccsdk-app-os/src/main/webapp/manifest.jsp new file mode 100644 index 0000000..417825f --- /dev/null +++ b/ccsdk-app-os/src/main/webapp/manifest.jsp @@ -0,0 +1,28 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<% + // Read contents of maven-generated manifest file. + final String path = "/META-INF/MANIFEST.MF"; + java.io.InputStream input = getServletContext().getResourceAsStream(path); + java.io.InputStreamReader reader = new java.io.InputStreamReader(input, "UTF-8"); + char [] buf = new char[1024]; + int length = reader.read(buf, 0, buf.length); + final String manifest = new String(buf, 0, length); + reader.close(); + input.close(); +%> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Manifest</title> +</head> +<body> +<h2> +Contents of file <%= path %>: +</h2> +<pre> +<%= manifest %> +</pre> +</body> +</html> diff --git a/ccsdk-app-overlay/pom.xml b/ccsdk-app-overlay/pom.xml index f6a95cf..d103674 100644 --- a/ccsdk-app-overlay/pom.xml +++ b/ccsdk-app-overlay/pom.xml @@ -6,12 +6,12 @@ <parent> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-parent</artifactId> - <version>1.3.2-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-overlay</artifactId> - <version>1.3.2-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>war</packaging> <name>ONAP Operations Manager Dashboard overlay</name> <description>CCSDK Dashboard web resources</description> @@ -22,9 +22,11 @@ <skiptests>true</skiptests> </properties> + <build> <plugins> <!-- Silence Eclipse warnings by declaring Java 1.8 class output format --> + <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> @@ -34,6 +36,7 @@ <target>1.8</target> </configuration> </plugin> + --> </plugins> </build> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-controllers.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-controllers.js deleted file mode 100644 index c764165..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-controllers.js +++ /dev/null @@ -1,464 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -appDS2.controller('blueprintTableController', function($rootScope, $scope, $log, $modal, modalService, BlueprintService) { - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - // models for controls on screen - $scope.ecdapp.tableData = []; - $scope.ecdapp.currentPageNum = 1; - $scope.ecdapp.viewPerPage = 10; - // other - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; - - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.loadTable = function() { - $scope.ecdapp.isDataLoading = true; - BlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage) - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("blueprintController.loadTable failed: " + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - if (debug) - $log.debug("bluePrintController.loadTable succeeded, size " + jsonObj.data.length); - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $log.error("blueprintController.loadTable failed: " + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - }; - - /** - * Invoked at first page load AND when - * user clicks on the B2B pagination control. - */ - $scope.pageChangeHandler = function(page) { - // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); - $scope.ecdapp.currentPageNum = page; - $scope.ecdapp.loadTable(); - } - - /** - * Shows a modal pop-up with blueprint content. - * Passes data in via an object named "message". - */ - $scope.ecdapp.viewBlueprintModalPopup = function(blueprint) { - $scope.ecdapp.editBlueprint = null; - var modalInstance = $modal.open({ - templateUrl : 'blueprint_view_popup.html', - controller : 'blueprintViewCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-medium', - resolve : { - message : function() { - var dataForPopup = { - blueprint : blueprint - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function() { - // No response. - }); - }; - - /** - * Shows a modal pop-up to upload a blueprint. - * Passes data in via an object named "message". - * On success, updates the table. - */ - $scope.ecdapp.uploadBlueprintModalPopup = function() { - $scope.ecdapp.editBlueprint = null; - var modalInstance = $modal.open({ - templateUrl : 'blueprint_upload_popup.html', - controller : 'blueprintUploadCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-small', - resolve : { - message : function() { - var dataForPopup = { - blueprint : $scope.ecdapp.editBlueprint, - blueprintList : $scope.ecdapp.tableData - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - if (debug) - $log.debug('uploadBlueprintModalPopup: response: ' + JSON.stringify(response)); - if (response == null) { - // $log.debug('user closed dialog'); - } - else { - if (response.error != null) { - $log.error('uploadBlueprintModalPopup failed: ' + response.error); - alert('Failed to upload blueprint:\n' + response.error); - } - else { - // success, get the updated list. - $scope.ecdapp.loadTable(); - } - } - }); - }; - - /** - * Shows a modal pop-up to create a deployment from a blueprint. - * Passes data in via an object named "message". - */ - $scope.ecdapp.deployBlueprintModalPopup = function(blueprint) { - var modalInstance = $modal.open({ - templateUrl : 'blueprint_deploy_popup.html', - controller : 'blueprintDeployCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-medium', - resolve : { - message : function() { - var dataForPopup = { - blueprint : blueprint - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - if (debug) - $log.debug('deployBlueprintModalPopup: response: ' + JSON.stringify(response)); - if (response == null) { - if (debug) - $log.debug('user closed dialog'); - } - else { - if (response.error != null) { - $log.error('deployBlueprintModalPopup failed: ' + response.error); - alert('Failed to deploy blueprint:\n' + response.error); - // No need to update THIS table. - // Must switch to deployments page to see result? Awkward. - } - } - }); - }; - - /** - * Shows a modal pop-up to confirm deletion. - * On successful completion, updates the table. - */ - $scope.ecdapp.deleteBlueprintModalPopup = function(blueprint) { - modalService.popupConfirmWin("Confirm", "Delete blueprint with ID '" - + blueprint.id + "'?", function() { - BlueprintService.deleteBlueprint(blueprint.id).then( - function(response) { - if (debug) - $log.debug('deleteBlueprintModalPopup: response: ' + JSON.stringify(response)); - if (response && response.error) { - // $log.error('deleteBlueprint failed: ' + response.error); - alert('Failed to delete blueprint:\n' + response.error); - } - else { - // No response body on success. - $scope.ecdapp.loadTable(); - } - }, - function(error) { - $log.error('BlueprintService.deleteBlueprint failed: ' + error); - alert('Service failed to delete blueprint:\n' + error); - }); - }); - }; - - // Populate the table on load. Note that the b2b selector code - // sets the page-number value, and the change event calls load table. - // Do not call this here to avoid double load: - // $scope.ecdapp.loadTable(); - -}); - -/*************************************************************************/ - -appDS2.controller('blueprintUploadCtrl', function( - $scope, $log, $modalInstance, message, BlueprintService) { - - 'use strict'; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Upload Blueprint'; - $scope.ecdapp.uploadRequest = - { - blueprint_id : '', - blueprint_filename : '', - zip_url : '' - }; - - /** - * Validates content of user-editable fields. - * Uses the list in message.feedList - * Returns null if all is well, - * a descriptive error message otherwise. - */ - $scope.ecdapp.validateRequest = function(uploadRequest) { - if (uploadRequest == null) - return "No data found.\nPlease enter some values."; - if (uploadRequest.blueprint_id == null || uploadRequest.blueprint_id.trim() === '') - return "ID is required.\nPlease enter a value."; - if (uploadRequest.blueprint_filename == null || uploadRequest.blueprint_filename.trim() === '') - return "File name is required.\nPlease enter a value."; - if (uploadRequest.blueprint_filename.toLowerCase().substr(-4) !== 'yaml') - return "File name must end with YAML.\nPlease use that suffix."; - if (uploadRequest.zip_url == null || uploadRequest.zip_url.trim() === '') - return "Zip file URL is required.\nPlease enter a value."; - return null; - } - - $scope.ecdapp.uploadBlueprint = function(uploadRequest) { - var validateMsg = $scope.ecdapp.validateRequest(uploadRequest); - if (validateMsg != null) { - alert('Invalid upload request:\n' + validateMsg); - return; - } - BlueprintService.uploadBlueprint(uploadRequest) - .then(function(response) { - // $log.debug('blueprintPopupCtrl: response: ' + response); - if (response.error) - alert('Failed to upload blueprint:\n' + response.error); - else - $modalInstance.close(response); - }, - function (error) { - $log.error('blueprintUploadCtrl: error while uploading: ' + error); - alert('Server rejected upload request:\n' + error); - } - ); - - }; - -}); - -/*************************************************************************/ - -appDS2.controller('blueprintViewCtrl', function( - $scope, $log, message, BlueprintService) { - - 'use strict'; - - var debug = false; - - if (debug) - $log.debug("blueprintViewCtrl.message: " + JSON.stringify(message)); - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.blueprintId = message.blueprint.id; - - $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.id; - - // Fetch the blueprint - $scope.ecdapp.isDataLoading = true; - BlueprintService.viewBlueprint(message.blueprint.id).then(function(jsonObj) { - if (debug) - $log.debug("blueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed'; - } - else { - $scope.ecdapp.blueprint = jsonObj.content; - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $scope.ecdapp.isDataLoading = false; - alert('Failed to get blueprint. Please retry.'); - $log.error("blueprintViewCtrl failed: " + error); - }); - -}); - - -/*************************************************************************/ - -appDS2.controller('blueprintDeployCtrl', function( - $scope, $log, $modalInstance, message, DeploymentService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Deploy Blueprint'; - - // Cache the input parameter names for validation - if (debug) - $log.debug('blueprintDeployCtrl: inputs: ' + JSON.stringify(message.blueprint.plan.inputs)); - $scope.ecdapp.inputsDict = message.blueprint.plan.inputs; - - // Copy the input parameter names and default values - let inputsAndDefaults = {}; - for (var pkey in message.blueprint.plan.inputs) { - if (debug) - $log.debug('blueprintDeployCtrl: checking key ' + pkey); - let dval = message.blueprint.plan.inputs[pkey].default; - if (! dval) - dval = ''; - inputsAndDefaults[pkey] = dval; - } - if (debug) - $log.debug('blueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults)); - - // Create an object for edit - $scope.ecdapp.editRequest = { - deployment_id : '', - blueprint_id : message.blueprint.id, - fileModel : null, - parmFileDict : inputsAndDefaults - }; - - /** - * Handler for file-read event reads file, parses YAML, validates content. - */ - var fileReader = new FileReader(); - fileReader.onload = function(event) { - let yamlString = fileReader.result; - if (debug) - $log.debug('fileReader.onload: read: ' + yamlString); - let ydict = {}; - try { - ydict = YAML.parse(yamlString); - } - catch (ex) { - alert('Failed to parse file as YAML:\n' + ex); - } - // Process the file - for (var ykey in ydict) { - let yval = ydict[ykey]; - if (debug) - $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); - // Allow only expected keys with scalar values - if (! (ykey in $scope.ecdapp.editRequest.parmFileDict)) - alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey); - else if (typeof yval !== 'string' && typeof yval !== 'number') - alert('Unexpected file content:\nNot a simple key-value pair:\n' + ykey); - else - $scope.ecdapp.editRequest.parmFileDict[ykey] = yval; - } - if (debug) - $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict)); - - // Update table in all cases - $scope.$apply(); - } - - // Handler for file-select event - $scope.handleFileSelect = function() { - if (debug) - $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); - fileReader.readAsText($scope.ecdapp.editRequest.fileModel); - }; - - /** - * Validates content of user-editable fields. - * Returns null if all is well, - * a descriptive error message otherwise. - */ - $scope.ecdapp.validateRequest = function(editRequest) { - if (editRequest == null) - return 'No data found.\nPlease enter some values.'; - if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '') - return 'Deployment ID is required.\nPlease enter a value.'; - if (editRequest.blueprint_id == null || editRequest.blueprint_id.trim() == '') - return 'Blueprint ID is required.\nPlease enter a value.'; - // Check that every file parameter is defined by blueprint - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) { - // Defined in blueprint? - if (! $scope.ecdapp.inputsDict[pkey]) - return 'Unexpected input parameter\n' + pkey; - // Populated? - let parmVal = $scope.ecdapp.editRequest.parmFileDict[pkey]; - if (parmVal == null || (typeof (parmVal) === 'string' && parmVal.trim().length == 0)) - return 'Missing value for parameter\n' + pkey; - } - // Check that a value is supplied for every expected input - for (var bkey in $scope.ecdapp.inputsDict) { - if (! $scope.ecdapp.editRequest.parmFileDict[bkey]) - return 'Missing input parameter\n' + bkey; - } - return null; - } - - $scope.ecdapp.deployBlueprint = function(editRequest) { - if (debug) - $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest)); - var validateMsg = $scope.ecdapp.validateRequest(editRequest); - if (validateMsg != null) { - alert('Invalid Request:\n' + validateMsg); - return; - } - // Create request with key:value parameters dictionary - let deployRequest = { - deployment_id : editRequest.deployment_id, - blueprint_id : editRequest.blueprint_id, - parameters : {} - }; - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) - deployRequest.parameters[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey]; - if (debug) - $log.debug('deployBlueprint: deployRequest is ' + JSON.stringify(deployRequest)); - - DeploymentService.deployBlueprint(deployRequest) - .then(function(response) { - if (response.error) - alert('Failed to deploy blueprint:\n' + response.error); - else - $modalInstance.close(response); - }, - function (error) { - $log.error('blueprintDeployCtrl: error while deploying: ' + error); - alert('Server rejected deployment request:\n' + error); - } - ); - - }; - -}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-service.js deleted file mode 100644 index f058b09..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-service.js +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -appDS2.factory('BlueprintService', function ($http, $q, $log) { - return { - /** - * Gets one page of blue prints objects. - * @param {Number} pageNum - page number; e.g., 1 - * @param {Number} viewPerPage - number of items per page; e.g., 25 - * @return {JSON} Response object from remote side - */ - getBlueprints: function(pageNum,viewPerPage) { - // cache control for IE - let cc = "&cc=" + new Date().getTime().toString(); - let url = 'blueprints?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc; - return $http({ - method: 'GET', - url: url, - cache: false, - responseType: 'json' - }).then(function(response) { - if (response.data == null || typeof response.data != 'object') - return $q.reject('BlueprintService.getBlueprints: response.data null or not object'); - else - return response.data; - }, - function(error) { - $log.error('BlueprintService.getBlueprints failed: ' + JSON.stringify(error)); - return $q.reject(error.statusText); - }); - }, - - /** - * Gets blueprint content. - * @return {JSON} Response object from remote side - */ - viewBlueprint: function(id) { - // cache control for IE - let url = 'viewblueprints/' + id; - return $http({ - method: 'GET', - url: url, - cache: false, - responseType: 'json' - }).then(function(response) { - if (response.data == null || typeof response.data != 'object') - return $q.reject('BlueprintService.viewBlueprint: response.data null or not object'); - else - return response.data; - }, - function(error) { - $log.error('BlueprintService.viewBlueprint failed: ' + JSON.stringify(error)); - return $q.reject(error.statusText); - }); - }, - - uploadBlueprint: function(uploadRequest) { - let url = 'blueprints'; - return $http({ - method: 'POST', - url: url, - data: uploadRequest, - responseType: 'json' - }).then(function(response) { - if (response.data == null || typeof response.data != 'object') - return $q.reject('BlueprintService.uploadBlueprint: response.data null or not object'); - else - return response.data; - }, - function(error) { - $log.error('BlueprintService.uploadBlueprint failed: ' + JSON.stringify(error)); - return $q.reject(error.statusText); - }); - }, - - deleteBlueprint: function(id) { - let url = 'blueprints/' + id; - return $http({ - method: 'DELETE', - url: url, - cache: false, - responseType: 'json' - }).then(function(response) { - // This is called on response code 200..299. - // On success, response.data is null. - // On failure, response.data has an error message. - return response.data; - }, - function(error) { - $log.error('BlueprintService.deleteBlueprint failed: ' + JSON.stringify(error)); - return $q.reject(error.statusText); - }); - } - - }; -}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_popups.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_popups.html deleted file mode 100644 index ee92d84..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_popups.html +++ /dev/null @@ -1,187 +0,0 @@ -<script type="text/ng-template" id="blueprint_upload_popup.html"> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="blueprintId">*Blueprint ID</label> - <div class="field-group"> - <!--autofocus is HTML5 attribute; doesn't work in Firefox--> - <input id="blueprintId" class="span12" type="text" data-ng-model="ecdapp.editBlueprint.blueprint_id" autofocus> - </div> - </div> - </div> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="blueprintFileName">*File Name</label> - <div class="field-group"> - <input id="blueprintFileName" class="span12" type="text" data-ng-model="ecdapp.editBlueprint.blueprint_filename"> - </div> - </div> - </div> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="zipFileUrl">*Zip File URL</label> - <div class="field-group"> - <input id="zipFileUrl" class="span12" type="text" data-ng-model="ecdapp.editBlueprint.zip_url"> - </div> - </div> - </div> - </div> - - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.uploadBlueprint(ecdapp.editBlueprint);"> - Save - </button> - <button class="btn btn-small" type="button" - ng-click="$dismiss('cancel')"> - Cancel - </button> - </div> - </div> - -</script> - -<script type="text/ng-template" id="blueprint_view_popup.html"> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-show="ecdapp.errMsg"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.errMsg"> - <pre>{{ecdapp.blueprint}}</pre> - </div> - - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="$dismiss('cancel');"> - Close - </button> - </div> - </div> - -</script> - -<script type="text/ng-template" id="blueprint_deploy_popup.html"> - - <style> - .ecd-parameter-table - { - border: 1px; - overflow: auto; - } - .ecd-parameter-table th - { - font-size: 1.4rem; - } - </style> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <div class="row-nowrap"> - <div class="span12"> - <label for="blueprintFileName">*Deployment ID</label> - <!--autofocus is HTML5 attribute; doesn't work in Firefox--> - <input id="blueprintFileName" class="span12" type="text" data-ng-model="ecdapp.editRequest.deployment_id" autofocus/> - </div> - <div class="span12"> - <label for="blueprintId">Blueprint ID</label> - <!--not editable--> - <input id="blueprintId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.editRequest.blueprint_id"/> - </div> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="parameters">*Parameters</label> - <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center"> - <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" > - Drag & drop a parameters YAML file here, or click to browse. - </span> - </div> - </div> - <div class="ecd-parameter-table"> - <table id="parameters"> - <tr id="ecd-table-header"> - <th width="40%">Name</th> - <th width="60%">Value</th> - </tr> - <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict"> - <tr id="tr-rowData"> - <td ng-bind="pkey"/> - <td ng-bind="pval"/> - </tr> - </tbody> - </table> - </div> - </div> - </div> - - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.deployBlueprint(ecdapp.editRequest);"> - Save - </button> - <button class="btn btn-small" type="button" - ng-click="$dismiss('cancel')"> - Cancel - </button> - </div> - </div> - -</script> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_table.html deleted file mode 100644 index 3ce60b9..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_table.html +++ /dev/null @@ -1,98 +0,0 @@ -<div id="page-content"> - - <h1 class="heading-page" id="blueprints-page">Blueprints</h1> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-hide="ecdapp.isDataLoading"> - - <div id="button-search-row"> - <button class="btn btn-alt btn-small" - type="submit" - ng-click="ecdapp.uploadBlueprintModalPopup();"> - Upload Blueprint... - </button> - <div style="float:right;"> - <div class="form-field form-field__small"> - <input - type="text" - placeholder="Search Blueprints" - ng-model="ecdapp.searchString"/> - </div> - </div> - </div> - - <div ng-show="ecdapp.isRequestFailed"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.isRequestFailed"> - - <div - b2b-table - id="blueprints-table" - class="b2b-table-div" - table-data="ecdapp.tableData" - search-string="ecdapp.searchString" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - - <table> - - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header key="id">ID</th> - <th b2b-table-header key="main_file_name">File Name</th> - <th b2b-table-header key="description">Description</th> - <th b2b-table-header key="created_at">Created Date</th> - <th b2b-table-header key="updated_at">Updated Date</th> - <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> - </tr> - </thead> - - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData"> - <tr id="tr-rowData"> - <td b2b-table-body - ng-bind="rowData.id"/> - <td b2b-table-body - ng-bind="rowData.main_file_name"/> - <td b2b-table-body - ng-bind="rowData.description"/> - <td b2b-table-body - ng-bind="rowData.created_at"/> - <td b2b-table-body - ng-bind="rowData.updated_at"/> - <td b2b-table-body> - <div ng-click="ecdapp.viewBlueprintModalPopup(rowData);"> - <a href="" title="View blueprint" class="icon-people-preview ecd-icon-action"></a> - </div> - <div ng-click="ecdapp.deployBlueprintModalPopup(rowData);"> - <a href="" title="Deploy blueprint" class="icon-datanetwork-cloudupload ecd-icon-action"></a> - </div> - <div ng-click="ecdapp.deleteBlueprintModalPopup(rowData);"> - <a href="" title="Delete blueprint" class="icon-misc-trash ecd-icon-action"></a> - </div> - </td> - </tr> - </tbody> - </table> - </div> - - <div b2b-pagination="" total-pages="ecdapp.totalPages" - current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler" - role="navigation"> - </div> - - <div style="height: 10px;"> - <!-- space between page number and black footer --> - </div> - - </div><!-- loading --> - -</div><!-- page content --> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-controllers.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-controllers.js index 1e80082..f89ce76 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-controllers.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-controllers.js @@ -1,26 +1,6 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ appDS2.controller('deploymentTableController', function( - $rootScope, $scope, $log, $modal, DeploymentService) { + $rootScope, $scope, $log, $modal, $routeParams, DeploymentService, ControllerService, + InventoryDeploymentService, localStorageService, $interval) { 'use strict'; @@ -36,17 +16,469 @@ appDS2.controller('deploymentTableController', function( // other $scope.ecdapp.errMsg = null; $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.useCache = true; + $scope.ecdapp.groupByTenant = false; + $scope.ecdapp.filterByUser = true; + $scope.ecdapp.cache_switch = { + value: true + }; + $scope.ecdapp.getTenants = function() { + ControllerService.getTenants() + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("blueprintController.getTenants failed: " + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + var tenants = []; + for (var tenIndx = 0; tenIndx < jsonObj.items.length; tenIndx++) { + tenants.push(jsonObj.items[tenIndx].name); + } + $scope.ecdapp.availableTenants = tenants; + if ($scope.ecdapp.availableTenants != undefined) { + $scope.ecdapp.selectedTenant = $scope.ecdapp.availableTenants[0]; + } + localStorageService.set('tenants', JSON.stringify(tenants)); + } + }, function(error) { + $log.error("blueprintController.getTenants failed: " + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + }); + }; + + $scope.ecdapp.availableTenants = JSON.parse(localStorageService.get('tenants')); + if ($scope.ecdapp.availableTenants == undefined) { + $scope.ecdapp.getTenants(); + } else { + //$scope.ecdapp.selectedTenant = $scope.ecdapp.availableTenants[0]; + $scope.ecdapp.selectedTenant = ''; + } + // searching + $scope.ecdapp.searchBy = $routeParams.depId; + if ($scope.ecdapp.searchBy == undefined) { + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + + "cache:" + $scope.ecdapp.useCache + ";" +"owner:" + $scope.userId + ";"; + //+ "user:" + $scope.ecdapp.filterByUser + ";"; + } else { + if ($scope.ecdapp.searchBy.includes("owner")) { + if ($scope.ecdapp.searchBy.split(":")[1] === "group") { + $scope.ecdapp.filterByUser = false; + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + + "cache:" + $scope.ecdapp.useCache + ";"; + } + } else { + $scope.ecdapp.selectedTenant = $scope.ecdapp.searchBy.split(";")[0].split(":")[1] + } + } + //$scope.ecdapp.selectedTenant = "default_tenant"; + //if ($scope.ecdapp.availableTenants != undefined) { + // $scope.ecdapp.selectedTenant = $scope.ecdapp.availableTenants[0]; + //} + + // sorting + $scope.ecdapp.sortBy = null; + + $scope.ecdapp.isDisabled = false; + $scope.ecdapp.isDetailView = false; + $scope.ecdapp.isHelmType = false; + $scope.ecdapp.aafUsernameString; + $scope.ecdapp.dcaeTargetTypeString; + $scope.ecdapp.selectedSrvc; + $scope.ecdapp.usingAafFilter = false; + $scope.ecdapp.usingDcaeTargetTypeFilter = false; + $scope.ecdapp.selectedOwner; + $scope.ecdapp.availableServices; // = JSON.parse(localStorageService.get('deplNames')); + $scope.ecdapp.selectedServices; + $scope.ecdapp.bpOwners = JSON.parse(localStorageService.get('bpOwners')); + + $scope.ecdapp.availableStatus = + ['pending','started','cancelling','force_cancelling','cancelled','terminated','failed']; + $scope.ecdapp.selectedStatus; + + $scope.ecdapp.showingMoreFilters = false; + + $scope.ecdapp.toggleMoreFilters = function() { + $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters; + }; + + + // Handler for disabling non aaf/dcae target type search fields + $scope.ecdapp.handleDisableOtherFields = function() { + //If using aaf filter, disable others + //and clear the dcae target type field + if ($scope.ecdapp.aafUsernameString == '' || typeof $scope.ecdapp.aafUsernameString == "undefined") + $scope.ecdapp.usingAafFilter = false; + else { + $scope.ecdapp.usingAafFilter = true; + $scope.ecdapp.dcaeTargetTypeString = ''; + } + + //If using dcae target type filter, disable others + //and clear the aaf filter field + if ($scope.ecdapp.dcaeTargetTypeString == '' || typeof $scope.ecdapp.dcaeTargetTypeString == "undefined") + $scope.ecdapp.usingDcaeTargetTypeFilter = false; + else { + $scope.ecdapp.usingDcaeTargetTypeFilter = true; + $scope.ecdapp.aafUsernameString = ''; + } + }; + + // get the blueprints summary list + $scope.ecdapp.bp = []; + $scope.ecdapp.getAllAuthBpList = function() { + InventoryBlueprintService.getBlueprintsSummary() + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + jsonObj.error); + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.bp = []; + } else { + $scope.ecdapp.errMsg = null; + $scope.ecdapp.bp = jsonObj; + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + error); + $scope.ecdapp.errMsg = error; + $scope.ecdapp.bp = []; + $scope.ecdapp.isDataLoading = false; + }); + }; + + $scope.ecdapp.getDeploymentsList = function() { + InventoryDeploymentService.getDeploymentList($scope.ecdapp.searchBy).then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryDeploymentController.getDeploymentList failed: " + + jsonObj.error); + $scope.ecdapp.availableServices = []; + } else { + //localStorageService.set('deplNames', JSON.stringify(jsonObj)); + $scope.ecdapp.availableServices = jsonObj; + //JSON.parse(localStorageService.get('deplNames')); + } + }, + function(error) { + $log.error("inventoryDeploymentController.getDeploymentList failed: " + + error); + $scope.ecdapp.availableServices = []; + }); + }; + + $scope.ecdapp.reloadTable = function() { + $scope.ecdapp.currentPageNum = 1; + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + +"cache:" + $scope.ecdapp.useCache + ";"; + //+ "user:" + $scope.ecdapp.filterByUser + ";"; + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";"; + } + $scope.ecdapp.searchString = ''; + $scope.ecdapp.resetFilters(); + $scope.ecdapp.loadTable(); + }; + + $scope.ecdapp.resetFilters = function() { + $scope.ecdapp.selectedServices = ''; + $scope.ecdapp.selectedTenants = ''; + $scope.ecdapp.selectedStatus = ''; + $scope.ecdapp.selectedOwner = ''; + $scope.ecdapp.isHelmType = false; + $scope.ecdapp.searchString = ''; + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + +"cache:" + $scope.ecdapp.useCache + ";"; + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";"; + } + /* + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + +"cache:" + $scope.ecdapp.useCache + ";"+ "user:" + $scope.ecdapp.filterByUser + ";"; + */ + }; + $scope.ecdapp.filterBySvc = function() { + if ( typeof $scope.ecdapp.searchString != "undefined" && + $scope.ecdapp.searchString != '') { + if ($scope.ecdapp.searchString.includes("serviceRef:") || + $scope.ecdapp.searchString.includes("tenant:") || + $scope.ecdapp.searchString.includes("status:") || + $scope.ecdapp.searchString.includes("helm:")) { + $scope.ecdapp.searchBy = $scope.ecdapp.searchString +";cache:" + $scope.ecdapp.useCache + ";"; + // + "user:" + $scope.ecdapp.filterByUser + ";"; + } else { + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + $scope.ecdapp.searchBy += 'serviceRef:' + $scope.ecdapp.searchString +";cache:" + $scope.ecdapp.useCache + ";"; + //+ "user:" + $scope.ecdapp.filterByUser + ";"; + } + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";"; + } + $scope.ecdapp.searchTable(); + } + }; + + $scope.ecdapp.extendedfilterSrch = function() { + /* + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + + "cache:" + $scope.ecdapp.useCache + ";" + "user:" + $scope.ecdapp.filterByUser + ";"; + * + */ + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + + "cache:" + $scope.ecdapp.useCache + ";"; + + if ( typeof $scope.ecdapp.selectedServices != "undefined" && + $scope.ecdapp.selectedServices != '') { + var svcFilterStr = 'serviceRef:' + $scope.ecdapp.selectedServices.toString(); + $scope.ecdapp.searchBy += svcFilterStr + ";" + } + if ( typeof $scope.ecdapp.selectedOwner != "undefined" && + $scope.ecdapp.selectedOwner != '') { + var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString(); + $scope.ecdapp.searchBy += ownerFilterStr + ';' + } + if ( typeof $scope.ecdapp.selectedStatus != "undefined" && + $scope.ecdapp.selectedStatus != '') { + var statusFilterStr = 'status:' + $scope.ecdapp.selectedStatus.toString(); + $scope.ecdapp.searchBy += statusFilterStr + ';' + } + if ( typeof $scope.ecdapp.isHelmType != "undefined" && + $scope.ecdapp.isHelmType == true) { + var helmFilterStr = 'helm:' + $scope.ecdapp.isHelmType; + $scope.ecdapp.searchBy += helmFilterStr + ';' + } + + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";"; + } + //If using AAF username filter, ignore other fields and do filtered search. + if ($scope.ecdapp.usingAafFilter) { + var aafFilterStr = 'aafUsername:' + $scope.ecdapp.aafUsernameString.toString(); + $scope.ecdapp.searchBy = $scope.ecdapp.aafUsernameString.toString(); + $scope.ecdapp.searchString = aafFilterStr + ';'; + $scope.ecdapp.searchTableAafFilter(); + } + else if ($scope.ecdapp.usingDcaeTargetTypeFilter) { + var dcaeTargetTypeFilterStr = 'dcaeTargetType:' + $scope.ecdapp.dcaeTargetTypeString.toString(); + $scope.ecdapp.searchBy = $scope.ecdapp.dcaeTargetTypeString.toString(); + $scope.ecdapp.searchString = dcaeTargetTypeFilterStr + ';'; + $scope.ecdapp.searchTableDcaeTargetTypeFilter(); + } + else { + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + $scope.ecdapp.searchTable(); + } + }; + + $scope.ecdapp.sortTable = function(sortBy) { + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.sortBy = sortBy; + DeploymentService.getDeployments($scope.ecdapp.currentPageNum, + $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy).then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("DeploymentController.sortTable failed: " + + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.tableData = jsonObj.items; + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error("DeploymentController.sortTable failed: " + + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + }); + }; + /** + * Loads the table. Interprets the remote controller's response and copies + * to scope variables. The response is either a list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.searchTable = function() { + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.showingMoreFilters = false; + if ($scope.ecdapp.currentPageNum != 1) { + $scope.ecdapp.currentPageNum = 1; + } else { + $scope.ecdapp.stopLoading(); + DeploymentService.getDeployments($scope.ecdapp.currentPageNum, + $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy).then( + function(jsonObj) { + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false); + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + if (jsonObj.error) { + $log.error("DeploymentController.loadTable failed: " + + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.tableData = jsonObj.items; + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + $scope.ecdapp.searchBy = ''; + $log.error("DeploymentController.loadTable failed: " + + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + }); + } + }; + + /** + * Loads the table with AAF Filter. Interprets the remote controller's response and copies + * to scope variables. The response is either a list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.searchTableAafFilter = function() { + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.showingMoreFilters = false; + if ($scope.ecdapp.currentPageNum != 1) { + $scope.ecdapp.currentPageNum = 1; + } else { + $scope.ecdapp.stopLoading(); + InventoryDeploymentService.getDeploymentsAafFilter($scope.ecdapp.currentPageNum, + $scope.ecdapp.viewPerPage, $scope.ecdapp.searchBy).then( + function(jsonObj) { + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false); + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + if (jsonObj.error) { + $log.error("inventoryDeploymentController.loadTable failed: " + + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.tableData = jsonObj.items; + //$scope.ecdapp.updateTable(); + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + $scope.ecdapp.searchBy = ''; + $log.error("inventoryDeploymentController.loadTable failed: " + + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + }); + } + }; + + /** + * Loads the table with Dcae target type Filter. Interprets the remote controller's response and copies + * to scope variables. The response is either a list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.searchTableDcaeTargetTypeFilter = function() { + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.showingMoreFilters = false; + if ($scope.ecdapp.currentPageNum != 1) { + $scope.ecdapp.currentPageNum = 1; + } else { + $scope.ecdapp.stopLoading(); + InventoryDeploymentService.getDeploymentsDcaeTargetTypeFilter($scope.ecdapp.currentPageNum, + $scope.ecdapp.viewPerPage, $scope.ecdapp.searchBy).then( + function(jsonObj) { + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false); + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + if (jsonObj.error) { + $log.error("inventoryDeploymentController.loadTable failed: " + + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.tableData = jsonObj.items; + //$scope.ecdapp.updateTable(); + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + $scope.ecdapp.searchBy = ''; + $log.error("inventoryDeploymentController.loadTable failed: " + + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + }); + } + }; + $scope.ecdapp.stopLoading = function() { + if (angular.isDefined(stop)) { + $interval.cancel(stop); + stop = undefined; + } + }; + + $scope.ecdapp.toggleRefresh = function() { + if ($scope.ecdapp.useCache === true) { + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false); + } else { + $scope.ecdapp.stopLoading(); + } + }; + + if ($scope.ecdapp.useCache === true) { + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false); + } + + $scope.ecdapp.toggleUserFilt = function() { + if ($scope.ecdapp.filterByUser === true) { + $scope.ecdapp.groupByTenant = false; + $scope.ecdapp.selectedTenant = ''; + } else { + $scope.ecdapp.searchString = ''; + } + $scope.ecdapp.reloadTable(); + } + + $scope.ecdapp.toggleTenantFilt = function() { + if ($scope.ecdapp.groupByTenant === false) { + $scope.ecdapp.selectedTenant = ''; + } + } /** * Loads the table. Interprets the remote controller's response and copies * to scope variables. The response is either a list to be assigned to * tableData, or an error to be shown. */ - $scope.ecdapp.loadTable = function() { + $scope.ecdapp.loadTable = function(sortBy, searchBy) { $scope.ecdapp.isDataLoading = true; + //$scope.ecdapp.searchString = ''; + $scope.ecdapp.sortBy = sortBy; DeploymentService.getDeployments($scope.ecdapp.currentPageNum, - $scope.ecdapp.viewPerPage).then( + $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy).then( function(jsonObj) { if (jsonObj.error) { $log.error("deploymentController.loadTable failed: " @@ -69,7 +501,13 @@ appDS2.controller('deploymentTableController', function( $scope.ecdapp.errMsg = error; $scope.ecdapp.tableData = []; $scope.ecdapp.isDataLoading = false; + var loc = location.pathname; + var loc1 = loc.replace("/", ""); + var loc2 = loc1.replace("/ecd", "/login.htm"); + alert("Session expired - Sign in again"); + location.replace("/"+loc2); }); + $scope.ecdapp.getDeploymentsList(); }; /** @@ -79,9 +517,186 @@ appDS2.controller('deploymentTableController', function( $scope.pageChangeHandler = function(page) { // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); $scope.ecdapp.currentPageNum = page; - $scope.ecdapp.loadTable(); + //$scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";"; + $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy); } + $scope.ecdapp.tenantChangeHandler = function() { + $scope.ecdapp.currentPageNum = 1; + $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + +"cache:" + $scope.ecdapp.useCache + ";"; + //+ "user:" + $scope.ecdapp.filterByUser + ";"; + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";"; + } + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy); + } + + //$scope.ecdapp.getTenants(); + + /** + * modal pop-up for app reconfig operation + * + */ + $scope.ecdapp.reconfigDeploymentModalPopup = function(deployment) { + var modalInstance = $modal.open({ + templateUrl : 'app_reconfig_view_popup.html', + controller : 'appReconfigCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + deployment : deployment + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + // No response. + }); + }; + + /** + * Shows a modal pop-up to confirm deletion. + * On successful completion, updates the table. + */ + $scope.ecdapp.deleteDeploymentModalPopup = function(deployment) { + deployment.onlyLatest = true; + var modalInstance = $modal.open({ + templateUrl : 'inventory_deployment_delete_popup.html', + controller : 'deploymentDeleteCtrl', + sizeClass: 'modal-small', + resolve : { + message : function() { + var dataForPopup = { + deployment : deployment, + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + if (debug) + $log.debug('deleteDeploymentPopup: response: ' + JSON.stringify(response)); + if (response == null) { + // $log.debug('user closed dialog'); + } + else { + if (response.error != null) { + $log.error('deleteDeploymentModalPopup failed: ' + response.error); + alert('Failed to delete deployment:\n' + response.error); + } + else { + $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment); + } + } + }); + }; + + /** + * Shows a modal pop-up with executions for a deployment. + * Passes data in via an object named "deployment". + */ + $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) { + var modalInstance = $modal.open({ + templateUrl : 'inventory_execution_view_popup.html', + controller : 'deploymentExecutionsViewCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + deployment : deployment + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + // No response. + }); + }; + + + $scope.ecdapp.viewDeploymentInputsModalPopup = function(deployment) { + var modalInstance = $modal.open({ + templateUrl : 'inventory_deployment_inputs_view_popup.html', + controller : 'deploymentInputsViewCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + deployment : deployment + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + // No response. + }); + }; + + /** + * Shows a modal pop-up to initiate update blueprint for a deployment + */ + $scope.ecdapp.updateDeploymentModalPopup = function(deployment) { + var modalInstance = $modal.open({ + templateUrl: 'inventory_deployment_update_popup.html', + controller: 'deploymentUpdateCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve: { + message: function() { + var dataForPopup = { + deployment : deployment + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + if (response != null) { + if (response.error != null) { + $log.error('updateDeploymentModalPopup failed: ' + response.error); + alert('Failed to update deployment:\n' + response.error); + } + else { + $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment); + } + } + }); + }; + + /** + * Shows a modal pop-up with blueprint content. + * Passes data in via an object named "message". + */ + $scope.ecdapp.getBlueprintDataModal = function(deployment) { + var modalInstance = $modal.open({ + templateUrl : 'blueprint_content_popup.html', + controller : 'deployBlueprintContentCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + blueprint : deployment, + tenant_name: $scope.ecdapp.selectedTenant + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + }); + }; + + /** * Shows a modal pop-up to create an execution from a deployment. * Passes data in via an object named "message". @@ -96,7 +711,7 @@ appDS2.controller('deploymentTableController', function( resolve : { message : function() { var dataForPopup = { - deployment : deployment + deployment : deployment, }; return dataForPopup; } @@ -119,253 +734,1480 @@ appDS2.controller('deploymentTableController', function( }); }; - /** - * Shows a modal pop-up to confirm deletion. - * On successful completion, updates the table. - */ - $scope.ecdapp.deleteDeploymentModalPopup = function(deployment) { - var modalInstance = $modal.open({ - templateUrl : 'deployment_delete_popup.html', - controller : 'deploymentDeleteCtrl', - sizeClass: 'modal-small', - resolve : { - message : function() { - var dataForPopup = { - deployment : deployment - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - if (debug) - $log.debug('deleteDeploymentPopup: response: ' + JSON.stringify(response)); - if (response == null) { - // $log.debug('user closed dialog'); - } - else { - if (response.error != null) { - $log.error('deleteDeploymentModalPopup failed: ' + response.error); - alert('Failed to delete deployment:\n' + response.error); - } - else { - // success, get the updated list. - $scope.ecdapp.loadTable() - } - } - }); - }; + $scope.ecdapp.checkHelmStatus = function(deployment) { + var selTenant = deployment.tenant_name; + if ( typeof selTenant === "undefined" ) { + selTenant = "default_tenant"; + } + deployment.onlyLatest = true; + + // This object holds data for this operation + $scope.ecdapp.helmStatusRequest = { + "deployment_id": deployment.id, + "workflow_name": "status", + "tenant": selTenant + }; + InventoryDeploymentService.helmStatusFlow($scope.ecdapp.helmStatusRequest).then(function(jsonObj) { + if (debug) + $log.debug("checkHelmStatus response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; + $scope.ecdapp.updatingDeployment = false; + $scope.ecdapp.isDataLoading = false; + alert('Request Failed: ' + jsonObj.error); + } else { + console.log('%c POSTED helm status request', 'color: magenta; font-weight: bold;'); + $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment); + } + }, function(error) { + $log.error('helmStatusFlow failed: ' + error); + alert('helmStatusFlow failed: ' + error); + }); + + }; + + /** + * Shows a modal pop-up to initiate helm upgrade for a deployment + */ + $scope.ecdapp.upgradeDeploymentModalPopup = function(deployment) { + //console.log(deployment); + var modalInstance = $modal.open({ + templateUrl: 'inventory_deployment_upgrade_popup.html', + controller: 'deploymentUpgradeCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve: { + message: function() { + var dataForPopup = { + deployment : deployment + }; + return dataForPopup; + } + } + }); + }; + + /** + * Shows a modal pop-up to initiate helm rollback for a deployment + */ + $scope.ecdapp.rollbackDeploymentModalPopup = function(deployment) { + var modalInstance = $modal.open({ + templateUrl: 'inventory_deployment_rollback_popup.html', + controller: 'deploymentRollbackCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve: { + message: function() { + var dataForPopup = { + deployment : deployment + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + // No response. + }); + }; + $scope.$on('$destroy', function() { + // Make sure that the interval is destroyed too + $scope.ecdapp.stopLoading(); + }); + }); /*************************************************************************/ appDS2.controller('deploymentDeleteCtrl', function( - $scope, $log, $modalInstance, message, DeploymentService) { + $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { - 'use strict'; - - // Controls logging in this controller - var debug = false; + 'use strict'; - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Delete Deployment'; - $scope.ecdapp.deploymentId = message.deployment.id; - $scope.ecdapp.ignoreLiveNodes = false; - - $scope.ecdapp.deleteDeploymentById = function(){ - DeploymentService.deleteDeployment($scope.ecdapp.deploymentId, $scope.ecdapp.ignoreLiveNodes).then( - function(response) { - if (debug) - $log.debug('deploymentDeleteCtrl.deleteDeployment: ' + JSON.stringify(response)); - if (response && response.error) { - $log.error('DeploymentService.deleteDeployment failed: ' + response.error); - alert('Failed to delete deployment:\n' + response.error); - } - else { - // Delete service returns null on success. - $modalInstance.close("success"); - } - }, - function(error) { - $log.error('DeploymentService.deleteDeployment failed: ' + error); - alert('Service failed to delete deployment:\n' + error); - }); - } + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'Undeploy?'; + $scope.ecdapp.deploymentRef = message.deployment.id; + var selTenant = message.deployment.tenant_name; + $scope.ecdapp.ui_tenant = selTenant; + $scope.ecdapp.tenant = selTenant; + + $scope.ecdapp.deleteDeploymentById = function(){ + $scope.ecdapp.isDisabled = true; + InventoryDeploymentService.deleteDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then( + function(response) { + if (debug) + $log.debug('inventoryDeploymentDeleteCtrl.deleteDeployment: ' + JSON.stringify(response)); + if (response && response.error) { + $log.error('InventoryDeploymentService.deleteDeployment failed: ' + response.error); + alert('Failed to delete deployment:\n' + response.error); + } + else { + // Delete service returns null on success. + $modalInstance.close("success"); + } + }, + function(error) { + $log.error('InventoryDeploymentService.deleteDeployment failed: ' + error); + alert('Service failed to delete deployment:\n' + error); + }); + } }); /*************************************************************************/ -appDS2.controller('deploymentExecuteCtrl', function( - $scope, $log, $modalInstance, message, ExecutionService) { +appDS2.controller('deploymentExecutionsViewCtrl', function( + $scope, $rootScope, $interval, $log, $modalInstance, message, modalService, InventoryExecutionService, ExecutionService) { - 'use strict'; - - // Controls logging in this controller - var debug = false; + 'use strict'; - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Execute Deployment'; - - // Cache the input parameter names for validation - $scope.ecdapp.inputsDict = {}; - if (debug) - $log.debug('DeploymentXeqCtrl: inputsDict is ' + JSON.stringify($scope.ecdapp.inputsDict)); - - // Copy the input names and values - // (different structure than blueprint) - /*for (var pkey in message.deployment.inputs) { - let dval = message.deployment.inputs[pkey]; - inputsAndValues[pkey] = dval; - }*/ - - // Gather workflow names as a simple list - var workflowList = []; - for (var i = 0; i < message.deployment.workflows.length; i++) - workflowList.push(message.deployment.workflows[i].name); - if (debug) - $log.debug('DeploymentXeqCtrl: workflowList is ' + JSON.stringify(workflowList)); - - // Create an object for edit. - $scope.ecdapp.editRequest = { - deployment_id : message.deployment.id, - allow_custom_parameter : false, - force : false, - // Has title and value objects - workflow_name: { value : '' }, - workflow_list : workflowList, - fileModel : null, - parmFileDict : {} - }; - - $scope.selectWorkflowName = function(){ - var workflows = message.deployment.workflows; - let inputsAndValues = {}; - var res = workflows.filter(function(d){ - if(d.name == $scope.ecdapp.editRequest.workflow_name.value){ - return d - } - }); - for(var key in res[0].parameters){ - inputsAndValues[key] = typeof (res[0].parameters[key].default) === 'string' ? res[0].parameters[key].default : null; - } - $scope.ecdapp.inputsDict = inputsAndValues; - $scope.ecdapp.editRequest.parmFileDict = inputsAndValues; - }; - - if (debug) - $log.debug('DeploymentXeqCtrl: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest)); + var debug = false; - /** - * Handler for file-read event reads file, parses YAML, validates content. - */ - var fileReader = new FileReader(); - fileReader.onload = function(event) { - let yamlString = fileReader.result; - if (debug) - $log.debug('fileReader.onload: read: ' + yamlString); - let ydict = {}; - try { - ydict = YAML.parse(yamlString); - } - catch (ex) { - alert('Failed to parse file as YAML:\n' + ex); - } - for (var ykey in ydict) { - let yval = ydict[ykey]; - if (debug) - $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); - // Only accept valid, expected key-value pairs - if (typeof yval !== 'string' && typeof yval!=='number') - alert('Unexpected file content:\nNot a simple key-value pair:\n' + ykey); - else if (! (ykey in $scope.ecdapp.editRequest.parmFileDict)) - alert('Unexpected file content:\nKey not defined by deployment:\n' + ykey); - else - $scope.ecdapp.editRequest.parmFileDict[ykey] = yval; - } - if (debug) - $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict)); - - // Update table in all cases - $scope.$apply(); - } + if (debug) + $log.debug("inventoryDeploymentsExecutionsViewCtrl.message: " + JSON.stringify(message)); - // Handler for file-select event - $scope.handleFileSelect = function() { - if (debug) - $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); - fileReader.readAsText($scope.ecdapp.editRequest.fileModel); - }; + // this object holds all app data and functions + $scope.ecdapp = {}; + // models for controls on screen + $scope.ecdapp.label = 'Deployment ' + message.deployment.id + ' Executions'; + $scope.ecdapp.tableData = []; + $scope.ecdapp.logTableData = []; + $scope.ecdapp.currentPageNum = 1; + $scope.ecdapp.viewPerPage = 10; + $scope.ecdapp.currentLogPageNum = 1; + $scope.ecdapp.selectedRow = null; - /** - * Validates content of user-editable fields. - * Returns null if all is well, - * a descriptive error message otherwise. - */ - var validateRequest = function(editRequest) { - if (debug) - $log.debug('validateRequest: editRequest is ' + JSON.stringify(editRequest)); - if (editRequest == null) - return "No data found.\nPlease enter some values."; - if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '') - return "Deployment ID is required.\nPlease enter a value."; - if (editRequest.workflow_name.value == null || editRequest.workflow_name.value.trim() == '') - return "Workflow name is required.\nPlease select a workflow."; - // Check that every file parameter is defined by blueprint - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) { - // Defined in blueprint? - if (! $scope.ecdapp.inputsDict[pkey]) - return 'Unexpected input parameter\n' + pkey; - // Populated? - let parmVal = $scope.ecdapp.editRequest.parmFileDict[pkey]; - if (parmVal.trim().length == 0) - return 'Missing value for parameter ' + pkey; - } - // Check that a value is supplied for every expected input - for (var bkey in $scope.ecdapp.inputsDict) { - if (! $scope.ecdapp.editRequest.parmFileDict[bkey]) - return 'Missing input parameter\n' + bkey; - } - return null; - } - - $scope.ecdapp.executeDeployment = function(editRequest) { - var validateMsg = validateRequest(editRequest); - if (validateMsg != null) { - alert('Invalid execution request:\n' + validateMsg); - return; - } - - // Create request with key:value parameters dictionary - let executeRequest = { - deployment_id : editRequest.deployment_id, - workflow_name : editRequest.workflow_name.value, - allow_custom_parameter : editRequest.allow_custom_parameter, - force : editRequest.force, - parameters : {} - }; - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) - executeRequest.parameters[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey]; - if (debug) - $log.debug('executeDeployment: executeRequest is ' + JSON.stringify(executeRequest)); - - ExecutionService.executeDeployment(executeRequest) - .then(function(response) { - if (response.error) - alert('Failed to create execution:\n' + response.error); - else - $modalInstance.close(response); - }, - function (error) { - $log.error('deploymentExecuteCtrl: error while creating execution: ' + error); - alert('Server rejected execute request:\n' + error); - } - ); + // other + $scope.ecdapp.errMsg = null; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.isEventLogQuery = false; + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.isLastExecution = message.deployment.onlyLatest; + $scope.ecdapp.isLogType = true; + $scope.ecdapp.refresh_switch = { + value: true + }; + $scope.ecdapp.options = { + "on":"On", + "off":"Off" + } + var selTenant = message.deployment.tenant_name; - }; + $scope.ecdapp.ui_tenant = selTenant; + $scope.ecdapp.tenant = selTenant; + $scope.ecdapp.execId = ""; + $scope.ecdapp.deplRef = message.deployment.id; + var stop; + /** + * Loads the table. Interprets the remote controller's response and copies + * to scope variables. The response is either a list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.loadTable = function() { + $scope.ecdapp.isDataLoading = true; + InventoryExecutionService.getExecutionsByDeployment($scope.ecdapp.deplRef, + $scope.ecdapp.tenant, + $scope.ecdapp.currentPageNum, + $scope.ecdapp.viewPerPage).then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("deploymentExecutionsViewCtrl.loadTable failed: " + + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + if (jsonObj.error.includes("404")) { + $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; + } + $scope.ecdapp.tableData = []; + $scope.ecdapp.stopLoading(); + } else { + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + var resultLen = jsonObj.items.length; + if (resultLen != undefined && resultLen > 0) { + var exec_id = jsonObj.items[resultLen-1].id; + $scope.ecdapp.execId = exec_id; + $scope.ecdapp.selectedRow = resultLen-1; + if ($scope.ecdapp.isLastExecution) { + $scope.ecdapp.tableData = []; + $scope.ecdapp.tableData.push(jsonObj.items[resultLen-1]); + } else { + $scope.ecdapp.tableData = jsonObj.items; + } + $scope.ecdapp.getExecutionLogs($scope.ecdapp.selectedRow, exec_id, $scope.ecdapp.tenant); + } + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error("inventoryDeploymentExecutionsViewCtrl.loadTable failed: " + + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + $scope.ecdapp.stopLoading(); + }); + }; + $scope.$watch('ecdapp.refresh_switch["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + if (newValue === true) { + $scope.ecdapp.loadTable(); + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false); + } else { + $scope.ecdapp.stopLoading(); + } + } + }, true); + + if ($scope.ecdapp.refresh_switch.value === true) { + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false); + } + + $scope.ecdapp.stopLoading = function() { + if (angular.isDefined(stop)) { + $interval.cancel(stop); + stop = undefined; + } + }; + $scope.ecdapp.copyStringToClipboard = function(str) { + // Create new element + var el = document.createElement('textarea'); + // Set value (string to be copied) + el.value = str; + // Set non-editable to avoid focus and move outside of view + el.setAttribute('readonly', ''); + el.style = {position: 'absolute', left: '-9999px'}; + document.body.appendChild(el); + // Select text inside element + el.select(); + // Copy text to clipboard + document.execCommand('copy'); + // Remove temporary element + document.body.removeChild(el); + }; + + $scope.ecdapp.cancelExecutionModalPopup = function(execution, tenant) { + modalService.popupConfirmWin("Confirm", "Cancel execution with ID '" + + execution.id + "'?", function() { + $scope.ecdapp.isCancelOn = true; + // TODO: gather action from user + InventoryExecutionService.cancelExecution(execution.id, execution.deployment_id, "force-cancel", tenant).then( + function(response) { + if (debug) + $log.debug("Controller.cancelExecutionModalPopup: " + JSON.stringify(response)); + if (response && response.error) { + // $log.error('cancelExectuion failed: ' + response.error); + alert('Failed to cancel execution:\n' + response.error); + $scope.ecdapp.isCancelOn = false; + } + else { + // No response body on success. + $scope.ecdapp.isCancelOn = false; + $scope.ecdapp.loadTable(); + } + }, + function(error) { + $scope.ecdapp.isCancelOn = false; + $log.error('ExecutionService.cancelExecution failed: ' + error); + alert('Service failed to cancel execution:\n' + error); + }); + }) + }; + + /** + * Invoked at first page load AND when + * user clicks on the B2B pagination control. + */ + $scope.pageChangeHandler = function(page) { + if (debug) + console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); + $scope.ecdapp.currentPageNum = page; + $scope.ecdapp.loadTable(); + + } + $scope.pageChangeHandlerEvent = function(page) { + if (debug) + console.log('pageChangeHandlerEvent: current is ' + $scope.ecdapp.currentLogPageNum + ' new is ' + page); + if (page != $scope.ecdapp.currentLogPageNum ) { + $scope.ecdapp.currentLogPageNum = page; + $scope.ecdapp.getExecutionLogs($scope.ecdapp.selectedRow, $scope.ecdapp.execId, $scope.ecdapp.tenant); + } + } + + $scope.ecdapp.setClickedRow = function(index){ //function that sets the value of selectedRow to current index + $scope.ecdapp.selectedRow = index; + } + $scope.ecdapp.selected = false; + $scope.ecdapp.toggleStatusDefinitions = function() { + $scope.ecdapp.selected = $scope.ecdapp.selected ? false :true; + } + + /** + * Shows a modal pop-up with the error. + */ + $scope.ecdapp.viewErrorModalPopup = function(row) { + $modalInstance.dismiss('cancel'); + modalService.showFailure('Error Details', row.error, function() { } ); + }; + + $scope.ecdapp.getExecutionLogs = function(rowIdx, id, tenant) { + $scope.ecdapp.setClickedRow(rowIdx); + $scope.ecdapp.execId = id; + $scope.ecdapp.isEventLogQuery = false; + InventoryExecutionService.getEventsByExecution(id , $scope.ecdapp.isLogType, tenant, + $scope.ecdapp.currentLogPageNum, $scope.ecdapp.viewPerPage ).then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: " + + jsonObj.error); + $scope.ecdapp.isEventLogQuery = false; + $scope.ecdapp.evtErrMsg = jsonObj.error; + $scope.ecdapp.logTableData = []; + } else { + $scope.ecdapp.isEventLogQuery = true; + $scope.ecdapp.evtErrMsg = null; + $scope.ecdapp.totalLogPages = jsonObj.totalPages; + $scope.ecdapp.logTableData = jsonObj.items; + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: " + + error); + $scope.ecdapp.evtErrMsg = error; + $scope.ecdapp.logTableData = []; + $scope.ecdapp.isDataLoading = false; + }); + } + + $scope.$on('$destroy', function() { + // Make sure that the interval is destroyed too + $scope.ecdapp.stopLoading(); + }); +}); + + +/*************************************************************************/ +appDS2.controller('deploymentInputsViewCtrl', function( + $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'Deployment Inputs'; + $scope.ecdapp.deploymentRef = message.deployment.id; + $scope.ecdapp.serviceId = message.deployment.serviceId; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.isRequestFailed = false; + var selTenant = message.deployment.tenant_name; + if ( typeof selTenant === "undefined" ) { + selTenant = "default_tenant"; + } + $scope.ecdapp.ui_tenant = selTenant; + $scope.ecdapp.tenant = selTenant; + let inputsAndDescriptions = {}; + let inputsAndDefaults = {}; + // Get associated blueprint for inputs info + InventoryDeploymentService.getBlueprint($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(blueprint) { + if (debug) + $log.debug("inventoryDeploymentInputsViewCtrl.getBlueprint response: " + JSON.stringify(blueprint)); + if (!blueprint.error) { + for (var pkey in blueprint.items[0].plan.inputs) { + let description = blueprint.items[0].plan.inputs[pkey].description; + if ( typeof description === "undefined" ) { + description = ''; + } + inputsAndDescriptions[pkey] = description; + } + $scope.ecdapp.deployment.descriptionDict = inputsAndDescriptions; + } + }, + function(error) { + $log.error('InventoryDeploymentService.getBlueprint failed: ' + JSON.stringify(error)); + }); + + InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) { + if (deployment.items.length == 0) { + $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; + $log.error("InventoryDeploymentSerice.getDeployment failed: " + + $scope.ecdapp.errMsg); + $scope.ecdapp.isRequestFailed = true; + } + // Deployment IDs are unique, so this will always return exactly one item! + // retrieve blueprintId and inputs of deployment. + else { + $scope.ecdapp.errMsg = null; + //$scope.ecdapp.deployment = deployment.items[0]; + let ydict = deployment.items[0].inputs; + for (var ykey in ydict) { + let yval = ydict[ykey]; + if (yval.constructor === {}.constructor) + inputsAndDefaults[ykey] = JSON.stringify(yval, undefined, 2); + else + inputsAndDefaults[ykey] = yval; + } + $scope.ecdapp.isRequestFailed = false; + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error)); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.isDataLoading = false; + }); + $scope.ecdapp.deployment = { + parmFileDict : inputsAndDefaults, + descriptionDict : inputsAndDescriptions + }; }); +/*************************************************************************/ + +appDS2.controller('deployBlueprintContentCtrl', function( + $scope, $log, message, DeploymentService) { + + 'use strict'; + + var debug = false; + + if (debug) + $log.debug("deployBlueprintContentCtrl.message: " + JSON.stringify(message)); + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.blueprint_id; + // Fetch the blueprint + $scope.ecdapp.isDataLoading = true; + DeploymentService.getBlueprintContent(message.blueprint.blueprint_id, message.tenant_name).then(function(jsonObj) { + if (debug) + $log.debug("deployBlueprintContentCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed'; + } + else { + $scope.ecdapp.typeName = message.blueprint.blueprint_id; + $scope.ecdapp.blueprint = jsonObj.data; + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $scope.ecdapp.isDataLoading = false; + alert('Failed to get blueprint. Please retry.'); + $log.error("deployBlueprintContentCtrl failed: " + error); + }); +}); + + + /*************************************************************************/ + appDS2.controller('deploymentUpdateCtrl', function( + $scope, $log, $modalInstance, message, InventoryBlueprintService, InventoryDeploymentService) { + + 'use strict'; + + var debug = false; + if (debug) + $log.debug("inventoryDeploymentUpdateCtrl.message: " + JSON.stringify(message)); + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.deploymentInProgress = false; + $scope.ecdapp.serviceTypeComplete = false; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.label = 'Update ' + message.deployment.id; + $scope.ecdapp.deploymentRef = message.deployment.id; + var selTenant = message.deployment.tenant_name; + if ( typeof selTenant === "undefined" ) { + selTenant = "default_tenant"; + } + $scope.ecdapp.tenant = selTenant; + $scope.ecdapp.ui_tenant = selTenant; + $scope.ecdapp.updateBp = ''; + $scope.ecdapp.typeName = ''; + $scope.ecdapp.typeId = ''; + $scope.ecdapp.inputsDict = {}; + $scope.ecdapp.nodeInst = []; + $scope.ecdapp.selectedNodeInst; + $scope.ecdapp.editRequest = { + deployment_id : $scope.ecdapp.deploymentRef, + type_id : '', + fileModel : null, + parmFileDict : {}, + descriptionDict : {}, + tenant : $scope.ecdapp.tenant + }; + $scope.ecdapp.install_flow = { + value: true + }; + + $scope.ecdapp.uninstall_flow = { + value: true + }; + + $scope.ecdapp.reinstall_flow = { + value: true + }; + + $scope.ecdapp.install_first_flow_flag = { + value: false + }; + + $scope.ecdapp.force_flag = { + value: false + }; + + $scope.ecdapp.ignore_failure_flag = { + value: false + }; + + $scope.ecdapp.skip_install = false; + $scope.ecdapp.skip_uninstall = false; + $scope.ecdapp.skip_reinstall = false; + $scope.ecdapp.install_first_flow = false; + $scope.ecdapp.force = false; + $scope.ecdapp.ignore_failure = false; + + $scope.$watch('ecdapp.install_flow["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + console.log("toggled install flow: " + newValue); + $scope.ecdapp.skip_install = oldValue; + } + }, true); + + $scope.$watch('ecdapp.uninstall_flow["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + console.log("toggled uninstall flow: " + newValue); + $scope.ecdapp.skip_uninstall = oldValue; + } + }, true); + + $scope.$watch('ecdapp.reinstall_flow["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + console.log("toggled reinstall flow: " + newValue); + $scope.ecdapp.skip_reinstall = oldValue; + } + }, true); + + $scope.$watch('ecdapp.install_first_flow_flag["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + console.log("toggled install first flow: " + newValue); + $scope.ecdapp.install_first_flow = newValue; + } + }, true); + + $scope.$watch('ecdapp.force_flag["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + console.log("toggled force flag: " + newValue); + $scope.ecdapp.force = newValue; + } + }, true); + + $scope.$watch('ecdapp.ignore_failure_flag["value"]', function(newValue,oldValue,scope) { + if (newValue != oldValue) { + console.log("toggled ignore_failure flow: " + newValue); + $scope.ecdapp.ignore_failure = newValue; + } + }, true); + + // deployment node instances + InventoryDeploymentService.getNodeInstances($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant) + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryDeploymentUpdateCtrl.getNodeInstances failed: " + jsonObj.error); + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.nodeInst = []; + } else { + $scope.ecdapp.errMsg = null; + for (var nodeIndx = 0; nodeIndx < jsonObj.items.length; nodeIndx++) { + $scope.ecdapp.nodeInst.push(jsonObj.items[nodeIndx].id); + } + } + }, function(error) { + $log.error("inventoryDeploymentUpdateCtrl.getNodeInstances failed: " + error); + $scope.ecdapp.errMsg = error; + $scope.ecdapp.nodeInst = []; + $scope.ecdapp.isDataLoading = false; + }); + + // current blueprint +/* var typeLink = message.deployment.typeLink.href; + var n = typeLink.lastIndexOf("/"); + var typeId = typeLink.substring(n+1); + // Fetch the blueprint + $scope.ecdapp.isDataLoading = true; + InventoryBlueprintService.viewBlueprint(typeId).then(function(jsonObj) { + if (debug) + $log.debug("inventoryDeploymentUpdateCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed'; + } + else { + $scope.ecdapp.typeName = jsonObj.typeName; + $scope.ecdapp.typeId = jsonObj.typeId; + $scope.ecdapp.bp.push(jsonObj); + $scope.ecdapp.getBlueprint(); + } + //$scope.ecdapp.isDataLoading = false; + }, function(error) { + $scope.ecdapp.isDataLoading = false; + alert('Failed to get blueprint. Please retry.'); + $log.error("blueprintViewCtrl failed: " + error); + });*/ + + // get the blueprints from inventory matching deployment reference filter + $scope.ecdapp.bp = []; + InventoryBlueprintService.getBlueprintsSummary() + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + jsonObj.error); + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.bp = []; + } else { + $scope.ecdapp.errMsg = null; + $scope.ecdapp.bp = jsonObj; + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + error); + $scope.ecdapp.errMsg = error; + $scope.ecdapp.bp = []; + $scope.ecdapp.isDataLoading = false; + }); + $scope.ecdapp.getBlueprint = function() { + $scope.ecdapp.isDataLoading = true; + InventoryBlueprintService.viewBlueprint($scope.ecdapp.typeId).then(function(jsonObj) { + if (debug) + $log.debug("inventoryDeploymentUpdateCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed'; + $scope.ecdapp.serviceTypeComplete = false; + $scope.ecdapp.isDataLoading = false; + } + else { + $scope.ecdapp.typeName = jsonObj.typeName; + $scope.ecdapp.typeVersion = jsonObj.typeVersion; + $scope.ecdapp.inputsDict = jsonObj.blueprintInputs; + // query the current deployment inputs + InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) { + if (deployment.items.length == 0) { + $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; + $log.error("InventoryDeploymentSerice.getDeployment failed: " + + $scope.ecdapp.errMsg); + //$scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.serviceTypeComplete = true; + } + // Deployment IDs are unique, so this will always return exactly one item!. + // retrieve inputs of deployment. + else { + $scope.ecdapp.errMsg = null; + $scope.ecdapp.deployment = deployment.items[0]; + // Copy the input parameter names and default values + let inputsAndDefaults = {}; + let inputsAndDescriptions = {}; + let ydict = deployment.items[0].inputs; + for (var ykey in ydict) { + let yval = ydict[ykey]; + if (yval.constructor === {}.constructor) + inputsAndDefaults[ykey] = JSON.stringify(yval, undefined, 2); + else + //$scope.ecdapp.deployment.inputs[ykey] = yval; + inputsAndDefaults[ykey] = yval; + } + for (var pkey in $scope.ecdapp.inputsDict) { + //$scope.ecdapp.deployment = deployment.items[0]; + let description = $scope.ecdapp.inputsDict[pkey].description; + if ( typeof description === "undefined" ) + description = ''; + inputsAndDescriptions[pkey] = description; + } + + $scope.ecdapp.editRequest.parmFileDict = inputsAndDefaults; + $scope.ecdapp.editRequest.descriptionDict = inputsAndDescriptions; + $scope.ecdapp.editRequest.type_id = $scope.ecdapp.typeId; + if (debug) + $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults)); + + $scope.ecdapp.serviceTypeComplete = true; + //$scope.$apply(); + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error)); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.isDataLoading = false; + }); + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $scope.ecdapp.isDataLoading = false; + $scope.ecdapp.serviceTypeComplete = false; + alert('Failed to get blueprint. Please retry with valid blueprint ID.'); + $log.error("inventoryDeploymentUpdateCtrl failed: " + error); + }); + }; + + /** + * Handler for file-read event reads file, parses JSON, validates content. + */ + var fileReader = new FileReader(); + fileReader.onload = function(event) { + let jsonString = fileReader.result; + if (debug) + $log.debug('fileReader.onload: read: ' + jsonString); + let ydict = {}; + try { + ydict = JSON.parse(jsonString); + } + catch (ex) { + alert('Failed to parse file as JSON:\n' + ex); + } + // Process the file + for (var ykey in ydict) { + let yval = ydict[ykey]; + if (debug) + $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); + // Allow only expected keys with scalar values + if (! (ykey in $scope.ecdapp.editRequest.parmFileDict)) + alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey); + if (yval.constructor === {}.constructor) + $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval); + else + $scope.ecdapp.editRequest.parmFileDict[ykey] = yval; + } + if (debug) + $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict)); + + // Update table in all cases + $scope.$apply(); + } + + // Handler for file-select event + $scope.handleFileSelect = function() { + if (debug) + $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); + fileReader.readAsText($scope.ecdapp.editRequest.fileModel); + }; + + $scope.ecdapp.validateRequest = function(editRequest) { + if (editRequest == null) + return 'No data found.\nPlease enter some values.'; + if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '') + return 'Deployment ID is required.\nPlease enter a value.'; + if (editRequest.type_id == null || editRequest.type_id.trim() == '') + return 'Type ID is required.\nPlease enter a value.'; + // Check that every file parameter is defined by blueprint + for (var pkey in $scope.ecdapp.editRequest.parmFileDict) { + // Defined in blueprint? + if (! $scope.ecdapp.inputsDict[pkey]) + return 'Unexpected input parameter\n' + pkey; + } + return null; + } + + $scope.ecdapp.updateDeployment = function(editRequest) { + if (debug) + $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest)); + var validateMsg = $scope.ecdapp.validateRequest(editRequest); + if (validateMsg != null) { + alert('Invalid Request:\n' + validateMsg); + $scope.ecdapp.errMsg = validateMsg; + return; + } + // Create request with key:value parameters dictionary + let deploymentRequestObject = { + deploymentId : editRequest.deployment_id, + serviceTypeId : editRequest.type_id, + inputs : {}, + tenant : editRequest.tenant, + method : "update", + reinstall_list : $scope.ecdapp.selectedNodeInst, + skip_install : $scope.ecdapp.skip_install, + skip_uninstall : $scope.ecdapp.skip_uninstall, + skip_reinstall : $scope.ecdapp.skip_reinstall, + force : $scope.ecdapp.force, + ignore_failure : $scope.ecdapp.ignore_failure, + install_first : $scope.ecdapp.install_first_flow + }; + + for (var pkey in $scope.ecdapp.editRequest.parmFileDict) + try { + deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]); + } catch (error) { + deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey]; + } + if (debug) + $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject)); + + $scope.ecdapp.deploymentInProgress = true; + InventoryDeploymentService.deployBlueprint(deploymentRequestObject) + .then(function(response) { + $scope.ecdapp.deploymentInProgress = false; + if (response.error) { + alert('Failed to deploy blueprint:\n' + response.error); + $scope.ecdapp.errMsg = response.error; + } else { + alert('Deployment update request sent successfully, query the execution status for final outcome'); + $modalInstance.close(response); + } + }, + function (error) { + $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error); + alert('Server rejected deployment request:\n' + error); + $scope.ecdapp.deploymentInProgress = false; + } + ); + }; + + }); + + /*************************************************************************/ + appDS2.controller('deploymentRollbackCtrl', function( + $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'Deployment Rollback'; + $scope.ecdapp.revisions = []; + $scope.ecdapp.deploymentRef = message.deployment.id; + $scope.ecdapp.serviceId = message.deployment.serviceId; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.updatingDeployment = false; + var selTenant = message.deployment.tenant_name; + if ( typeof selTenant === "undefined" ) { + selTenant = "default_tenant"; + } + $scope.ecdapp.tenant = selTenant; + $scope.ecdapp.ui_tenant = selTenant; + $scope.ecdapp.local_revisions = []; + // This object holds data for this operation + $scope.ecdapp.rollbackRequest = { + "deployment_id": message.deployment.deploymentRef, + "workflow_name": "rollback", + "tenant": selTenant, + "revision": 1 + }; + + InventoryDeploymentService.getNodeInstanceVersions($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(nodeRunTime) { + if (nodeRunTime == null) { + $scope.ecdapp.errMsg = "Failed to retrieve Node instance runtime information"; + $log.error("InventoryDeploymentSerice.getNodeInstanceVersions failed: " + + $scope.ecdapp.errMsg); + $scope.ecdapp.isRequestFailed = true; + } else { + $scope.ecdapp.errMsg = null; + $scope.ecdapp.revisions = nodeRunTime.items[0].runtime_properties['helm-history']; + if (Array.isArray($scope.ecdapp.revisions) ) { + var dLen = $scope.ecdapp.revisions.length; + + for (var i = 1; i < dLen; i++) { + var str = $scope.ecdapp.revisions[i].replace(/\s+/g, ' '); + var itemStrArr = str.split(" "); + var itemLen = itemStrArr.length; + var revObj = {}; + revObj.revision = itemStrArr[0].trim(); + revObj.updated = itemStrArr.slice(1,5).toString().replace(/,/g, ' '); + revObj.status = itemStrArr[6].trim(); + revObj.chart = itemStrArr[7].trim(); + revObj.description = itemStrArr.slice(8,itemLen).toString().replace(/,/g, ' '); + revObj.name = itemStrArr[0].trim(); + revObj.checked = false; + $scope.ecdapp.local_revisions.push(revObj); + } + } + console.log($scope.ecdapp.local_revisions); + $scope.ecdapp.isRequestFailed = false; + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error('InventoryDeploymentService.getNodeInstanceVersions failed: ' + JSON.stringify(error)); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.isDataLoading = false; + }); + $scope.ecdapp.updateSelection = function(position) { + $scope.ecdapp.rollbackRequest.revision = position; + angular.forEach($scope.ecdapp.local_revisions, function(item, index) { + if (position != index+1) + item.checked = false; + }); + } + /** + * rollback deployment based on parameters user enters/adjusts in modal popup + * First retrieves the node-id using the blueprintId + * Using the node-id and deploymentId, retrieves the node-instance-id + * Calls the update resource API, passing object with deploymentId, and changed parameters + */ + $scope.ecdapp.rollbackWorkflow = function(revision) { + $scope.ecdapp.updatingDeployment = true; + $scope.ecdapp.isDataLoading = true; + InventoryDeploymentService.rollbackFlow($scope.ecdapp.rollbackRequest).then(function(jsonObj) { + if (debug) + $log.debug("inventoryDeploymentRollbackCtrl.rollbackWorkflow response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; + $scope.ecdapp.updatingDeployment = false; + $scope.ecdapp.isDataLoading = false; + } else { + console.log('%c ROLLBACK RESOURCES COMPLETED', 'color: magenta; font-weight: bold;'); + alert('Rollback request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Rollback is now pending'); + $scope.ecdapp.updatingDeployment = false; + $scope.ecdapp.isDataLoading = false; + } + }, function(error) { + $scope.ecdapp.updatingDeployment = false; + $log.error('inventoryDeploymentRollbackCtrl failed: ' + error); + alert('Failed to rollback Deployment ' + $scope.ecdapp.deploymentRef + '. Please retry.'); + $scope.ecdapp.isDataLoading = false; + }); + } + }); + + /*************************************************************************/ + appDS2.controller('appReconfigCtrl', function( + $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService, DeploymentService) { + + 'use strict'; + + var debug = true; + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.tenant = message.deployment.tenant_name; + $scope.ecdapp.deploymentId = message.deployment.id; + $scope.ecdapp.bpId = message.deployment.blueprint_id; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.updatingDeployment = false; + $scope.ecdapp.parmFileDict = {}; + $scope.ecdapp.parmCurrFileDict = {}; + $scope.ecdapp.app_config_from_bp = {}; + $scope.ecdapp.app_config_new = {}; + $scope.ecdapp.app_config_bakup = {}; + $scope.ecdapp.app_config_inputs = []; + $scope.ecdapp.app_config_bp_str =''; + $scope.ecdapp.app_config_latest_str =''; + $scope.ecdapp.descriptionDict = {}; + $scope.ecdapp.appConfigOverride = {}; + $scope.ecdapp.app_config_input_map = {}; + + $scope.ecdapp.reconfigRequest = { + deployment_id: $scope.ecdapp.deploymentId, + workflow_id: 'execute_operation', + parameters: {}, + tenant: $scope.ecdapp.tenant + }; + $scope.ecdapp.reconfigRequest.parameters.operation = + 'dcae.interfaces.lifecycle.Reconfiguration'; + $scope.ecdapp.reconfigRequest.parameters.operation_kwargs = {}; + $scope.ecdapp.reconfigRequest.parameters.operation_kwargs.type = 'app_reconfig'; + $scope.ecdapp.reconfigRequest.parameters.operation_kwargs.application_config = {}; + $scope.ecdapp.reconfigRequest.parameters.allow_kwargs_override = true; + $scope.ecdapp.reconfigRequest.parameters.type_names = + ['dcae.nodes.DockerContainerForComponents', 'dcae.nodes.DockerContainerForComponentsUsingDmaap', + 'dcae.nodes.ContainerizedServiceComponent', 'dcae.nodes.ContainerizedServiceComponentUsingDmaap']; + + // get the BP object from cloudify + // get the depl object from cloudify + // get the node instance data from cloudify + // parse the application_config from BP node properties + // parse the inputs from deployment + // display FORM with current input fields that are referred in the appl + // config object + // display application_config on the screen and setup data binding to the + // input FORM + // create POST request body for start execution to cloudify + // invoke service method to send POST request to cloudify + InventoryDeploymentService.getBlueprint($scope.ecdapp.bpId, + $scope.ecdapp.tenant).then(function(blueprint) { + if (debug) + $log.debug("appReconfigCtrl.getBlueprint response: " + JSON.stringify(blueprint)); + if (blueprint.error) { + $scope.ecdapp.errMsg = 'Request Failed: ' + blueprint.error; + $scope.ecdapp.updatingDeployment = false; + $scope.ecdapp.isRequestFailed = true; + } + else { + $scope.ecdapp.isRequestFailed = false; + if (Array.isArray(blueprint.items) && blueprint.items.length > 0) { + var foundNode = blueprint.items[0].plan.nodes.find(function checkAppConfig(node) { + if (Object.keys(node.properties).includes("application_config")) { + return true; + } + }); + if (foundNode != undefined && foundNode.properties != undefined ) { + $scope.ecdapp.app_config_from_bp = foundNode.properties.application_config; + $scope.ecdapp.app_config_bp_str = + JSON.stringify($scope.ecdapp.app_config_from_bp, undefined, 4); + + $scope.ecdapp.checkType = function(key1, value1) { + if (value1 instanceof Object && !Array.isArray(value1)) { + for (let [key2, value2] of Object.entries(value1)) { + if (key2 == "get_input") { + $scope.ecdapp.app_config_inputs.push(value2); + $scope.ecdapp.app_config_input_map[key1] = value2; + } else { + $scope.ecdapp.checkType(key2, value2); + } + } + } + }; + + for (let [key1, value1] of + Object.entries($scope.ecdapp.app_config_from_bp)) + { + $scope.ecdapp.checkType(key1, value1); + } + } + + let inputsAndDescriptions = {}; + for (var pkey in blueprint.items[0].plan.inputs) { + let description = blueprint.items[0].plan.inputs[pkey].description; + if ( typeof description === "undefined" ) { + description = ''; + } + inputsAndDescriptions[pkey] = description; + } + $scope.ecdapp.descriptionDict = inputsAndDescriptions; + + InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentId, + $scope.ecdapp.tenant).then(function(deployment) { + if (deployment.items.length == 0) { + $scope.ecdapp.errMsg = "404 - Deployment " + $scope.ecdapp.deploymentId + " Not Found!"; + $log.error("InventoryDeploymentSerice.getDeployment failed: " + + $scope.ecdapp.errMsg); + $scope.ecdapp.isRequestFailed = true; + } + else { + $scope.ecdapp.errMsg = null; + $scope.ecdapp.deployment = deployment.items[0]; + $scope.ecdapp.isRequestFailed = false; + if (Array.isArray(deployment.items) && deployment.items.length > 0) { + var deplInputs = deployment.items[0].inputs; + $scope.ecdapp.app_config_inputs.forEach(function findMatch(value, index, array) { + for (let [key, val] of Object.entries(deplInputs)) { + if (value == key) { + $scope.ecdapp.parmFileDict[key] = val; + } + } + }); + } + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error)); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.isDataLoading = false; + }); + + InventoryDeploymentService.getNodeInstanceData($scope.ecdapp.deploymentId, + $scope.ecdapp.tenant).then(function(nodeInstances) { + if (Array.isArray(nodeInstances.items) && nodeInstances.items.length > 0) { + var foundNode = nodeInstances.items.find(function checkAppConfig(item) { + if (Object.keys(item.runtime_properties).includes("application_config")) { + return true; + } + }); + if (foundNode != undefined) { + $scope.ecdapp.app_config_new = foundNode.runtime_properties.application_config; + $scope.ecdapp.app_config_latest_str = + JSON.stringify($scope.ecdapp.app_config_new, undefined, 4); + for (let [key, value] of + Object.entries(foundNode.runtime_properties.application_config)) + { + if (value.constructor === {}.constructor) + $scope.ecdapp.appConfigOverride[key] = angular.toJson(value); + else + $scope.ecdapp.appConfigOverride[key] = value; + } + $scope.ecdapp.app_config_inputs.forEach(function findMatch(value, index, array) { + for (let [key, val] of Object.entries($scope.ecdapp.appConfigOverride)) { + if (value == key) { + $scope.ecdapp.parmCurrFileDict[key] = val; + } + } + }); + } + } + }, + function(error) { + $log.error('InventoryDeploymentService.getNodeInstances failed: ' + JSON.stringify(error)); + }); + } + $scope.ecdapp.isDataLoading = false; + } + }, + function(error) { + $log.error('InventoryDeploymentService.getBlueprint failed: ' + JSON.stringify(error)); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.isDataLoading = false; + }); + + $scope.ecdapp.refreshAppConfig = function(newInputs) { + angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_bakup); + for (let [input_key, input_val] of Object.entries(newInputs)) { + $scope.ecdapp.replaceNewInput(input_key, input_val, $scope.ecdapp.app_config_from_bp); + } + angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_new); + angular.copy($scope.ecdapp.app_config_bakup, $scope.ecdapp.app_config_from_bp); + + $scope.ecdapp.app_config_latest_str = + JSON.stringify($scope.ecdapp.app_config_new, undefined, 4); + }; + + var fileReader = new FileReader(); + fileReader.onload = function(event) { + let jsonString = fileReader.result; + let ydict = {}; + try { + ydict = JSON.parse(jsonString); + } + catch (ex) { + alert('Failed to parse file as JSON:\n' + ex); + } + // Process the file + for (var ykey in ydict) { + let yval = ydict[ykey]; + // Allow only expected keys with scalar values + if (ykey in $scope.ecdapp.parmFileDict) + { + // alert('Unexpected file content:\nKey not defined by blueprint:\n' + + // ykey); + if (yval.constructor === {}.constructor) + $scope.ecdapp.parmFileDict[ykey] = angular.toJson(yval); + else + $scope.ecdapp.parmFileDict[ykey] = yval; + } + } + $scope.ecdapp.refreshAppConfig($scope.ecdapp.parmFileDict); + $scope.$apply(); + }; + // Handler for file-select event + $scope.handleFileSelect = function() { + if (debug) + $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); + fileReader.readAsText($scope.ecdapp.editRequest.fileModel); + }; + $scope.ecdapp.replaceNewInput = function(input_key, input_val, src) { + var itemFound = false; + for (let [key, value] of Object.entries(src)) { + if (value instanceof Object && !Array.isArray(value)) { + for (let [key2, value2] of Object.entries(value)) { + if (key2 == "get_input" && value2 == input_key) { + src[key] = input_val; + itemFound = true; + break; + } else { + $scope.ecdapp.replaceNewInput(input_key, input_val, value2); + } + } + } + if (itemFound) { + break; + } + } + }; + + $scope.ecdapp.reconfigDeploymentById = function(newInputs) { + $scope.ecdapp.updatingDeployment = true; + angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_bakup); + for (let [input_key, input_val] of Object.entries(newInputs)) { + $scope.ecdapp.replaceNewInput(input_key, input_val, + $scope.ecdapp.app_config_from_bp); + } + angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_new); + angular.copy($scope.ecdapp.app_config_bakup, $scope.ecdapp.app_config_from_bp); + $scope.ecdapp.app_config_latest_str = + JSON.stringify($scope.ecdapp.app_config_new, undefined, 4); + + $scope.ecdapp.reconfigRequest.parameters.operation_kwargs.application_config = + $scope.ecdapp.app_config_new; + + DeploymentService.reconfigFlow($scope.ecdapp.reconfigRequest).then(function(jsonObj) { + if (debug) + $log.debug("appReconfigCtrl.reconfigFlow response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; + $scope.ecdapp.updatingDeployment = false; + } + else { + $scope.ecdapp.updatingDeployment = false; + alert('application reconfig request for ' + $scope.ecdapp.deploymentId + ' successfully went through to Cloudify. Reconfig is now pending'); + $modalInstance.dismiss('cancel'); + } + }, function(error) { + $scope.ecdapp.updatingDeployment = false; + alert('Failed to perform reconfig for Deployment Id ' + $scope.ecdapp.deploymentId); + $log.error('appReconfigCtrl.reconfigFlow failed: ' + error); + }); + + }; + }); + + /*************************************************************************/ + appDS2.controller('deploymentUpgradeCtrl', function( + $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'Deployment Upgrade'; + $scope.ecdapp.deployment = null; + $scope.ecdapp.deploymentRef = message.deployment.id; //THIS IS THE BLUEPRINT ID + $scope.ecdapp.bpId = message.deployment.blueprint_id; + $scope.ecdapp.serviceId = message.deployment.serviceId; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.updatingDeployment = false; + var selTenant = message.deployment.tenant_name; + if ( typeof selTenant === "undefined" ) { + selTenant = "default_tenant"; + } + $scope.ecdapp.tenant = selTenant; + $scope.ecdapp.ui_tenant = selTenant; + $scope.ecdapp.parmFileDict = {}; + + // This object holds data for editing the input parameters + $scope.ecdapp.editRequest = { + deployment_id: '', + type_id: '', + fileModel: null, + resourceConstants: {}, + resourceDefinitionChanges: {} + }; + //First get the blueprintId associated with the deployment, along with the inputs of the deployment + InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) { + if (deployment.items.length == 0) { + $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; + $log.error("InventoryDeploymentSerice.getDeployment failed: " + + $scope.ecdapp.errMsg); + $scope.ecdapp.isRequestFailed = true; + } + // Deployment IDs are unique, so this will always return exactly one item! + else { + $scope.ecdapp.errMsg = null; + $scope.ecdapp.deployment = deployment.items[0]; + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.editRequest.type_id = deployment.items[0].blueprint_id; + $scope.ecdapp.parmFileDict = deployment.items[0].inputs; + Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) { + if (key == 'config-format' || key == 'config-url' || key == 'chart-version' || key == 'chart-repo-url' || key == 'config-set') { + $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key]; + } else { + $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key]; + } + //$scope.ecdapp.editRequest.resourceDefinitionChanges['config_set'] = ''; + }); + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error)); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.isDataLoading = false; + }); + + /** + * Validates content of user-editable fields. + * Returns null if all is well, + * a descriptive error message otherwise. + */ + + $scope.ecdapp.validateRequest = function(editRequest) { + if (editRequest == null) + return 'No data found.\nPlease enter some values.'; + if (editRequest["chart-version"] == null || editRequest["chart-version"].trim() == '') + return 'Chart version is required.\nPlease enter a value.'; + if (!editRequest["config-format"] || editRequest["config-format"].trim() == '') { + return 'config format is required.\nPlease enter a value.'; + } + if ((!editRequest["config-url"] || editRequest["config-url"].trim() == '') && + (!editRequest["config_set"] || editRequest["config_set"].trim() == '')) { + return 'Config URL or Config set is required.\nPlease enter either of these input values'; + } + return null; + }; + + /** + * Helm upgrade for deployment based on parameters user enters in modal popup + * First retrieves the node-id using the blueprintId + * Using the node-id and deploymentId, retrieves the node-instance-id + * Calls the start execution API, passing object with deploymentId, and changed parameters + */ + + $scope.ecdapp.upgradeWorkflow = function(resourceDefinitionChanges) { + $scope.ecdapp.updatingDeployment = true; + let nodeId = ''; + + // validate request + var validateMsg = $scope.ecdapp.validateRequest(resourceDefinitionChanges); + if (validateMsg != null) { + alert('Invalid Request:\n' + validateMsg); + $scope.ecdapp.updatingDeployment = false; + return; + } + //get node id from blueprint + InventoryDeploymentService.getBlueprint($scope.ecdapp.bpId, $scope.ecdapp.tenant).then(function(blueprint) { + if (debug) + $log.debug("inventoryDeploymentUpgradeCtrl.getBlueprint response: " + JSON.stringify(blueprint)); + if (blueprint.error) { + $scope.ecdapp.errMsg = 'Request Failed: ' + blueprint.error; + $scope.ecdapp.updatingDeployment = false; + } + else { + //console.log('returned blueprint:' + blueprint); + let count = 0; + //console.log("number of node objects in array: " + blueprint.items[0].plan.nodes.length); + //console.log(JSON.stringify(blueprint)); + blueprint.items[0].plan.nodes.map(function(node) { + if (node.type == 'onap.nodes.component') { + //want to get FIRST node with type 'cloudify.kubernetes.resources.Deployment' so only set nodeID for first matching type + if (count < 1) { + nodeId = node.id; + } + count = count + 1; + } + }); + //if no node has type 'cloudify.kubernetes.resources.Deployment', return message saying no deployment exists and exit (ie nodeId still is '') + if (nodeId == '') { + alert('Failed to retrieve Node Id. No matching deployment found (no deployment exists)'); + $scope.ecdapp.updatingDeployment = false; + return; + } + //found node id. now need to retrieve node-instance-id + console.log('%c RETRIEVED NODE ID: ' + nodeId, 'color: orange; font-weight: bold;'); + let nodeInstanceId = ''; + InventoryDeploymentService.getNodeInstanceId($scope.ecdapp.deploymentRef, nodeId, $scope.ecdapp.tenant).then(function(jsonObj) { + if (debug) + $log.debug("inventoryDeploymentUpgradeCtrl.getNodeInstanceId response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; + $scope.ecdapp.updatingDeployment = false; + } + else { + //if nodeInstanceId is still '' then it wasn't found, stop flow) + if (jsonObj.items[0].id == '') { + alert('Failed to retrieve Node Instance Id for Node Id' + nodeId); + $scope.ecdapp.updatingDeployment = false; + return; + } + //found node-instance-id. now need to update resources + nodeInstanceId = jsonObj.items[0].id; + console.log('%c RETRIEVED NODE INSTANCE ID:' + nodeInstanceId, 'color: green; font-weight: bold;'); + //console.log(resourceDefinitionChanges); + InventoryDeploymentService.upgradeFlow($scope.ecdapp.deploymentRef, nodeInstanceId, resourceDefinitionChanges, $scope.ecdapp.tenant).then(function(jsonObj) { + if (debug) + $log.debug("inventoryDeploymentUpgradeCtrl.updateResources response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; + $scope.ecdapp.updatingDeployment = false; + } + else { + console.log('%c UPDATE RESOURCES COMPLETED', 'color: magenta; font-weight: bold;'); + //console.log(jsonObj); + $scope.ecdapp.updatingDeployment = false; + alert('Helm Upgrade request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Upgrade is now pending'); $modalInstance.dismiss('cancel'); + } + }, function(error) { + $scope.ecdapp.updatingDeployment = false; + alert('Failed to perform upgrade for Deployment Id ' + $scope.ecdapp.deploymentRef + ' and Node Instance Id ' + nodeInstanceId + '. Please retry.'); + $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error); + }); + } + }, function(error) { + $scope.ecdapp.updatingDeployment = false; + alert('Failed to get Node Instance Id for deploymentId ' + $scope.ecdapp.deploymentRef + ' and Node Id ' + nodeId + '. Please retry.'); + $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error); + }); + + } + }, function(error) { + $scope.ecdapp.updatingDeployment = false; + alert('Failed to get blueprint for blueprintId ' + $scope.ecdapp.deploymentRef + '. Please retry.'); + $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error); + }); + }; + + /** + * Handler for file-read event reads file, parses JSON, validates content. + */ + + var fileReader = new FileReader(); + fileReader.onload = function(event) { + let jsonString = fileReader.result; + if (debug) + $log.debug('fileReader.onload: read: ' + jsonString); + let ydict = {}; + try { + ydict = JSON.parse(jsonString); + } + catch (ex) { + alert('Failed to parse file as JSON:\n' + ex); + } + // Process the file + for (var ykey in ydict) { + let yval = ydict[ykey]; + if (debug) + $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); + // Allow only expected keys with scalar values + if (! (ykey in $scope.ecdapp.parmFileDict)) + alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey); + if (yval.constructor === {}.constructor) + $scope.ecdapp.parmFileDict[ykey] = angular.toJson(yval); + else + $scope.ecdapp.parmFileDict[ykey] = yval; + } + if (debug) + $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.parmFileDict)); + + // Update table in all cases + //$scope.ecdapp.setResourceDefinitionChanges($scope.ecdapp.editRequest.resourceDefinitionChanges, $scope.ecdapp.editRequest.parmFileDict); + Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) { + + if (key == 'config-format' || key == 'config-url' || key == 'chart-version' || key == 'chart-repo-url' || key == 'config-set') { + $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key]; + } else { + $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key]; + } + }); + //$scope.$apply(); + }; + + // Handler for file-select event + $scope.handleFileSelect = function() { + if (debug) + $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); + fileReader.readAsText($scope.ecdapp.editRequest.fileModel); + }; + + }); + diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-service.js index cee83c3..f7f9db3 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-service.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-service.js @@ -1,24 +1,3 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ appDS2.factory('DeploymentService', function ($http, $q, $log) { return { /** @@ -27,10 +6,19 @@ appDS2.factory('DeploymentService', function ($http, $q, $log) { * @param {Number} viewPerPage - number of items per page; e.g., 25 * @return {JSON} Response object from remote side */ - getDeployments: function(pageNum,viewPerPage) { + getDeployments: function(pageNum,viewPerPage,sortBy,searchBy) { // cache control for IE let cc = "&cc=" + new Date().getTime().toString(); - let url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc; + let url = null; + if (sortBy && searchBy) { + url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&sortBy=' + sortBy + '&searchBy=' + searchBy + cc; + } else if (sortBy) { + url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&sortBy=' + sortBy + cc; + } else if (searchBy) { + url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&searchBy=' + searchBy + cc; + } else { + url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage +cc; + } return $http({ method: 'GET', url: url, @@ -84,6 +72,69 @@ appDS2.factory('DeploymentService', function ($http, $q, $log) { $log.error('DeploymentService.deleteDeployment failed: ' + JSON.stringify(error)); return $q.reject(error.statusText); }); + }, + + getBlueprintContent: function(id, tenant) { + let url ='blueprints/' + id + '/archive?tenant=' + tenant; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'yaml' + }).then(function(response) { + // This is called on response code 200..299. + // On success, response.data is null. + // On failure, response.data has an error message. +/* var contentType = "application/octet-stream"; + var data = response.data + var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL; + if (urlCreator) { + var blob = new Blob([data], { type: contentType }); + var url = urlCreator.createObjectURL(blob); + var a = document.createElement("a"); + document.body.appendChild(a); + a.style = "display: none"; + a.href = url; + a.download = "blueprint.yaml"; //you may assign this value from header as well + a.click(); + window.URL.revokeObjectURL(url); + }*/ + return response; + }, + function(error) { + $log.error('DeploymentService.getBlueprintContent failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + + reconfigFlow: function(reconfigRequest) { + let body = { + "deployment_id": reconfigRequest.deployment_id, + "workflow_id": reconfigRequest.workflow_id, + "allow_custom_parameters": true, + "force": true, + "tenant": reconfigRequest.tenant, + "parameters": reconfigRequest.parameters + }; + let urlStr = 'executions'; + return $http({ + method: 'POST', + url: urlStr, + data: body, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null) + return $q.reject('DeploymentService.reconfigFlow: response.data null or not object'); + else { + console.log(response); + return response.data; + } + }, + function(error) { + $log.error('DeploymentService.reconfigFlow failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); } }; }); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_popups.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_popups.html index f4a4cdd..d051495 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_popups.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_popups.html @@ -1,3 +1,43 @@ +<script type="text/ng-template" id="blueprint_content_popup.html"> + <div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> + </div> + <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div class="row-nowrap"> + <div class="span12"> + <label for="typeName">Blueprint Name</label> + <!--not editable--> + <input id="typeName" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.typeName" /> + </div> + </div> + <div ng-hide="ecdapp.errMsg"> + <pre>{{ecdapp.blueprint}}</pre> + </div> + </div> + <div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <div class="cta-button-group in"> + <button class="btn btn-alt btn-small" type="button" + ng-click="$dismiss('cancel');">Close</button> + </div> + </div> +</script> <script type="text/ng-template" id="deployment_execute_popup.html"> <style> @@ -91,7 +131,7 @@ <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict"> <tr id="tr-rowData"> <td ng-bind="pkey"/> - <td ng-bind="pval"/> + <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td> </tr> </tbody> </table> @@ -116,49 +156,138 @@ </script> -<script type="text/ng-template" id="deployment_delete_popup.html"> - - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" +<script type="text/ng-template" id="app_reconfig_view_popup.html"> + <div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title=""> + <span style="font-weight: bolder; background: aqua;">{{ecdapp.deploymentId}}</span> + Execute Reconfiguration + </h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> + </div> + <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" role="region" aria-label="Modal body content"> - - <div class="span12"> - <div class="form-row"> - <div class="field-group"> - <label> - Delete deployment with ID '{{ecdapp.deploymentId}}'? - </label> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-hide="ecdapp.isDataLoading" style="margin-top: 10px;"> + <div class="row-nowrap"> + <div class="span9"> + <div class="form-row"> + <label for="parameters">Configuration Inputs</label> + <div class="tooltip" b2b-tooltip trigger="focus" style="float:right;"> + <a href="javascript:void(0)" class="tooltip-element" data-placement="left" role="button" aria-label="Help" aria-describedby="tooltiptext1" > + blueprint + <div class="arrow"></div> + </a> + <div class="tooltip-wrapper" role="tooltip" aria-live="polite" aria-atomic="false" style="z-index:1111"> + <div class="tooltip-size-control"> + <div class="helpertext" tabindex="-1" role="tooltip" id="tooltiptext1"> + <div class="popover-title">Application Configuration Blueprint</div> + <div class="popover-content"> + <pre>{{ecdapp.app_config_bp_str}}</pre> + </div> + </div> + </div> + </div> + </div> + <div b2b-file-drop + file-model="ecdapp.editRequest.fileModel" + on-drop="handleFileSelect()" align="center"> + <span b2b-file-link + file-model="ecdapp.editRequest.fileModel" + on-file-select="handleFileSelect()"> Drag + & drop a parameters JSON file here, or click to + browse. </span> + </div> + </div> + <div class="ecd-parameter-table"> + <table id="parameters"> + <tr id="ecd-table-header"> + <th width="20%">Name</th> + <th width="40%">Initial Value</th> + <th width="40%">Current Value</th> + </tr> + <tbody + ng-repeat="(pkey, pval) in ecdapp.parmFileDict"> + <tr id="tr-rowData"> + <td> + <div style="font-weight: bold;">{{pkey}}</div> + <div style="margin-top: 8px; font-weight: lighter;">{{ecdapp.descriptionDict[pkey]}}</div> + </td> + <td><input class="span12" + type="text" disabled="disabled" + data-ng-model="ecdapp.parmFileDict[pkey]" + autofocus /> + </td> + <td><input class="span12" + type="text" + data-ng-model="ecdapp.parmCurrFileDict[pkey]" + ng-keyup="ecdapp.refreshAppConfig(ecdapp.parmCurrFileDict);" + autofocus /> + </td> + </tr> + </tbody> + </table> </div> + <!-- + <div class="reconfig-params" style="margin-top: 10px;"> + <label for="parameters">Configuration Override</label> + <table id="reconfig"> + <tr id="ecd-table-header"> + <th width="50%">Name</th> + <th width="50%">Value</th> + </tr> + <tbody + ng-repeat="(pkey, pval) in ecdapp.appConfigOverride"> + <tr id="tr-rowData"> + <td> + <div style="font-weight: bold;">{{pkey}}</div> + </td> + <td><input class="span12" + type="text" + ng-keyup="ecdapp.refreshAppConfigOverride(pkey, pval);" + data-ng-model="ecdapp.appConfigOverride[pkey]" autofocus /> + </td> + </tr> + </tbody> + </table> + </div> + --> </div> - </div> - - <div class="span12"> - <div class="form-row"> - <label for="ignoreLiveNodesCheck"> </label> - <div class="field-group"> - <label for="ignoreLiveNodes" class="checkbox"> - <input id="ignoreLiveNodes" type="checkbox" ng-model="ecdapp.ignoreLiveNodes" /> - <i class="skin"></i><span>Ignore Live Nodes</span> - </label> + <div class="span3"> + <div class="form-row"> + <label style="text-decoration: underline;">Application Configuration</label> + <pre style="font-weight: bold;">{{ecdapp.app_config_latest_str}}</pre> </div> </div> - </div> - + </div> </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <!-- show progress indicator --> + <div style="width: 100%;"> + <div ng-show="ecdapp.updatingDeployment" + style="display: table; margin: 0 auto;" class="span"> + <i class="icon-spinner small" role="img" + aria-label="Update Deployment in Progress..."></i> Update + Deployment in Progress... + </div> + </div> + <div ng-hide="ecdapp.isDataLoading" class="b2b-modal-footer ng-scope ng-isolate-scope"> <div class="cta-button-group in"> <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.deleteDeploymentById(deployment);"> - Delete + ng-show="!ecdapp.updatingDeployment" + ng-click="ecdapp.reconfigDeploymentById(ecdapp.parmCurrFileDict);"> + Submit </button> <button class="btn btn-small" type="button" ng-click="$dismiss('cancel')"> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_table.html index c414484..211d17d 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_table.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_table.html @@ -1,93 +1,339 @@ <div id="page-content"> + <h1 class="heading-page" id="deployments-page">Deployments</h1> + <div style="float: right; margin-top: -20px;" class="span4 form-row"> + <div ng-show="ecdapp.groupByTenant" class="field-group span10"> + <label title="Cloudify Tenant" for="cldTenants">Tenant: {{ecdapp.selectedTenant}}</label> + <select id="cldTenants" name="cldTenants" b2b-dropdown placeholder-text="Select Tenant" + class="span8" + ng-model="ecdapp.selectedTenant" + ng-change="ecdapp.tenantChangeHandler()"> + <option b2b-dropdown-list + option-repeat="d in ecdapp.availableTenants" value="{{d}}">{{d}}</option> + </select> + </div> + </div> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div> + <div id="button-search-row" style="margin-left: 45px; width: 60%;" + ng-hide="ecdapp.isDataLoading"> + <div> + <div class="group"> + <div class="advanced-search"> + <button tabindex="-1" + style="position: absolute; margin-left: -35px; border: none; background: none; top: 5px;" + "class="btn btn-small" title="Reload view without applying basic filters" + type="button" ng-click="ecdapp.reloadTable()"> + <i class="icon-arrows-replay-restart"></i> + </button> + <button tabindex="1" + style="position: absolute; border: none; background: none; margin-left: 5px; top: 5px;" + "class="btn btn-medium" type="button" + ng-click="ecdapp.filterBySvc()"> + <i class="ion-search"></i> + </button> + <input tabindex="0" style="padding-left: 50px;" + class="advanced-search-input" type="text" + placeholder="Search Deployments" + title="multiple deployment name patterns - comma separated values" + ng-model="ecdapp.searchString" + ng-keydown="[13, 32].includes($event.keyCode) && ecdapp.filterBySvc()"></input> + <button type="button" id="show-menu-filters" + class="btn dropdown-toggle" + ng-click="ecdapp.toggleMoreFilters()" data-toggle="dropdown" + title="More Filters"> + <i class="icon-controls-down"></i> + </button> + </div> + </div> + <div class="menu-filters" ng-show="ecdapp.showingMoreFilters"> + <div class="group"> + <label class="col-sm-3 control-label">Service IDs: </label> + <ui-select multiple ng-model="ecdapp.selectedServices" + ng-disabled="ecdapp.usingAafFilter || ecdapp.usingDcaeTargetTypeFilter" + theme="bootstrap" close-on-select="false" title="Service ID"> + <ui-select-match class="ui-select-match">{{$item}}</ui-select-match> + <ui-select-choices class="ui-select-choices" + repeat="service in ecdapp.availableServices | filter:$select.search" + position='down'> {{service}} </ui-select-choices> </ui-select> + </div> + <div class="group" ng-hide="ecdapp.filterByUser"> + <label class="col-sm-3 control-label">Owners: </label> + <ui-select multiple ng-model="ecdapp.selectedOwner" + theme="bootstrap" close-on-select="false" + title="Blueprint owner"> <ui-select-match + class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices + class="ui-select-choices" + repeat="owner in ecdapp.bpOwners | filter:$select.search" + position='down'> {{owner}} </ui-select-choices> </ui-select> + </div> + <div class="group"> + <label class="col-sm-3 control-label">Status: </label> + <ui-select multiple ng-model="ecdapp.selectedStatus" + ng-disabled="ecdapp.usingAafFilter || ecdapp.usingDcaeTargetTypeFilter" + theme="bootstrap" close-on-select="false" + title="Install Status"> <ui-select-match + class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices + class="ui-select-choices" + repeat="status in ecdapp.availableStatus | filter:$select.search" + position='down'> {{status}} </ui-select-choices> </ui-select> + </div> + <div title="Helm only" style="margin-top: 10px;"> + <label for="checkbox1" class="checkbox"> <input + ng-disabled="ecdapp.usingAafFilter || ecdapp.usingDcaeTargetTypeFilter" + id="checkbox1" type="checkbox" ng-model="ecdapp.isHelmType"><i + class="skin"></i><span>Helm Chart Deployment</span> + </label> + </div> + <div class="group"> + <label class="col-sm-3 control-label">AAF Username: </label> <input + tabindex="0" class="advanced-search-input" type="text" + title="Filter by AAF Username in inputs - *Disables other fields*" + ng-disabled="ecdapp.usingDcaeTargetTypeFilter" + ng-model="ecdapp.aafUsernameString" + ng-change="ecdapp.handleDisableOtherFields()"></input> + </div> + <div class="group"> + <label class="col-sm-3 control-label">DCAE Target + Type: </label> <input tabindex="0" class="advanced-search-input" + type="text" + title="Filter by DCAE Target Type in inputs - *Disables other fields*" + ng-disabled="ecdapp.usingAafFilter" + ng-model="ecdapp.dcaeTargetTypeString" + ng-change="ecdapp.handleDisableOtherFields()"></input> + </div> + <div class="group" style="float: right;"> + <button tabindex="-1" class="btn btn-small" + title="Reset Filters" type="button" + ng-click="ecdapp.resetFilters()"> + <i class="icon-arrows-replay-restart"></i> + </button> + <button tabindex="1" class="btn btn-small" + title="Filtered search" type="button" + ng-click="ecdapp.extendedfilterSrch()"> + <i class="ion-search"></i> + </button> + </div> + </div> + </div> + </div> + <div id="depFilter" style="margin-left: 20px;margin-top: 10px; margin-bottom: 10px;" title="Additional filters"> + <label for="checkbox3" class="checkbox" style="margin-right: 100px;"> + <input id="checkbox3" type="checkbox" ng-model="ecdapp.filterByUser" ng-change="ecdapp.toggleUserFilt()" class="ng-valid ng-dirty ng-valid-parse ng-touched"> + <i class="skin"></i><span>My Deployments</span> + </label> + <label for="checkbox1" class="checkbox" style="margin-right: 20px;"> + <input id="checkbox1" type="checkbox" ng-model="ecdapp.useCache" ng-change="ecdapp.toggleRefresh()" class="ng-pristine ng-untouched ng-valid"> + <i class="skin"></i><span>Cache</span> + </label> + <label for="checkbox2" class="checkbox" > + <input id="checkbox2" type="checkbox" ng-model="ecdapp.groupByTenant" ng-change="ecdapp.toggleTenantFilt()" class="ng-valid ng-dirty ng-valid-parse ng-touched"> + <i class="skin"></i><span>Tenant</span> + </label> + </div> + </div> - <h1 class="heading-page" id="deployments-page">Deployments</h1> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> + <div ng-show="ecdapp.isRequestFailed"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-hide="ecdapp.isRequestFailed"> + <div b2b-table id="deployments-table" class="b2b-table-div" + table-data="ecdapp.tableData" + current-page="ecdapp.currentPageIgnored" + next-sort="ecdapp.nextSortIgnored"> + <table> + <thead b2b-table-row type="header"> + <tr id="th-header-row"> + <th b2b-table-header sortable="false" key="id" + ng-click="ecdapp.sortTable('id')">ID</th> + <th b2b-table-header sortable="false" key="blueprint_id" + ng-click="ecdapp.sortTable('blueprint_id')">Blueprint ID</th> + <!-- <th b2b-table-header key="description">Description</th> --> + <th b2b-table-header sortable="false" key="created_at" + ng-click="ecdapp.sortTable('created_at')">Created Date</th> + <th b2b-table-header sortable="false" key="owner" + ng-click="ecdapp.sortTable('created_at')">Owner</th> + <th b2b-table-header sortable="false" key="tenant" >Tenant</th> + <!-- <th b2b-table-header key="updated_at">Updated Date</th>--> + <th b2b-table-header sortable="false" key="status">Health</th> + <th b2b-table-header sortable="false">Actions</th> + <!-- <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> --> + </tr> + </thead> + <tbody b2b-table-row type="body" + row-repeat="rowData in ecdapp.tableData"> + <tr id="tr-rowData"> + <td b2b-table-body> + <div> + <div ng-if="rowData.lastExecution.status !== undefined" class="stat_tooltip" + style="width: 30px; position: relative;"> + <img ng-if="rowData.lastExecution.status !== undefined && + rowData.lastExecution.status == 'terminated'" + src="static/fusion/images/active.png"/> + <img ng-if="rowData.lastExecution.status !== undefined && + rowData.lastExecution.status == 'failed'" + src="static/fusion/images/inactive.png"/> + <img ng-if="rowData.lastExecution.status !== undefined && + rowData.lastExecution.status == 'started'" + src="static/fusion/images/loading.gif"/> + <img ng-if="rowData.lastExecution.status !== undefined && + rowData.lastExecution.status == 'pending'" + src="static/fusion/images/loading.gif"/> + <div class="wrapper"> + <div> + <span + style="left: 10px; font-weight: bold; position: relative; top: 10px;">Last + Execution in Cloudify</span> + <table> + <thead> + <tr> + <th>Workflow</th> + <th>Status</th> + <th>Created</th> + <th>Ended</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{rowData.lastExecution.workflow_id}}</td> + <td>{{rowData.lastExecution.status}}</td> + <td>{{rowData.lastExecution.created_at}}</td> + <td>{{rowData.lastExecution.ended_at}}</td> + </tr> + <div + style="position: relative; top: 150px; width: 250px; margin: 0 auto;"> + <button style="border-radius: 5px;" + ng-click="ecdapp.viewDeploymentExecutionsModalPopup(rowData)"> + View Executions</button> + </div> + </tbody> + </table> + </div> + </div> + </div> + <div style="position: relative; left: 10px;">{{rowData.id}}</div> + </div> + </td> + <td b2b-table-body> + <div ng-if="rowData.description !== undefined" class="gen_tooltip">{{rowData.blueprint_id}} + <div> + <span class="gen_tooltiptext_r">{{rowData.description}}</span> + </div> + </div> + <div ng-if="rowData.description === undefined">{{rowData.blueprint_id}}</div> + </td> + <td b2b-table-body ng-bind="rowData.created_at"/> + <!-- <td b2b-table-body ng-bind="rowData.updated_at" /> --> + <td b2b-table-body ng-bind="rowData.owner"/> + <td b2b-table-body ng-bind="rowData.tenant_name"/> + <td b2b-table-body> + <img ng-if="rowData.healthStatus == 'passing'" + src="static/fusion/images/active.png" + title="{{rowData.healthStatus}}" /> <img + ng-if="rowData.healthStatus == 'critical'" + src="static/fusion/images/inactive.png" + title="{{rowData.healthStatus}}" /> </span> + </td> + <td b2b-table-body> + <div class="btn-group btn-actions" + style="margin-bottom: 0; box-shadow: none;"> + <button type="button" class="btn dropdown-toggle" + data-toggle="dropdown" title="More Actions"> + <i class="icon-apps-marketplace"></i> + </button> + <ul class="dropdown-menu"> + <li> + <div ng-show="rowData.lastExecution.status != ''" + ng-click="ecdapp.getBlueprintDataModal(rowData);"> + <i class="icon-documents-book ecd-icon-action"></i><a + href="">View blueprint</a> + </div> + </li> + <li> + <div ng-show="rowData.lastExecution.status != ''" + ng-click="ecdapp.viewDeploymentInputsModalPopup(rowData);"> + <i class="icoDocuments-report ecd-icon-action"></i><a + href="">View Inputs</a> + </div> + </li> + <li> + <div ng-show="rowData.lastExecution.status != ''" + ng-click="ecdapp.viewDeploymentExecutionsModalPopup(rowData);"> + <i class="icon-overview ecd-icon-action"></i><a + href="">View executions</a> + </div> + </li> + <li> + <div + ng-show="rowData.canDeploy && rowData.lastExecution.status === 'terminated'" + ng-click="ecdapp.updateDeploymentModalPopup(rowData);"> + <i class="icon-misc-pen ecd-icon-action"></i><a + href="">Update deployment</a> + </div> + </li> + <li> + <div + ng-show="rowData.canDeploy && rowData.lastExecution.status != ''" + ng-click="ecdapp.deleteDeploymentModalPopup(rowData);"> + <i class="icon-misc-trash ecd-icon-action"></i><a + href="">Undeploy</a> + </div> + </li> + <li> + <div + ng-show="rowData.isHelm && rowData.helmStatus" + ng-click="ecdapp.checkHelmStatus(rowData);"> + <i class="icoDocuments-report ecd-icon-action"></i><a + href="">Helm Status</a> + </div> + </li> + <li> + <div + ng-show="rowData.canDeploy && rowData.isHelm" + ng-click="ecdapp.upgradeDeploymentModalPopup(rowData);"> + <i + class="icon-controls-down ecd-icon-action"></i><a + href="">Helm Upgrade</a> + </div> + </li> + <li> + <div + ng-show="rowData.canDeploy && rowData.isHelm" + ng-click="ecdapp.rollbackDeploymentModalPopup(rowData);"> + <i + class="icon-controls-up ecd-icon-action"></i><a + href="">Helm Rollback</a> + </div> + </li> + <li> + <div + ng-click="ecdapp.reconfigDeploymentModalPopup(rowData);"> + <i + class="icon-datanetwork-contentdelivery ecd-icon-action"></i><a + href="">Reconfigure</a> + </div> + </li> + </ul> + </div> <!-- .btn-group --> + </td> + </tr> + </tbody> + </table> + </div> + <div b2b-pagination="" total-pages="ecdapp.totalPages" + current-page="ecdapp.currentPageNum" + click-handler="pageChangeHandler" role="navigation"></div> + </div> +</div> +<div style="height: 10px;"> + <!-- space between page number and black footer --> +</div> - <div ng-hide="ecdapp.isDataLoading"> - - <div id="button-search-row"> - <div style="float:right;"> - <div class="form-field form-field__small"> - <input - type="text" - placeholder="Search Deployments" - ng-model="ecdapp.searchString"/> - </div> - </div> - </div> - - <div ng-show="ecdapp.isRequestFailed"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.isRequestFailed"> - - <div - b2b-table - id="deployments-table" - class="b2b-table-div" - table-data="ecdapp.tableData" - search-string="ecdapp.searchString" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - - <table> - - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header key="deployment_id">ID</th> - <th b2b-table-header key="blueprint_id">Blueprint ID</th> - <th b2b-table-header key="description">Description</th> - <th b2b-table-header key="created_at">Created Date</th> - <th b2b-table-header key="updated_at">Updated Date</th> - <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> - </tr> - </thead> - - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData"> - <tr id="tr-rowData"> - <td b2b-table-body - ng-bind="rowData.id"/> - <td b2b-table-body - ng-bind="rowData.blueprint_id"/> - <td b2b-table-body - ng-bind="rowData.description"/> - <td b2b-table-body - ng-bind="rowData.created_at"/> - <td b2b-table-body - ng-bind="rowData.updated_at"/> - <td b2b-table-body> - <div ng-click="ecdapp.createExecutionModalPopup(rowData);"> - <a href="" title="Create execution" class="icon-controls-playalt ecd-icon-action"></a> - </div> - <div ng-click="ecdapp.deleteDeploymentModalPopup(rowData);"> - <a href="" title="Delete deployment" class="icon-misc-trash ecd-icon-action"></a> - </div> - </td> - </tr> - </tbody> - </table> - </div> - - <div b2b-pagination="" total-pages="ecdapp.totalPages" - current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler" - role="navigation"> - </div> - - </div> - </div> - - <div style="height: 10px;"> - <!-- space between page number and black footer --> - </div> - - </div><!-- loading --> - -</div><!-- page content --> +<!-- loading --> +<!-- page content --> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/execution-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/execution-service.js index 34414c4..e4a8879 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/execution-service.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/execution-service.js @@ -1,24 +1,3 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ appDS2.factory('ExecutionService', function ($http, $q, $log) { return { /** @@ -88,8 +67,8 @@ appDS2.factory('ExecutionService', function ($http, $q, $log) { }); }, - cancelExecution: function(id, deploymentId, action) { - let url = 'executions/' + id + '?deployment_id=' + deploymentId + '&action=' + action; + cancelExecution: function(id, deploymentId, action, tenant) { + let url = 'executions/' + id + '?deployment_id=' + deploymentId + '&action=' + action + '&tenant=' + tenant; return $http({ method: 'DELETE', url: url, @@ -105,6 +84,6 @@ appDS2.factory('ExecutionService', function ($http, $q, $log) { $log.error('ExecutionService.cancelExecution failed: ' + JSON.stringify(error)); return $q.reject(error.statusText); }); - } + }, }; }); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-service.js new file mode 100644 index 0000000..0d34db3 --- /dev/null +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-service.js @@ -0,0 +1,31 @@ +appDS2.factory('PluginService', function ($http, $q, $log) { + return { + /** + * Gets one page of objects. + * @param {Number} pageNum - page number; e.g., 1 + * @param {Number} viewPerPage - number of items per page; e.g., 25 + * @return {JSON} Response object from remote side + */ + getPlugins: function(pageNum,viewPerPage) { + // cache control for IE + let cc = "&cc=" + new Date().getTime().toString(); + let url = 'plugins?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('PluginService.getPlugins: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('PluginService.getPlugins failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + } + + }; +}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-table-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-table-controller.js new file mode 100644 index 0000000..23b59aa --- /dev/null +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-table-controller.js @@ -0,0 +1,64 @@ +appDS2.controller('PluginsTableController', function( + $rootScope, $scope, $log, $modal, modalService, PluginService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + // models for controls on screen + $scope.ecdapp.tableData = []; + $scope.ecdapp.currentPageNum = 1; + $scope.ecdapp.viewPerPage = 10; + // other + $scope.ecdapp.errMsg = null; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.isRequestFailed = false; + + /** + * Loads the table. Interprets the remote controller's response and copies + * to scope variables. The response is either a list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.loadTable = function() { + $scope.ecdapp.isDataLoading = true; + PluginService.getPlugins($scope.ecdapp.currentPageNum, + $scope.ecdapp.viewPerPage).then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("PluginsTableController.loadTable failed: " + + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.tableData = jsonObj; + } + $scope.ecdapp.isDataLoading = false; + }, + function(error) { + $log.error("PluginsTableController.loadTable failed: " + + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + }); + }; + + /** + * Invoked at first page load AND when + * user clicks on the B2B pagination control. + */ + $scope.pageChangeHandler = function(page) { + if (debug) + console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); + $scope.ecdapp.currentPageNum = page; + $scope.ecdapp.loadTable(); + } + +}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin_table.html index 965b701..99935b8 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller_table.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin_table.html @@ -1,7 +1,5 @@ <div id="page-content"> - - <h1 class="heading-page" id="controllers">ECOMP-C Instances</h1> - + <h1 class="heading-page" id="plugins-page">Cloudify Plugins</h1> <!-- show progress indicator --> <div ng-show="ecdapp.isDataLoading"> <div class="span" style="margin-bottom:20px;"> @@ -10,14 +8,13 @@ </div> </div> - <div ng-hide="ecdapp.isDataLoading"> - + <div ng-hide="ecdapp.isDataLoading"> <div id="button-search-row"> <div style="float:right;"> <div class="form-field form-field__small"> <input type="text" - placeholder="Search Controllers" + placeholder="Search Plugins" ng-model="ecdapp.searchString"/> </div> </div> @@ -27,53 +24,48 @@ <span class="ecd-error-message">{{ecdapp.errMsg}}</span> </div> - <div ng-hide="ecdapp.isRequestFailed"> - + <div ng-hide="ecdapp.isRequestFailed"> <div b2b-table - id="controllers-table" + id="plugins-table" class="b2b-table-div" table-data="ecdapp.tableData" search-string="ecdapp.searchString" current-page="ecdapp.currentPageIgnored" next-sort="ecdapp.nextSortIgnored"> - - <table> - + <table> <thead b2b-table-row type="header"> <tr id="th-header-row"> - <th b2b-table-header sortable="false">Selected</th> - <th b2b-table-header key="name">Name</th> - <th b2b-table-header key="url">URL</th> + <th b2b-table-header key="name">Package name</th> + <th b2b-table-header key="version">Package version</th> + <th b2b-table-header key="platform">Supported Platform</th> + <th b2b-table-header key="distribution">Distribution</th> + <th b2b-table-header key="uploaded_at">Uploaded at</th> </tr> </thead> <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData"> <tr id="tr-rowData"> - <td b2b-table-body> - <label class="radio"> - <input - type="radio" - name="ecdSelGroup" - title="rowData.url" - ng-value="rowData.url" - ng-model="ecdapp.radiobutton.url" - ng-change="ecdapp.selectController(rowData);"> - <i class="skin"></i> - <span></span> - </label> - </td> <td b2b-table-body - ng-bind="rowData.name"/> + ng-bind="rowData.package_name"/> <td b2b-table-body - ng-bind="rowData.url"/> + ng-bind="rowData.package_version"/> + <td b2b-table-body + ng-bind="rowData.supported_platform"/> + <td b2b-table-body + ng-bind="rowData.distribution"/> + <td b2b-table-body + ng-bind="rowData.uploaded_at"/> </tr> </tbody> </table> </div> - <!-- no pagination --> - + <div b2b-pagination="" total-pages="ecdapp.totalPages" + current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler" + role="navigation"> + </div> + </div> <div style="height: 10px;"> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca-table-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca-table-controller.js deleted file mode 100644 index cafc517..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca-table-controller.js +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -appDS2.controller('toscaTableController', function( - $rootScope, $scope, $log, $modal, modalService, ExecutionService) { - - 'use strict'; - - // this object holds all app data and functions - $scope.ecdapp = {}; - // models for controls on screen - $scope.ecdapp.tableData = []; - $scope.ecdapp.currentPageNum = 1; - $scope.ecdapp.viewPerPage = 10; - // other - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; - - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either a list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.loadTable = function() { - var toBeDefined = true; - if (toBeDefined) { - $scope.ecdapp.isDataLoading = false; - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = 'TOSCA Models not available (yet).'; - } - else { - $scope.ecdapp.isDataLoading = true; - ExecutionService.getExecutions($scope.ecdapp.currentPageNum, - $scope.ecdapp.viewPerPage).then( - function(jsonObj) { - if (jsonObj.error) { - $log.error("executionController.loadTable failed: " - + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error("executionController.loadTable failed: " - + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - } - }; - - /** - * Invoked at first page load AND when - * user clicks on the B2B pagination control. - */ - $scope.pageChangeHandler = function(page) { - // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); - $scope.ecdapp.currentPageNum = page; - $scope.ecdapp.loadTable(); - } - - /** - * Shows a modal pop-up to confirm deletion. - * On successful completion, updates the table. - */ - $scope.ecdapp.deleteToscaModalPopup = function(execution) { - modalService.popupConfirmWin("Confirm", "Delete TOSCA model with ID '" - + execution.id + "'?", function() { - // TODO: gather action from user - }) - }; - - // Populate the table on load. Note that the b2b selector code - // sets the page-number value, and the change event calls load table. - // Do not call this here to avoid double load: - // $scope.ecdapp.loadTable(); - -}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca_table.html deleted file mode 100644 index affec91..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca_table.html +++ /dev/null @@ -1,87 +0,0 @@ -<div id="page-content"> - - <h1 class="heading-page" id="blueprints-page">TOSCA Models</h1> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-hide="ecdapp.isDataLoading"> - - <div id="button-search-row"> - <div style="float:right;"> - <div class="form-field form-field__small"> - <input - type="text" - placeholder="Search TOSCA Models" - ng-model="ecdapp.searchString"/> - </div> - </div> - </div> - - <div ng-show="ecdapp.isRequestFailed"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.isRequestFailed"> - - <div - b2b-table - id="tosca-table" - class="b2b-table-div" - table-data="ecdapp.tableData" - search-string="ecdapp.searchString" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - - <table> - - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header key="id">ID</th> - <th b2b-table-header key="name">Name</th> - <th b2b-table-header key="description">Description</th> - <th b2b-table-header key="created_at">Created Date</th> - <th b2b-table-header key="updated_at">Updated Date</th> - <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> - </tr> - </thead> - - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData"> - <tr id="tr-rowData"> - <td b2b-table-body - ng-bind="rowData.id"/> - <td b2b-table-body - ng-bind="rowData.main_file_name"/> - <td b2b-table-body - ng-bind="rowData.description"/> - <td b2b-table-body - ng-bind="rowData.created_at"/> - <td b2b-table-body - ng-bind="rowData.updated_at"/> - <td b2b-table-body> - <div ng-click="ecdapp.deleteToscaModalPopup(rowData);"> - <a href="" title="Delete TOSCA model" class="icon-misc-trash ecd-icon-action"></a> - </div> - </td> - </tr> - </tbody> - </table> - </div> - - <div b2b-pagination="" total-pages="ecdapp.totalPages" - current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler" - role="navigation"> - </div> - - <div style="height: 10px;"> - <!-- space between page number and black footer --> - </div> - - </div><!-- loading --> - -</div><!-- page content --> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/node_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/node_table.html index 670fa6a..5471dbd 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/node_table.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/node_table.html @@ -47,7 +47,7 @@ <th b2b-table-header key="node">Node Name</th> <th b2b-table-header key="id">Node ID</th> <th b2b-table-header key="address">Address</th> - <th b2b-table-header sortable="false"><i class="icon-settings ecd-icon-display"></i></th> + <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> </tr> </thead> @@ -59,7 +59,7 @@ <td b2b-table-body ng-bind="rowData.address" /> <td b2b-table-body> <div ng-click="ecdapp.viewServicesModalPopup(rowData, ecdapp.datacenter);"> - <a href="" title="View node services" class="icon-overview ecd-icon-action"></a> + <a href="" title="View node services" class="icon-people-preview ecd-icon-action"></a> </div> </td> </tr> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/service_health_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/service_health_table.html index 40e8d95..56a7345 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/service_health_table.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/service_health_table.html @@ -50,9 +50,10 @@ <th b2b-table-header key="status">Status</th> <th b2b-table-header key="node">Node Name</th> <th b2b-table-header key="serviceID">Service ID</th> + <th b2b-table-header key="serviceID">Tenant</th> <th b2b-table-header key="notes">Notes</th> <th b2b-table-header key="output">Output</th> - <th b2b-table-header sortable="false"><i class="icon-settings ecd-icon-display"></i></th> + <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> </tr> </thead> @@ -69,11 +70,12 @@ </td> <td b2b-table-body ng-bind="rowData.node" /> <td b2b-table-body ng-bind="rowData.serviceID" /> + <td b2b-table-body ng-bind="rowData.tenant" /> <td b2b-table-body ng-bind="rowData.notes" /> <td b2b-table-body ng-bind="rowData.output" /> <td b2b-table-body> <div ng-click="ecdapp.viewHealthHistoryModalPopup(rowData);"> - <a href="" title="View history" class="icoDocuments-bookmarks ecd-icon-action"></a> + <a href="" title="View history" class="icon-datanetwork-history ecd-icon-action"></a> </div> <div ng-click="ecdapp.deregisterServiceModalPopup(rowData);"> <a href="" title="Deregister service" class="icon-misc-trash ecd-icon-action"></a> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/angular-local-storage.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/angular-local-storage.js new file mode 100644 index 0000000..a936f14 --- /dev/null +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/angular-local-storage.js @@ -0,0 +1,592 @@ +/** + * An Angular module that gives you access to the browsers local storage + * @version v0.7.1 - 2017-06-21 + * @link https://github.com/grevory/angular-local-storage + * @author grevory <greg@gregpike.ca> + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +(function (window, angular) { +var isDefined = angular.isDefined, + isUndefined = angular.isUndefined, + isNumber = angular.isNumber, + isObject = angular.isObject, + isArray = angular.isArray, + isString = angular.isString, + extend = angular.extend, + toJson = angular.toJson; + +angular + .module('LocalStorageModule', []) + .provider('localStorageService', function() { + // You should set a prefix to avoid overwriting any local storage variables from the rest of your app + // e.g. localStorageServiceProvider.setPrefix('yourAppName'); + // With provider you can use config as this: + // myApp.config(function (localStorageServiceProvider) { + // localStorageServiceProvider.prefix = 'yourAppName'; + // }); + this.prefix = 'ls'; + + // You could change web storage type localstorage or sessionStorage + this.storageType = 'localStorage'; + + // Cookie options (usually in case of fallback) + // expiry = Number of days before cookies expire // 0 = Does not expire + // path = The web path the cookie represents + // secure = Wether the cookies should be secure (i.e only sent on HTTPS requests) + this.cookie = { + expiry: 30, + path: '/', + secure: false + }; + + // Decides wether we should default to cookies if localstorage is not supported. + this.defaultToCookie = true; + + // Send signals for each of the following actions? + this.notify = { + setItem: true, + removeItem: false + }; + + // Setter for the prefix + this.setPrefix = function(prefix) { + this.prefix = prefix; + return this; + }; + + // Setter for the storageType + this.setStorageType = function(storageType) { + this.storageType = storageType; + return this; + }; + // Setter for defaultToCookie value, default is true. + this.setDefaultToCookie = function (shouldDefault) { + this.defaultToCookie = !!shouldDefault; // Double-not to make sure it's a bool value. + return this; + }; + // Setter for cookie config + this.setStorageCookie = function(exp, path, secure) { + this.cookie.expiry = exp; + this.cookie.path = path; + this.cookie.secure = secure; + return this; + }; + + // Setter for cookie domain + this.setStorageCookieDomain = function(domain) { + this.cookie.domain = domain; + return this; + }; + + // Setter for notification config + // itemSet & itemRemove should be booleans + this.setNotify = function(itemSet, itemRemove) { + this.notify = { + setItem: itemSet, + removeItem: itemRemove + }; + return this; + }; + + this.$get = ['$rootScope', '$window', '$document', '$parse','$timeout', function($rootScope, $window, $document, $parse, $timeout) { + var self = this; + var prefix = self.prefix; + var cookie = self.cookie; + var notify = self.notify; + var storageType = self.storageType; + var webStorage; + + // When Angular's $document is not available + if (!$document) { + $document = document; + } else if ($document[0]) { + $document = $document[0]; + } + + // If there is a prefix set in the config lets use that with an appended period for readability + if (prefix.substr(-1) !== '.') { + prefix = !!prefix ? prefix + '.' : ''; + } + var deriveQualifiedKey = function(key) { + return prefix + key; + }; + + // Removes prefix from the key. + var underiveQualifiedKey = function (key) { + return key.replace(new RegExp('^' + prefix, 'g'), ''); + }; + + // Check if the key is within our prefix namespace. + var isKeyPrefixOurs = function (key) { + return key.indexOf(prefix) === 0; + }; + + // Checks the browser to see if local storage is supported + var checkSupport = function () { + try { + var supported = (storageType in $window && $window[storageType] !== null); + + // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage + // is available, but trying to call .setItem throws an exception. + // + // "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage + // that exceeded the quota." + var key = deriveQualifiedKey('__' + Math.round(Math.random() * 1e7)); + if (supported) { + webStorage = $window[storageType]; + webStorage.setItem(key, ''); + webStorage.removeItem(key); + } + + return supported; + } catch (e) { + // Only change storageType to cookies if defaulting is enabled. + if (self.defaultToCookie) + storageType = 'cookie'; + $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); + return false; + } + }; + var browserSupportsLocalStorage = checkSupport(); + + // Directly adds a value to local storage + // If local storage is not available in the browser use cookies + // Example use: localStorageService.add('library','angular'); + var addToLocalStorage = function (key, value, type) { + var previousType = getStorageType(); + + try { + setStorageType(type); + + // Let's convert undefined values to null to get the value consistent + if (isUndefined(value)) { + value = null; + } else { + value = toJson(value); + } + + // If this browser does not support local storage use cookies + if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') { + if (!browserSupportsLocalStorage) { + $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED'); + } + + if (notify.setItem) { + $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: 'cookie'}); + } + return addToCookies(key, value); + } + + try { + if (webStorage) { + webStorage.setItem(deriveQualifiedKey(key), value); + } + if (notify.setItem) { + $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType}); + } + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); + return addToCookies(key, value); + } + return true; + } finally { + setStorageType(previousType); + } + }; + + // Directly get a value from local storage + // Example use: localStorageService.get('library'); // returns 'angular' + var getFromLocalStorage = function (key, type) { + var previousType = getStorageType(); + + try { + setStorageType(type); + + if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') { + if (!browserSupportsLocalStorage) { + $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED'); + } + + return getFromCookies(key); + } + + var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null; + // angular.toJson will convert null to 'null', so a proper conversion is needed + // FIXME not a perfect solution, since a valid 'null' string can't be stored + if (!item || item === 'null') { + return null; + } + + try { + return JSON.parse(item); + } catch (e) { + return item; + } + } finally { + setStorageType(previousType); + } + }; + + // Remove an item from local storage + // Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular' + // + // This is var-arg removal, check the last argument to see if it is a storageType + // and set type accordingly before removing. + // + var removeFromLocalStorage = function () { + var previousType = getStorageType(); + + try { + // can't pop on arguments, so we do this + var consumed = 0; + if (arguments.length >= 1 && + (arguments[arguments.length - 1] === 'localStorage' || + arguments[arguments.length - 1] === 'sessionStorage')) { + consumed = 1; + setStorageType(arguments[arguments.length - 1]); + } + + var i, key; + for (i = 0; i < arguments.length - consumed; i++) { + key = arguments[i]; + if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') { + if (!browserSupportsLocalStorage) { + $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED'); + } + + if (notify.removeItem) { + $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: 'cookie'}); + } + removeFromCookies(key); + } + else { + try { + webStorage.removeItem(deriveQualifiedKey(key)); + if (notify.removeItem) { + $rootScope.$broadcast('LocalStorageModule.notification.removeitem', { + key: key, + storageType: self.storageType + }); + } + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); + removeFromCookies(key); + } + } + } + } finally { + setStorageType(previousType); + } + }; + + // Return array of keys for local storage + // Example use: var keys = localStorageService.keys() + var getKeysForLocalStorage = function (type) { + var previousType = getStorageType(); + + try { + setStorageType(type); + + if (!browserSupportsLocalStorage) { + $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED'); + return []; + } + + var prefixLength = prefix.length; + var keys = []; + for (var key in webStorage) { + // Only return keys that are for this app + if (key.substr(0, prefixLength) === prefix) { + try { + keys.push(key.substr(prefixLength)); + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error', e.Description); + return []; + } + } + } + + return keys; + } finally { + setStorageType(previousType); + } + }; + + // Remove all data for this app from local storage + // Also optionally takes a regular expression string and removes the matching key-value pairs + // Example use: localStorageService.clearAll(); + // Should be used mostly for development purposes + var clearAllFromLocalStorage = function (regularExpression, type) { + var previousType = getStorageType(); + + try { + setStorageType(type); + + // Setting both regular expressions independently + // Empty strings result in catchall RegExp + var prefixRegex = !!prefix ? new RegExp('^' + prefix) : new RegExp(); + var testRegex = !!regularExpression ? new RegExp(regularExpression) : new RegExp(); + + if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') { + if (!browserSupportsLocalStorage) { + $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED'); + } + return clearAllFromCookies(); + } + if (!browserSupportsLocalStorage && !self.defaultToCookie) + return false; + var prefixLength = prefix.length; + + for (var key in webStorage) { + // Only remove items that are for this app and match the regular expression + if (prefixRegex.test(key) && testRegex.test(key.substr(prefixLength))) { + try { + removeFromLocalStorage(key.substr(prefixLength)); + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); + return clearAllFromCookies(); + } + } + } + + return true; + } finally { + setStorageType(previousType); + } + }; + + // Checks the browser to see if cookies are supported + var browserSupportsCookies = (function() { + try { + return $window.navigator.cookieEnabled || + ("cookie" in $document && ($document.cookie.length > 0 || + ($document.cookie = "test").indexOf.call($document.cookie, "test") > -1)); + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); + return false; + } + }()); + + // Directly adds a value to cookies + // Typically used as a fallback if local storage is not available in the browser + // Example use: localStorageService.cookie.add('library','angular'); + var addToCookies = function (key, value, daysToExpiry, secure) { + + if (isUndefined(value)) { + return false; + } else if(isArray(value) || isObject(value)) { + value = toJson(value); + } + + if (!browserSupportsCookies) { + $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED'); + return false; + } + + try { + var expiry = '', + expiryDate = new Date(), + cookieDomain = ''; + + if (value === null) { + // Mark that the cookie has expired one day ago + expiryDate.setTime(expiryDate.getTime() + (-1 * 24 * 60 * 60 * 1000)); + expiry = "; expires=" + expiryDate.toGMTString(); + value = ''; + } else if (isNumber(daysToExpiry) && daysToExpiry !== 0) { + expiryDate.setTime(expiryDate.getTime() + (daysToExpiry * 24 * 60 * 60 * 1000)); + expiry = "; expires=" + expiryDate.toGMTString(); + } else if (cookie.expiry !== 0) { + expiryDate.setTime(expiryDate.getTime() + (cookie.expiry * 24 * 60 * 60 * 1000)); + expiry = "; expires=" + expiryDate.toGMTString(); + } + if (!!key) { + var cookiePath = "; path=" + cookie.path; + if (cookie.domain) { + cookieDomain = "; domain=" + cookie.domain; + } + /* Providing the secure parameter always takes precedence over config + * (allows developer to mix and match secure + non-secure) */ + if (typeof secure === 'boolean') { + if (secure === true) { + /* We've explicitly specified secure, + * add the secure attribute to the cookie (after domain) */ + cookieDomain += "; secure"; + } + // else - secure has been supplied but isn't true - so don't set secure flag, regardless of what config says + } + else if (cookie.secure === true) { + // secure parameter wasn't specified, get default from config + cookieDomain += "; secure"; + } + $document.cookie = deriveQualifiedKey(key) + "=" + encodeURIComponent(value) + expiry + cookiePath + cookieDomain; + } + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error', e.message); + return false; + } + return true; + }; + + // Directly get a value from a cookie + // Example use: localStorageService.cookie.get('library'); // returns 'angular' + var getFromCookies = function (key) { + if (!browserSupportsCookies) { + $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED'); + return false; + } + + var cookies = $document.cookie && $document.cookie.split(';') || []; + for(var i=0; i < cookies.length; i++) { + var thisCookie = cookies[i]; + while (thisCookie.charAt(0) === ' ') { + thisCookie = thisCookie.substring(1,thisCookie.length); + } + if (thisCookie.indexOf(deriveQualifiedKey(key) + '=') === 0) { + var storedValues = decodeURIComponent(thisCookie.substring(prefix.length + key.length + 1, thisCookie.length)); + try { + var parsedValue = JSON.parse(storedValues); + return typeof(parsedValue) === 'number' ? storedValues : parsedValue; + } catch(e) { + return storedValues; + } + } + } + return null; + }; + + var removeFromCookies = function (key) { + addToCookies(key,null); + }; + + var clearAllFromCookies = function () { + var thisCookie = null; + var prefixLength = prefix.length; + var cookies = $document.cookie.split(';'); + for(var i = 0; i < cookies.length; i++) { + thisCookie = cookies[i]; + + while (thisCookie.charAt(0) === ' ') { + thisCookie = thisCookie.substring(1, thisCookie.length); + } + + var key = thisCookie.substring(prefixLength, thisCookie.indexOf('=')); + removeFromCookies(key); + } + }; + + var getStorageType = function() { + return storageType; + }; + + var setStorageType = function(type) { + if (type && storageType !== type) { + storageType = type; + browserSupportsLocalStorage = checkSupport(); + } + return browserSupportsLocalStorage; + }; + + // Add a listener on scope variable to save its changes to local storage + // Return a function which when called cancels binding + var bindToScope = function(scope, key, def, lsKey, type) { + lsKey = lsKey || key; + var value = getFromLocalStorage(lsKey, type); + + if (value === null && isDefined(def)) { + value = def; + } else if (isObject(value) && isObject(def)) { + value = extend(value, def); + } + + $parse(key).assign(scope, value); + + return scope.$watch(key, function(newVal) { + addToLocalStorage(lsKey, newVal, type); + }, isObject(scope[key])); + }; + + // Add listener to local storage, for update callbacks. + if (browserSupportsLocalStorage) { + if ($window.addEventListener) { + $window.addEventListener("storage", handleStorageChangeCallback, false); + $rootScope.$on('$destroy', function() { + $window.removeEventListener("storage", handleStorageChangeCallback); + }); + } else if($window.attachEvent){ + // attachEvent and detachEvent are proprietary to IE v6-10 + $window.attachEvent("onstorage", handleStorageChangeCallback); + $rootScope.$on('$destroy', function() { + $window.detachEvent("onstorage", handleStorageChangeCallback); + }); + } + } + + // Callback handler for storage changed. + function handleStorageChangeCallback(e) { + if (!e) { e = $window.event; } + if (notify.setItem) { + if (isString(e.key) && isKeyPrefixOurs(e.key)) { + var key = underiveQualifiedKey(e.key); + // Use timeout, to avoid using $rootScope.$apply. + $timeout(function () { + $rootScope.$broadcast('LocalStorageModule.notification.changed', { key: key, newvalue: e.newValue, storageType: self.storageType }); + }); + } + } + } + + // Return localStorageService.length + // ignore keys that not owned + var lengthOfLocalStorage = function(type) { + var previousType = getStorageType(); + + try { + setStorageType(type); + + var count = 0; + var storage = $window[storageType]; + for(var i = 0; i < storage.length; i++) { + if(storage.key(i).indexOf(prefix) === 0 ) { + count++; + } + } + + return count; + } finally { + setStorageType(previousType); + } + }; + + var changePrefix = function(localStoragePrefix) { + prefix = localStoragePrefix; + }; + + return { + isSupported: browserSupportsLocalStorage, + getStorageType: getStorageType, + setStorageType: setStorageType, + setPrefix: changePrefix, + set: addToLocalStorage, + add: addToLocalStorage, //DEPRECATED + get: getFromLocalStorage, + keys: getKeysForLocalStorage, + remove: removeFromLocalStorage, + clearAll: clearAllFromLocalStorage, + bind: bindToScope, + deriveKey: deriveQualifiedKey, + underiveKey: underiveQualifiedKey, + length: lengthOfLocalStorage, + defaultToCookie: this.defaultToCookie, + cookie: { + isSupported: browserSupportsCookies, + set: addToCookies, + add: addToCookies, //DEPRECATED + get: getFromCookies, + remove: removeFromCookies, + clearAll: clearAllFromCookies + } + }; + }]; + }); +})(window, window.angular);
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.css b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.css new file mode 100644 index 0000000..0e713bb --- /dev/null +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.css @@ -0,0 +1,362 @@ +/*! + * ui-select + * http://github.com/angular-ui/ui-select + * Version: 0.19.7 - 2017-04-15T14:28:36.790Z + * License: MIT + */ + + +/* Style when highlighting a search. */ +.ui-select-highlight { + font-weight: bold; +} + +.ui-select-offscreen { + clip: rect(0 0 0 0) !important; + width: 1px !important; + height: 1px !important; + border: 0 !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + position: absolute !important; + outline: 0 !important; + left: 0px !important; + top: 0px !important; +} + + +.ui-select-choices-row:hover { + background-color: #f5f5f5; +} + +/* Select2 theme */ + +/* Mark invalid Select2 */ +.ng-dirty.ng-invalid > a.select2-choice { + border-color: #D44950; +} + +.select2-result-single { + padding-left: 0; +} + +.select2-locked > .select2-search-choice-close{ + display:none; +} + +.select-locked > .ui-select-match-close{ + display:none; +} + +body > .select2-container.open { + z-index: 9999; /* The z-index Select2 applies to the select2-drop */ +} + +/* Handle up direction Select2 */ +.ui-select-container[theme="select2"].direction-up .ui-select-match, +.ui-select-container.select2.direction-up .ui-select-match { + border-radius: 4px; /* FIXME hardcoded value :-/ */ + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.ui-select-container[theme="select2"].direction-up .ui-select-dropdown, +.ui-select-container.select2.direction-up .ui-select-dropdown { + border-radius: 4px; /* FIXME hardcoded value :-/ */ + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + + border-top-width: 1px; /* FIXME hardcoded value :-/ */ + border-top-style: solid; + + box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25); + + margin-top: -4px; /* FIXME hardcoded value :-/ */ +} +.ui-select-container[theme="select2"].direction-up .ui-select-dropdown .select2-search, +.ui-select-container.select2.direction-up .ui-select-dropdown .select2-search { + margin-top: 4px; /* FIXME hardcoded value :-/ */ +} +.ui-select-container[theme="select2"].direction-up.select2-dropdown-open .ui-select-match, +.ui-select-container.select2.direction-up.select2-dropdown-open .ui-select-match { + border-bottom-color: #5897fb; +} + +.ui-select-container[theme="select2"] .ui-select-dropdown .ui-select-search-hidden, +.ui-select-container[theme="select2"] .ui-select-dropdown .ui-select-search-hidden input{ + opacity: 0; + height: 0; + min-height: 0; + padding: 0; + margin: 0; + border:0; +} + +/* Selectize theme */ + +/* Helper class to show styles when focus */ +.selectize-input.selectize-focus{ + border-color: #007FBB !important; +} + +/* Fix input width for Selectize theme */ +.selectize-control.single > .selectize-input > input { + width: 100%; +} + +/* Fix line break when there's at least one item selected with the Selectize theme */ +.selectize-control.multi > .selectize-input > input { + margin: 0 !important; +} + +/* Fix dropdown width for Selectize theme */ +.selectize-control > .selectize-dropdown { + width: 100%; +} + +/* Mark invalid Selectize */ +.ng-dirty.ng-invalid > div.selectize-input { + border-color: #D44950; +} + +/* Handle up direction Selectize */ +.ui-select-container[theme="selectize"].direction-up .ui-select-dropdown { + box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25); + margin-top: -2px; /* FIXME hardcoded value :-/ */ +} + +.ui-select-container[theme="selectize"] input.ui-select-search-hidden{ + opacity: 0; + height: 0; + min-height: 0; + padding: 0; + margin: 0; + border:0; + width: 0; +} + +/* Bootstrap theme */ + +/* Helper class to show styles when focus */ +.btn-default-focus { + color: #333; + background-color: #EBEBEB; + border-color: #ADADAD; + text-decoration: none; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); +} + +.ui-select-bootstrap .ui-select-toggle { + position: relative; +} + +.ui-select-bootstrap .ui-select-toggle > .caret { + position: absolute; + height: 10px; + top: 50%; + right: 10px; + margin-top: -2px; +} + +/* Fix Bootstrap dropdown position when inside a input-group */ +.input-group > .ui-select-bootstrap.dropdown { + /* Instead of relative */ + position: static; +} + +.input-group > .ui-select-bootstrap > input.ui-select-search.form-control { + border-radius: 4px; /* FIXME hardcoded value :-/ */ + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group > .ui-select-bootstrap > input.ui-select-search.form-control.direction-up { + border-radius: 4px !important; /* FIXME hardcoded value :-/ */ + border-top-right-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +.ui-select-bootstrap .ui-select-search-hidden{ + opacity: 0; + height: 0; + min-height: 0; + padding: 0; + margin: 0; + border:0; +} + +.ui-select-bootstrap > .ui-select-match > .btn{ + /* Instead of center because of .btn */ + text-align: left !important; +} + +.ui-select-bootstrap > .ui-select-match > .caret { + position: absolute; + top: 45%; + right: 15px; +} + +/* See Scrollable Menu with Bootstrap 3 http://stackoverflow.com/questions/19227496 */ +.ui-select-bootstrap > .ui-select-choices ,.ui-select-bootstrap > .ui-select-no-choice { + width: 100%; + height: auto; + max-height: 200px; + overflow-x: hidden; + margin-top: -1px; +} + +body > .ui-select-bootstrap.open { + z-index: 1000; /* Standard Bootstrap dropdown z-index */ +} + +.ui-select-multiple.ui-select-bootstrap { + height: auto; + padding: 3px 3px 0 3px; +} + +.ui-select-multiple.ui-select-bootstrap input.ui-select-search { + background-color: transparent !important; /* To prevent double background when disabled */ + border: none; + outline: none; + height: 1.666666em; + margin-bottom: 3px; +} + +.ui-select-multiple.ui-select-bootstrap .ui-select-match .close { + font-size: 1.6em; + line-height: 0.75; +} + +.ui-select-multiple.ui-select-bootstrap .ui-select-match-item { + outline: 0; + margin: 0 3px 3px 0; +} + +.ui-select-multiple .ui-select-match-item { + position: relative; +} + +.ui-select-multiple .ui-select-match-item.dropping .ui-select-match-close { + pointer-events: none; +} + +.ui-select-multiple:hover .ui-select-match-item.dropping-before:before { + content: ""; + position: absolute; + top: 0; + right: 100%; + height: 100%; + margin-right: 2px; + border-left: 1px solid #428bca; +} + +.ui-select-multiple:hover .ui-select-match-item.dropping-after:after { + content: ""; + position: absolute; + top: 0; + left: 100%; + height: 100%; + margin-left: 2px; + border-right: 1px solid #428bca; +} + +.ui-select-bootstrap .ui-select-choices-row>span { + cursor: pointer; + display: block; + padding: 3px 20px; + clear: both; + font-weight: 400; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} + +.ui-select-bootstrap .ui-select-choices-row>span:hover, .ui-select-bootstrap .ui-select-choices-row>span:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} + +.ui-select-bootstrap .ui-select-choices-row.active>span { + color: #fff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} + +.ui-select-bootstrap .ui-select-choices-row.disabled>span, +.ui-select-bootstrap .ui-select-choices-row.active.disabled>span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} + +/* fix hide/show angular animation */ +.ui-select-match.ng-hide-add, +.ui-select-search.ng-hide-add { + display: none !important; +} + +/* Mark invalid Bootstrap */ +.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match { + border-color: #D44950; +} + +/* Handle up direction Bootstrap */ +.ui-select-container[theme="bootstrap"].direction-up .ui-select-dropdown { + box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25); +} + +.ui-select-bootstrap .ui-select-match-text { + width: 100%; + padding-right: 1em; +} +.ui-select-bootstrap .ui-select-match-text span { + display: inline-block; + width: 100%; + overflow: hidden; +} +.ui-select-bootstrap .ui-select-toggle > a.btn { + position: absolute; + height: 10px; + right: 10px; + margin-top: -2px; +} + +/* Spinner */ +.ui-select-refreshing.glyphicon { + position: absolute; + right: 0; + padding: 8px 27px; + } + +@-webkit-keyframes ui-select-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes ui-select-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +.ui-select-spin { + -webkit-animation: ui-select-spin 2s infinite linear; + animation: ui-select-spin 2s infinite linear; +} + +.ui-select-refreshing.ng-animate { + -webkit-animation: none 0s; +} diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.js new file mode 100644 index 0000000..5ac4e0b --- /dev/null +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.js @@ -0,0 +1,2427 @@ +/*! + * ui-select + * http://github.com/angular-ui/ui-select + * Version: 0.19.7 - 2017-04-15T14:28:36.649Z + * License: MIT + */ + + +(function () { +"use strict"; +var KEY = { + TAB: 9, + ENTER: 13, + ESC: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + SHIFT: 16, + CTRL: 17, + ALT: 18, + PAGE_UP: 33, + PAGE_DOWN: 34, + HOME: 36, + END: 35, + BACKSPACE: 8, + DELETE: 46, + COMMAND: 91, + + MAP: { 91 : "COMMAND", 8 : "BACKSPACE" , 9 : "TAB" , 13 : "ENTER" , 16 : "SHIFT" , 17 : "CTRL" , 18 : "ALT" , 19 : "PAUSEBREAK" , 20 : "CAPSLOCK" , 27 : "ESC" , 32 : "SPACE" , 33 : "PAGE_UP", 34 : "PAGE_DOWN" , 35 : "END" , 36 : "HOME" , 37 : "LEFT" , 38 : "UP" , 39 : "RIGHT" , 40 : "DOWN" , 43 : "+" , 44 : "PRINTSCREEN" , 45 : "INSERT" , 46 : "DELETE", 48 : "0" , 49 : "1" , 50 : "2" , 51 : "3" , 52 : "4" , 53 : "5" , 54 : "6" , 55 : "7" , 56 : "8" , 57 : "9" , 59 : ";", 61 : "=" , 65 : "A" , 66 : "B" , 67 : "C" , 68 : "D" , 69 : "E" , 70 : "F" , 71 : "G" , 72 : "H" , 73 : "I" , 74 : "J" , 75 : "K" , 76 : "L", 77 : "M" , 78 : "N" , 79 : "O" , 80 : "P" , 81 : "Q" , 82 : "R" , 83 : "S" , 84 : "T" , 85 : "U" , 86 : "V" , 87 : "W" , 88 : "X" , 89 : "Y" , 90 : "Z", 96 : "0" , 97 : "1" , 98 : "2" , 99 : "3" , 100 : "4" , 101 : "5" , 102 : "6" , 103 : "7" , 104 : "8" , 105 : "9", 106 : "*" , 107 : "+" , 109 : "-" , 110 : "." , 111 : "/", 112 : "F1" , 113 : "F2" , 114 : "F3" , 115 : "F4" , 116 : "F5" , 117 : "F6" , 118 : "F7" , 119 : "F8" , 120 : "F9" , 121 : "F10" , 122 : "F11" , 123 : "F12", 144 : "NUMLOCK" , 145 : "SCROLLLOCK" , 186 : ";" , 187 : "=" , 188 : "," , 189 : "-" , 190 : "." , 191 : "/" , 192 : "`" , 219 : "[" , 220 : "\\" , 221 : "]" , 222 : "'" + }, + + isControl: function (e) { + var k = e.which; + switch (k) { + case KEY.COMMAND: + case KEY.SHIFT: + case KEY.CTRL: + case KEY.ALT: + return true; + } + + if (e.metaKey || e.ctrlKey || e.altKey) return true; + + return false; + }, + isFunctionKey: function (k) { + k = k.which ? k.which : k; + return k >= 112 && k <= 123; + }, + isVerticalMovement: function (k){ + return ~[KEY.UP, KEY.DOWN].indexOf(k); + }, + isHorizontalMovement: function (k){ + return ~[KEY.LEFT,KEY.RIGHT,KEY.BACKSPACE,KEY.DELETE].indexOf(k); + }, + toSeparator: function (k) { + var sep = {ENTER:"\n",TAB:"\t",SPACE:" "}[k]; + if (sep) return sep; + // return undefined for special keys other than enter, tab or space. + // no way to use them to cut strings. + return KEY[k] ? undefined : k; + } + }; + +function isNil(value) { + return angular.isUndefined(value) || value === null; +} + +/** + * Add querySelectorAll() to jqLite. + * + * jqLite find() is limited to lookups by tag name. + * TODO This will change with future versions of AngularJS, to be removed when this happens + * + * See jqLite.find - why not use querySelectorAll? https://github.com/angular/angular.js/issues/3586 + * See feat(jqLite): use querySelectorAll instead of getElementsByTagName in jqLite.find https://github.com/angular/angular.js/pull/3598 + */ +if (angular.element.prototype.querySelectorAll === undefined) { + angular.element.prototype.querySelectorAll = function(selector) { + return angular.element(this[0].querySelectorAll(selector)); + }; +} + +/** + * Add closest() to jqLite. + */ +if (angular.element.prototype.closest === undefined) { + angular.element.prototype.closest = function( selector) { + var elem = this[0]; + var matchesSelector = elem.matches || elem.webkitMatchesSelector || elem.mozMatchesSelector || elem.msMatchesSelector; + + while (elem) { + if (matchesSelector.bind(elem)(selector)) { + return elem; + } else { + elem = elem.parentElement; + } + } + return false; + }; +} + +var latestId = 0; + +var uis = angular.module('ui.select', []) + +.constant('uiSelectConfig', { + theme: 'bootstrap', + searchEnabled: true, + sortable: false, + placeholder: '', // Empty by default, like HTML tag <select> + refreshDelay: 1000, // In milliseconds + closeOnSelect: true, + skipFocusser: false, + dropdownPosition: 'auto', + removeSelected: true, + resetSearchInput: true, + generateId: function() { + return latestId++; + }, + appendToBody: false, + spinnerEnabled: false, + spinnerClass: 'glyphicon glyphicon-refresh ui-select-spin', + backspaceReset: true +}) + +// See Rename minErr and make it accessible from outside https://github.com/angular/angular.js/issues/6913 +.service('uiSelectMinErr', function() { + var minErr = angular.$$minErr('ui.select'); + return function() { + var error = minErr.apply(this, arguments); + var message = error.message.replace(new RegExp('\nhttp://errors.angularjs.org/.*'), ''); + return new Error(message); + }; +}) + +// Recreates old behavior of ng-transclude. Used internally. +.directive('uisTranscludeAppend', function () { + return { + link: function (scope, element, attrs, ctrl, transclude) { + transclude(scope, function (clone) { + element.append(clone); + }); + } + }; +}) + +/** + * Highlights text that matches $select.search. + * + * Taken from AngularUI Bootstrap Typeahead + * See https://github.com/angular-ui/bootstrap/blob/0.10.0/src/typeahead/typeahead.js#L340 + */ +.filter('highlight', function() { + function escapeRegexp(queryToEscape) { + return ('' + queryToEscape).replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); + } + + return function(matchItem, query) { + return query && matchItem ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<span class="ui-select-highlight">$&</span>') : matchItem; + }; +}) + +/** + * A read-only equivalent of jQuery's offset function: http://api.jquery.com/offset/ + * + * Taken from AngularUI Bootstrap Position: + * See https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js#L70 + */ +.factory('uisOffset', + ['$document', '$window', + function ($document, $window) { + + return function(element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) + }; + }; +}]); + +/** + * Debounces functions + * + * Taken from UI Bootstrap $$debounce source code + * See https://github.com/angular-ui/bootstrap/blob/master/src/debounce/debounce.js + * + */ +uis.factory('$$uisDebounce', ['$timeout', function($timeout) { + return function(callback, debounceTime) { + var timeoutPromise; + + return function() { + var self = this; + var args = Array.prototype.slice.call(arguments); + if (timeoutPromise) { + $timeout.cancel(timeoutPromise); + } + + timeoutPromise = $timeout(function() { + callback.apply(self, args); + }, debounceTime); + }; + }; +}]); + +uis.directive('uiSelectChoices', + ['uiSelectConfig', 'uisRepeatParser', 'uiSelectMinErr', '$compile', '$window', + function(uiSelectConfig, RepeatParser, uiSelectMinErr, $compile, $window) { + + return { + restrict: 'EA', + require: '^uiSelect', + replace: true, + transclude: true, + templateUrl: function(tElement) { + // Needed so the uiSelect can detect the transcluded content + tElement.addClass('ui-select-choices'); + + // Gets theme attribute from parent (ui-select) + var theme = tElement.parent().attr('theme') || uiSelectConfig.theme; + return theme + '/choices.tpl.html'; + }, + + compile: function(tElement, tAttrs) { + + if (!tAttrs.repeat) throw uiSelectMinErr('repeat', "Expected 'repeat' expression."); + + // var repeat = RepeatParser.parse(attrs.repeat); + var groupByExp = tAttrs.groupBy; + var groupFilterExp = tAttrs.groupFilter; + + if (groupByExp) { + var groups = tElement.querySelectorAll('.ui-select-choices-group'); + if (groups.length !== 1) throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-group but got '{0}'.", groups.length); + groups.attr('ng-repeat', RepeatParser.getGroupNgRepeatExpression()); + } + + var parserResult = RepeatParser.parse(tAttrs.repeat); + + var choices = tElement.querySelectorAll('.ui-select-choices-row'); + if (choices.length !== 1) { + throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row but got '{0}'.", choices.length); + } + + choices.attr('ng-repeat', parserResult.repeatExpression(groupByExp)) + .attr('ng-if', '$select.open'); //Prevent unnecessary watches when dropdown is closed + + + var rowsInner = tElement.querySelectorAll('.ui-select-choices-row-inner'); + if (rowsInner.length !== 1) { + throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row-inner but got '{0}'.", rowsInner.length); + } + rowsInner.attr('uis-transclude-append', ''); //Adding uisTranscludeAppend directive to row element after choices element has ngRepeat + + // If IE8 then need to target rowsInner to apply the ng-click attr as choices will not capture the event. + var clickTarget = $window.document.addEventListener ? choices : rowsInner; + clickTarget.attr('ng-click', '$select.select(' + parserResult.itemName + ',$select.skipFocusser,$event)'); + + return function link(scope, element, attrs, $select) { + + + $select.parseRepeatAttr(attrs.repeat, groupByExp, groupFilterExp); //Result ready at $select.parserResult + $select.disableChoiceExpression = attrs.uiDisableChoice; + $select.onHighlightCallback = attrs.onHighlight; + $select.minimumInputLength = parseInt(attrs.minimumInputLength) || 0; + $select.dropdownPosition = attrs.position ? attrs.position.toLowerCase() : uiSelectConfig.dropdownPosition; + + scope.$watch('$select.search', function(newValue) { + if(newValue && !$select.open && $select.multiple) $select.activate(false, true); + $select.activeIndex = $select.tagging.isActivated ? -1 : 0; + if (!attrs.minimumInputLength || $select.search.length >= attrs.minimumInputLength) { + $select.refresh(attrs.refresh); + } else { + $select.items = []; + } + }); + + attrs.$observe('refreshDelay', function() { + // $eval() is needed otherwise we get a string instead of a number + var refreshDelay = scope.$eval(attrs.refreshDelay); + $select.refreshDelay = refreshDelay !== undefined ? refreshDelay : uiSelectConfig.refreshDelay; + }); + + scope.$watch('$select.open', function(open) { + if (open) { + tElement.attr('role', 'listbox'); + $select.refresh(attrs.refresh); + } else { + element.removeAttr('role'); + } + }); + }; + } + }; +}]); + +/** + * Contains ui-select "intelligence". + * + * The goal is to limit dependency on the DOM whenever possible and + * put as much logic in the controller (instead of the link functions) as possible so it can be easily tested. + */ +uis.controller('uiSelectCtrl', + ['$scope', '$element', '$timeout', '$filter', '$$uisDebounce', 'uisRepeatParser', 'uiSelectMinErr', 'uiSelectConfig', '$parse', '$injector', '$window', + function($scope, $element, $timeout, $filter, $$uisDebounce, RepeatParser, uiSelectMinErr, uiSelectConfig, $parse, $injector, $window) { + + var ctrl = this; + + var EMPTY_SEARCH = ''; + + ctrl.placeholder = uiSelectConfig.placeholder; + ctrl.searchEnabled = uiSelectConfig.searchEnabled; + ctrl.sortable = uiSelectConfig.sortable; + ctrl.refreshDelay = uiSelectConfig.refreshDelay; + ctrl.paste = uiSelectConfig.paste; + ctrl.resetSearchInput = uiSelectConfig.resetSearchInput; + ctrl.refreshing = false; + ctrl.spinnerEnabled = uiSelectConfig.spinnerEnabled; + ctrl.spinnerClass = uiSelectConfig.spinnerClass; + ctrl.removeSelected = uiSelectConfig.removeSelected; //If selected item(s) should be removed from dropdown list + ctrl.closeOnSelect = true; //Initialized inside uiSelect directive link function + ctrl.skipFocusser = false; //Set to true to avoid returning focus to ctrl when item is selected + ctrl.search = EMPTY_SEARCH; + + ctrl.activeIndex = 0; //Dropdown of choices + ctrl.items = []; //All available choices + + ctrl.open = false; + ctrl.focus = false; + ctrl.disabled = false; + ctrl.selected = undefined; + + ctrl.dropdownPosition = 'auto'; + + ctrl.focusser = undefined; //Reference to input element used to handle focus events + ctrl.multiple = undefined; // Initialized inside uiSelect directive link function + ctrl.disableChoiceExpression = undefined; // Initialized inside uiSelectChoices directive link function + ctrl.tagging = {isActivated: false, fct: undefined}; + ctrl.taggingTokens = {isActivated: false, tokens: undefined}; + ctrl.lockChoiceExpression = undefined; // Initialized inside uiSelectMatch directive link function + ctrl.clickTriggeredSelect = false; + ctrl.$filter = $filter; + ctrl.$element = $element; + + // Use $injector to check for $animate and store a reference to it + ctrl.$animate = (function () { + try { + return $injector.get('$animate'); + } catch (err) { + // $animate does not exist + return null; + } + })(); + + ctrl.searchInput = $element.querySelectorAll('input.ui-select-search'); + if (ctrl.searchInput.length !== 1) { + throw uiSelectMinErr('searchInput', "Expected 1 input.ui-select-search but got '{0}'.", ctrl.searchInput.length); + } + + ctrl.isEmpty = function() { + return isNil(ctrl.selected) || ctrl.selected === '' || (ctrl.multiple && ctrl.selected.length === 0); + }; + + function _findIndex(collection, predicate, thisArg){ + if (collection.findIndex){ + return collection.findIndex(predicate, thisArg); + } else { + var list = Object(collection); + var length = list.length >>> 0; + var value; + + for (var i = 0; i < length; i++) { + value = list[i]; + if (predicate.call(thisArg, value, i, list)) { + return i; + } + } + return -1; + } + } + + // Most of the time the user does not want to empty the search input when in typeahead mode + function _resetSearchInput() { + if (ctrl.resetSearchInput) { + ctrl.search = EMPTY_SEARCH; + //reset activeIndex + if (ctrl.selected && ctrl.items.length && !ctrl.multiple) { + ctrl.activeIndex = _findIndex(ctrl.items, function(item){ + return angular.equals(this, item); + }, ctrl.selected); + } + } + } + + function _groupsFilter(groups, groupNames) { + var i, j, result = []; + for(i = 0; i < groupNames.length ;i++){ + for(j = 0; j < groups.length ;j++){ + if(groups[j].name == [groupNames[i]]){ + result.push(groups[j]); + } + } + } + return result; + } + + // When the user clicks on ui-select, displays the dropdown list + ctrl.activate = function(initSearchValue, avoidReset) { + if (!ctrl.disabled && !ctrl.open) { + if(!avoidReset) _resetSearchInput(); + + $scope.$broadcast('uis:activate'); + ctrl.open = true; + ctrl.activeIndex = ctrl.activeIndex >= ctrl.items.length ? 0 : ctrl.activeIndex; + // ensure that the index is set to zero for tagging variants + // that where first option is auto-selected + if ( ctrl.activeIndex === -1 && ctrl.taggingLabel !== false ) { + ctrl.activeIndex = 0; + } + + var container = $element.querySelectorAll('.ui-select-choices-content'); + var searchInput = $element.querySelectorAll('.ui-select-search'); + if (ctrl.$animate && ctrl.$animate.on && ctrl.$animate.enabled(container[0])) { + var animateHandler = function(elem, phase) { + if (phase === 'start' && ctrl.items.length === 0) { + // Only focus input after the animation has finished + ctrl.$animate.off('removeClass', searchInput[0], animateHandler); + $timeout(function () { + ctrl.focusSearchInput(initSearchValue); + }); + } else if (phase === 'close') { + // Only focus input after the animation has finished + ctrl.$animate.off('enter', container[0], animateHandler); + $timeout(function () { + ctrl.focusSearchInput(initSearchValue); + }); + } + }; + + if (ctrl.items.length > 0) { + ctrl.$animate.on('enter', container[0], animateHandler); + } else { + ctrl.$animate.on('removeClass', searchInput[0], animateHandler); + } + } else { + $timeout(function () { + ctrl.focusSearchInput(initSearchValue); + if(!ctrl.tagging.isActivated && ctrl.items.length > 1) { + _ensureHighlightVisible(); + } + }); + } + } + else if (ctrl.open && !ctrl.searchEnabled) { + // Close the selection if we don't have search enabled, and we click on the select again + ctrl.close(); + } + }; + + ctrl.focusSearchInput = function (initSearchValue) { + ctrl.search = initSearchValue || ctrl.search; + ctrl.searchInput[0].focus(); + }; + + ctrl.findGroupByName = function(name) { + return ctrl.groups && ctrl.groups.filter(function(group) { + return group.name === name; + })[0]; + }; + + ctrl.parseRepeatAttr = function(repeatAttr, groupByExp, groupFilterExp) { + function updateGroups(items) { + var groupFn = $scope.$eval(groupByExp); + ctrl.groups = []; + angular.forEach(items, function(item) { + var groupName = angular.isFunction(groupFn) ? groupFn(item) : item[groupFn]; + var group = ctrl.findGroupByName(groupName); + if(group) { + group.items.push(item); + } + else { + ctrl.groups.push({name: groupName, items: [item]}); + } + }); + if(groupFilterExp){ + var groupFilterFn = $scope.$eval(groupFilterExp); + if( angular.isFunction(groupFilterFn)){ + ctrl.groups = groupFilterFn(ctrl.groups); + } else if(angular.isArray(groupFilterFn)){ + ctrl.groups = _groupsFilter(ctrl.groups, groupFilterFn); + } + } + ctrl.items = []; + ctrl.groups.forEach(function(group) { + ctrl.items = ctrl.items.concat(group.items); + }); + } + + function setPlainItems(items) { + ctrl.items = items || []; + } + + ctrl.setItemsFn = groupByExp ? updateGroups : setPlainItems; + + ctrl.parserResult = RepeatParser.parse(repeatAttr); + + ctrl.isGrouped = !!groupByExp; + ctrl.itemProperty = ctrl.parserResult.itemName; + + //If collection is an Object, convert it to Array + + var originalSource = ctrl.parserResult.source; + + //When an object is used as source, we better create an array and use it as 'source' + var createArrayFromObject = function(){ + var origSrc = originalSource($scope); + $scope.$uisSource = Object.keys(origSrc).map(function(v){ + var result = {}; + result[ctrl.parserResult.keyName] = v; + result.value = origSrc[v]; + return result; + }); + }; + + if (ctrl.parserResult.keyName){ // Check for (key,value) syntax + createArrayFromObject(); + ctrl.parserResult.source = $parse('$uisSource' + ctrl.parserResult.filters); + $scope.$watch(originalSource, function(newVal, oldVal){ + if (newVal !== oldVal) createArrayFromObject(); + }, true); + } + + ctrl.refreshItems = function (data){ + data = data || ctrl.parserResult.source($scope); + var selectedItems = ctrl.selected; + //TODO should implement for single mode removeSelected + if (ctrl.isEmpty() || (angular.isArray(selectedItems) && !selectedItems.length) || !ctrl.multiple || !ctrl.removeSelected) { + ctrl.setItemsFn(data); + }else{ + if ( data !== undefined && data !== null ) { + var filteredItems = data.filter(function(i) { + return angular.isArray(selectedItems) ? selectedItems.every(function(selectedItem) { + return !angular.equals(i, selectedItem); + }) : !angular.equals(i, selectedItems); + }); + ctrl.setItemsFn(filteredItems); + } + } + if (ctrl.dropdownPosition === 'auto' || ctrl.dropdownPosition === 'up'){ + $scope.calculateDropdownPos(); + } + $scope.$broadcast('uis:refresh'); + }; + + // See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L259 + $scope.$watchCollection(ctrl.parserResult.source, function(items) { + if (items === undefined || items === null) { + // If the user specifies undefined or null => reset the collection + // Special case: items can be undefined if the user did not initialized the collection on the scope + // i.e $scope.addresses = [] is missing + ctrl.items = []; + } else { + if (!angular.isArray(items)) { + throw uiSelectMinErr('items', "Expected an array but got '{0}'.", items); + } else { + //Remove already selected items (ex: while searching) + //TODO Should add a test + ctrl.refreshItems(items); + + //update the view value with fresh data from items, if there is a valid model value + if(angular.isDefined(ctrl.ngModel.$modelValue)) { + ctrl.ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters + } + } + } + }); + + }; + + var _refreshDelayPromise; + + /** + * Typeahead mode: lets the user refresh the collection using his own function. + * + * See Expose $select.search for external / remote filtering https://github.com/angular-ui/ui-select/pull/31 + */ + ctrl.refresh = function(refreshAttr) { + if (refreshAttr !== undefined) { + // Debounce + // See https://github.com/angular-ui/bootstrap/blob/0.10.0/src/typeahead/typeahead.js#L155 + // FYI AngularStrap typeahead does not have debouncing: https://github.com/mgcrea/angular-strap/blob/v2.0.0-rc.4/src/typeahead/typeahead.js#L177 + if (_refreshDelayPromise) { + $timeout.cancel(_refreshDelayPromise); + } + _refreshDelayPromise = $timeout(function() { + if ($scope.$select.search.length >= $scope.$select.minimumInputLength) { + var refreshPromise = $scope.$eval(refreshAttr); + if (refreshPromise && angular.isFunction(refreshPromise.then) && !ctrl.refreshing) { + ctrl.refreshing = true; + refreshPromise.finally(function() { + ctrl.refreshing = false; + }); + } + } + }, ctrl.refreshDelay); + } + }; + + ctrl.isActive = function(itemScope) { + if ( !ctrl.open ) { + return false; + } + var itemIndex = ctrl.items.indexOf(itemScope[ctrl.itemProperty]); + var isActive = itemIndex == ctrl.activeIndex; + + if ( !isActive || itemIndex < 0 ) { + return false; + } + + if (isActive && !angular.isUndefined(ctrl.onHighlightCallback)) { + itemScope.$eval(ctrl.onHighlightCallback); + } + + return isActive; + }; + + var _isItemSelected = function (item) { + return (ctrl.selected && angular.isArray(ctrl.selected) && + ctrl.selected.filter(function (selection) { return angular.equals(selection, item); }).length > 0); + }; + + var disabledItems = []; + + function _updateItemDisabled(item, isDisabled) { + var disabledItemIndex = disabledItems.indexOf(item); + if (isDisabled && disabledItemIndex === -1) { + disabledItems.push(item); + } + + if (!isDisabled && disabledItemIndex > -1) { + disabledItems.splice(disabledItemIndex, 1); + } + } + + function _isItemDisabled(item) { + return disabledItems.indexOf(item) > -1; + } + + ctrl.isDisabled = function(itemScope) { + + if (!ctrl.open) return; + + var item = itemScope[ctrl.itemProperty]; + var itemIndex = ctrl.items.indexOf(item); + var isDisabled = false; + + if (itemIndex >= 0 && (angular.isDefined(ctrl.disableChoiceExpression) || ctrl.multiple)) { + + if (item.isTag) return false; + + if (ctrl.multiple) { + isDisabled = _isItemSelected(item); + } + + if (!isDisabled && angular.isDefined(ctrl.disableChoiceExpression)) { + isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)); + } + + _updateItemDisabled(item, isDisabled); + } + + return isDisabled; + }; + + + // When the user selects an item with ENTER or clicks the dropdown + ctrl.select = function(item, skipFocusser, $event) { + if (isNil(item) || !_isItemDisabled(item)) { + + if ( ! ctrl.items && ! ctrl.search && ! ctrl.tagging.isActivated) return; + + if (!item || !_isItemDisabled(item)) { + // if click is made on existing item, prevent from tagging, ctrl.search does not matter + ctrl.clickTriggeredSelect = false; + if($event && ($event.type === 'click' || $event.type === 'touchend') && item) + ctrl.clickTriggeredSelect = true; + + if(ctrl.tagging.isActivated && ctrl.clickTriggeredSelect === false) { + // if taggingLabel is disabled and item is undefined we pull from ctrl.search + if ( ctrl.taggingLabel === false ) { + if ( ctrl.activeIndex < 0 ) { + if (item === undefined) { + item = ctrl.tagging.fct !== undefined ? ctrl.tagging.fct(ctrl.search) : ctrl.search; + } + if (!item || angular.equals( ctrl.items[0], item ) ) { + return; + } + } else { + // keyboard nav happened first, user selected from dropdown + item = ctrl.items[ctrl.activeIndex]; + } + } else { + // tagging always operates at index zero, taggingLabel === false pushes + // the ctrl.search value without having it injected + if ( ctrl.activeIndex === 0 ) { + // ctrl.tagging pushes items to ctrl.items, so we only have empty val + // for `item` if it is a detected duplicate + if ( item === undefined ) return; + + // create new item on the fly if we don't already have one; + // use tagging function if we have one + if ( ctrl.tagging.fct !== undefined && typeof item === 'string' ) { + item = ctrl.tagging.fct(item); + if (!item) return; + // if item type is 'string', apply the tagging label + } else if ( typeof item === 'string' ) { + // trim the trailing space + item = item.replace(ctrl.taggingLabel,'').trim(); + } + } + } + // search ctrl.selected for dupes potentially caused by tagging and return early if found + if (_isItemSelected(item)) { + ctrl.close(skipFocusser); + return; + } + } + _resetSearchInput(); + $scope.$broadcast('uis:select', item); + + if (ctrl.closeOnSelect) { + ctrl.close(skipFocusser); + } + } + } + }; + + // Closes the dropdown + ctrl.close = function(skipFocusser) { + if (!ctrl.open) return; + if (ctrl.ngModel && ctrl.ngModel.$setTouched) ctrl.ngModel.$setTouched(); + ctrl.open = false; + _resetSearchInput(); + $scope.$broadcast('uis:close', skipFocusser); + + }; + + ctrl.setFocus = function(){ + if (!ctrl.focus) ctrl.focusInput[0].focus(); + }; + + ctrl.clear = function($event) { + ctrl.select(null); + $event.stopPropagation(); + $timeout(function() { + ctrl.focusser[0].focus(); + }, 0, false); + }; + + // Toggle dropdown + ctrl.toggle = function(e) { + if (ctrl.open) { + ctrl.close(); + e.preventDefault(); + e.stopPropagation(); + } else { + ctrl.activate(); + } + }; + + // Set default function for locked choices - avoids unnecessary + // logic if functionality is not being used + ctrl.isLocked = function () { + return false; + }; + + $scope.$watch(function () { + return angular.isDefined(ctrl.lockChoiceExpression) && ctrl.lockChoiceExpression !== ""; + }, _initaliseLockedChoices); + + function _initaliseLockedChoices(doInitalise) { + if(!doInitalise) return; + + var lockedItems = []; + + function _updateItemLocked(item, isLocked) { + var lockedItemIndex = lockedItems.indexOf(item); + if (isLocked && lockedItemIndex === -1) { + lockedItems.push(item); + } + + if (!isLocked && lockedItemIndex > -1) { + lockedItems.splice(lockedItemIndex, 1); + } + } + + function _isItemlocked(item) { + return lockedItems.indexOf(item) > -1; + } + + ctrl.isLocked = function (itemScope, itemIndex) { + var isLocked = false, + item = ctrl.selected[itemIndex]; + + if(item) { + if (itemScope) { + isLocked = !!(itemScope.$eval(ctrl.lockChoiceExpression)); + _updateItemLocked(item, isLocked); + } else { + isLocked = _isItemlocked(item); + } + } + + return isLocked; + }; + } + + + var sizeWatch = null; + var updaterScheduled = false; + ctrl.sizeSearchInput = function() { + + var input = ctrl.searchInput[0], + container = ctrl.$element[0], + calculateContainerWidth = function() { + // Return the container width only if the search input is visible + return container.clientWidth * !!input.offsetParent; + }, + updateIfVisible = function(containerWidth) { + if (containerWidth === 0) { + return false; + } + var inputWidth = containerWidth - input.offsetLeft; + if (inputWidth < 50) inputWidth = containerWidth; + ctrl.searchInput.css('width', inputWidth+'px'); + return true; + }; + + ctrl.searchInput.css('width', '10px'); + $timeout(function() { //Give tags time to render correctly + if (sizeWatch === null && !updateIfVisible(calculateContainerWidth())) { + sizeWatch = $scope.$watch(function() { + if (!updaterScheduled) { + updaterScheduled = true; + $scope.$$postDigest(function() { + updaterScheduled = false; + if (updateIfVisible(calculateContainerWidth())) { + sizeWatch(); + sizeWatch = null; + } + }); + } + }, angular.noop); + } + }); + }; + + function _handleDropDownSelection(key) { + var processed = true; + switch (key) { + case KEY.DOWN: + if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode + else if (ctrl.activeIndex < ctrl.items.length - 1) { + var idx = ++ctrl.activeIndex; + while(_isItemDisabled(ctrl.items[idx]) && idx < ctrl.items.length) { + ctrl.activeIndex = ++idx; + } + } + break; + case KEY.UP: + var minActiveIndex = (ctrl.search.length === 0 && ctrl.tagging.isActivated) ? -1 : 0; + if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode + else if (ctrl.activeIndex > minActiveIndex) { + var idxmin = --ctrl.activeIndex; + while(_isItemDisabled(ctrl.items[idxmin]) && idxmin > minActiveIndex) { + ctrl.activeIndex = --idxmin; + } + } + break; + case KEY.TAB: + if (!ctrl.multiple || ctrl.open) ctrl.select(ctrl.items[ctrl.activeIndex], true); + break; + case KEY.ENTER: + if(ctrl.open && (ctrl.tagging.isActivated || ctrl.activeIndex >= 0)){ + ctrl.select(ctrl.items[ctrl.activeIndex], ctrl.skipFocusser); // Make sure at least one dropdown item is highlighted before adding if not in tagging mode + } else { + ctrl.activate(false, true); //In case its the search input in 'multiple' mode + } + break; + case KEY.ESC: + ctrl.close(); + break; + default: + processed = false; + } + return processed; + } + + // Bind to keyboard shortcuts + ctrl.searchInput.on('keydown', function(e) { + + var key = e.which; + + if (~[KEY.ENTER,KEY.ESC].indexOf(key)){ + e.preventDefault(); + e.stopPropagation(); + } + + $scope.$apply(function() { + + var tagged = false; + + if (ctrl.items.length > 0 || ctrl.tagging.isActivated) { + if(!_handleDropDownSelection(key) && !ctrl.searchEnabled) { + e.preventDefault(); + e.stopPropagation(); + } + if ( ctrl.taggingTokens.isActivated ) { + for (var i = 0; i < ctrl.taggingTokens.tokens.length; i++) { + if ( ctrl.taggingTokens.tokens[i] === KEY.MAP[e.keyCode] ) { + // make sure there is a new value to push via tagging + if ( ctrl.search.length > 0 ) { + tagged = true; + } + } + } + if ( tagged ) { + $timeout(function() { + ctrl.searchInput.triggerHandler('tagged'); + var newItem = ctrl.search.replace(KEY.MAP[e.keyCode],'').trim(); + if ( ctrl.tagging.fct ) { + newItem = ctrl.tagging.fct( newItem ); + } + if (newItem) ctrl.select(newItem, true); + }); + } + } + } + + }); + + if(KEY.isVerticalMovement(key) && ctrl.items.length > 0){ + _ensureHighlightVisible(); + } + + if (key === KEY.ENTER || key === KEY.ESC) { + e.preventDefault(); + e.stopPropagation(); + } + + }); + + ctrl.searchInput.on('paste', function (e) { + var data; + + if (window.clipboardData && window.clipboardData.getData) { // IE + data = window.clipboardData.getData('Text'); + } else { + data = (e.originalEvent || e).clipboardData.getData('text/plain'); + } + + // Prepend the current input field text to the paste buffer. + data = ctrl.search + data; + + if (data && data.length > 0) { + // If tagging try to split by tokens and add items + if (ctrl.taggingTokens.isActivated) { + var items = []; + for (var i = 0; i < ctrl.taggingTokens.tokens.length; i++) { // split by first token that is contained in data + var separator = KEY.toSeparator(ctrl.taggingTokens.tokens[i]) || ctrl.taggingTokens.tokens[i]; + if (data.indexOf(separator) > -1) { + items = data.split(separator); + break; // only split by one token + } + } + if (items.length === 0) { + items = [data]; + } + var oldsearch = ctrl.search; + angular.forEach(items, function (item) { + var newItem = ctrl.tagging.fct ? ctrl.tagging.fct(item) : item; + if (newItem) { + ctrl.select(newItem, true); + } + }); + ctrl.search = oldsearch || EMPTY_SEARCH; + e.preventDefault(); + e.stopPropagation(); + } else if (ctrl.paste) { + ctrl.paste(data); + ctrl.search = EMPTY_SEARCH; + e.preventDefault(); + e.stopPropagation(); + } + } + }); + + ctrl.searchInput.on('tagged', function() { + $timeout(function() { + _resetSearchInput(); + }); + }); + + // See https://github.com/ivaynberg/select2/blob/3.4.6/select2.js#L1431 + function _ensureHighlightVisible() { + var container = $element.querySelectorAll('.ui-select-choices-content'); + var choices = container.querySelectorAll('.ui-select-choices-row'); + if (choices.length < 1) { + throw uiSelectMinErr('choices', "Expected multiple .ui-select-choices-row but got '{0}'.", choices.length); + } + + if (ctrl.activeIndex < 0) { + return; + } + + var highlighted = choices[ctrl.activeIndex]; + var posY = highlighted.offsetTop + highlighted.clientHeight - container[0].scrollTop; + var height = container[0].offsetHeight; + + if (posY > height) { + container[0].scrollTop += posY - height; + } else if (posY < highlighted.clientHeight) { + if (ctrl.isGrouped && ctrl.activeIndex === 0) + container[0].scrollTop = 0; //To make group header visible when going all the way up + else + container[0].scrollTop -= highlighted.clientHeight - posY; + } + } + + var onResize = $$uisDebounce(function() { + ctrl.sizeSearchInput(); + }, 50); + + angular.element($window).bind('resize', onResize); + + $scope.$on('$destroy', function() { + ctrl.searchInput.off('keyup keydown tagged blur paste'); + angular.element($window).off('resize', onResize); + }); + + $scope.$watch('$select.activeIndex', function(activeIndex) { + if (activeIndex) + $element.find('input').attr( + 'aria-activedescendant', + 'ui-select-choices-row-' + ctrl.generatedId + '-' + activeIndex); + }); + + $scope.$watch('$select.open', function(open) { + if (!open) + $element.find('input').removeAttr('aria-activedescendant'); + }); +}]); + +uis.directive('uiSelect', + ['$document', 'uiSelectConfig', 'uiSelectMinErr', 'uisOffset', '$compile', '$parse', '$timeout', + function($document, uiSelectConfig, uiSelectMinErr, uisOffset, $compile, $parse, $timeout) { + + return { + restrict: 'EA', + templateUrl: function(tElement, tAttrs) { + var theme = tAttrs.theme || uiSelectConfig.theme; + return theme + (angular.isDefined(tAttrs.multiple) ? '/select-multiple.tpl.html' : '/select.tpl.html'); + }, + replace: true, + transclude: true, + require: ['uiSelect', '^ngModel'], + scope: true, + + controller: 'uiSelectCtrl', + controllerAs: '$select', + compile: function(tElement, tAttrs) { + + // Allow setting ngClass on uiSelect + var match = /{(.*)}\s*{(.*)}/.exec(tAttrs.ngClass); + if(match) { + var combined = '{'+ match[1] +', '+ match[2] +'}'; + tAttrs.ngClass = combined; + tElement.attr('ng-class', combined); + } + + //Multiple or Single depending if multiple attribute presence + if (angular.isDefined(tAttrs.multiple)) + tElement.append('<ui-select-multiple/>').removeAttr('multiple'); + else + tElement.append('<ui-select-single/>'); + + if (tAttrs.inputId) + tElement.querySelectorAll('input.ui-select-search')[0].id = tAttrs.inputId; + + return function(scope, element, attrs, ctrls, transcludeFn) { + + var $select = ctrls[0]; + var ngModel = ctrls[1]; + + $select.generatedId = uiSelectConfig.generateId(); + $select.baseTitle = attrs.title || 'Select box'; + $select.focusserTitle = $select.baseTitle + ' focus'; + $select.focusserId = 'focusser-' + $select.generatedId; + + $select.closeOnSelect = function() { + if (angular.isDefined(attrs.closeOnSelect)) { + return $parse(attrs.closeOnSelect)(); + } else { + return uiSelectConfig.closeOnSelect; + } + }(); + + scope.$watch('skipFocusser', function() { + var skipFocusser = scope.$eval(attrs.skipFocusser); + $select.skipFocusser = skipFocusser !== undefined ? skipFocusser : uiSelectConfig.skipFocusser; + }); + + $select.onSelectCallback = $parse(attrs.onSelect); + $select.onRemoveCallback = $parse(attrs.onRemove); + + //Set reference to ngModel from uiSelectCtrl + $select.ngModel = ngModel; + + $select.choiceGrouped = function(group){ + return $select.isGrouped && group && group.name; + }; + + if(attrs.tabindex){ + attrs.$observe('tabindex', function(value) { + $select.focusInput.attr('tabindex', value); + element.removeAttr('tabindex'); + }); + } + + scope.$watch(function () { return scope.$eval(attrs.searchEnabled); }, function(newVal) { + $select.searchEnabled = newVal !== undefined ? newVal : uiSelectConfig.searchEnabled; + }); + + scope.$watch('sortable', function() { + var sortable = scope.$eval(attrs.sortable); + $select.sortable = sortable !== undefined ? sortable : uiSelectConfig.sortable; + }); + + attrs.$observe('backspaceReset', function() { + // $eval() is needed otherwise we get a string instead of a boolean + var backspaceReset = scope.$eval(attrs.backspaceReset); + $select.backspaceReset = backspaceReset !== undefined ? backspaceReset : true; + }); + + attrs.$observe('limit', function() { + //Limit the number of selections allowed + $select.limit = (angular.isDefined(attrs.limit)) ? parseInt(attrs.limit, 10) : undefined; + }); + + scope.$watch('removeSelected', function() { + var removeSelected = scope.$eval(attrs.removeSelected); + $select.removeSelected = removeSelected !== undefined ? removeSelected : uiSelectConfig.removeSelected; + }); + + attrs.$observe('disabled', function() { + // No need to use $eval() (thanks to ng-disabled) since we already get a boolean instead of a string + $select.disabled = attrs.disabled !== undefined ? attrs.disabled : false; + }); + + attrs.$observe('resetSearchInput', function() { + // $eval() is needed otherwise we get a string instead of a boolean + var resetSearchInput = scope.$eval(attrs.resetSearchInput); + $select.resetSearchInput = resetSearchInput !== undefined ? resetSearchInput : true; + }); + + attrs.$observe('paste', function() { + $select.paste = scope.$eval(attrs.paste); + }); + + attrs.$observe('tagging', function() { + if(attrs.tagging !== undefined) + { + // $eval() is needed otherwise we get a string instead of a boolean + var taggingEval = scope.$eval(attrs.tagging); + $select.tagging = {isActivated: true, fct: taggingEval !== true ? taggingEval : undefined}; + } + else + { + $select.tagging = {isActivated: false, fct: undefined}; + } + }); + + attrs.$observe('taggingLabel', function() { + if(attrs.tagging !== undefined ) + { + // check eval for FALSE, in this case, we disable the labels + // associated with tagging + if ( attrs.taggingLabel === 'false' ) { + $select.taggingLabel = false; + } + else + { + $select.taggingLabel = attrs.taggingLabel !== undefined ? attrs.taggingLabel : '(new)'; + } + } + }); + + attrs.$observe('taggingTokens', function() { + if (attrs.tagging !== undefined) { + var tokens = attrs.taggingTokens !== undefined ? attrs.taggingTokens.split('|') : [',','ENTER']; + $select.taggingTokens = {isActivated: true, tokens: tokens }; + } + }); + + attrs.$observe('spinnerEnabled', function() { + // $eval() is needed otherwise we get a string instead of a boolean + var spinnerEnabled = scope.$eval(attrs.spinnerEnabled); + $select.spinnerEnabled = spinnerEnabled !== undefined ? spinnerEnabled : uiSelectConfig.spinnerEnabled; + }); + + attrs.$observe('spinnerClass', function() { + var spinnerClass = attrs.spinnerClass; + $select.spinnerClass = spinnerClass !== undefined ? attrs.spinnerClass : uiSelectConfig.spinnerClass; + }); + + //Automatically gets focus when loaded + if (angular.isDefined(attrs.autofocus)){ + $timeout(function(){ + $select.setFocus(); + }); + } + + //Gets focus based on scope event name (e.g. focus-on='SomeEventName') + if (angular.isDefined(attrs.focusOn)){ + scope.$on(attrs.focusOn, function() { + $timeout(function(){ + $select.setFocus(); + }); + }); + } + + function onDocumentClick(e) { + if (!$select.open) return; //Skip it if dropdown is close + + var contains = false; + + if (window.jQuery) { + // Firefox 3.6 does not support element.contains() + // See Node.contains https://developer.mozilla.org/en-US/docs/Web/API/Node.contains + contains = window.jQuery.contains(element[0], e.target); + } else { + contains = element[0].contains(e.target); + } + + if (!contains && !$select.clickTriggeredSelect) { + var skipFocusser; + if (!$select.skipFocusser) { + //Will lose focus only with certain targets + var focusableControls = ['input','button','textarea','select']; + var targetController = angular.element(e.target).controller('uiSelect'); //To check if target is other ui-select + skipFocusser = targetController && targetController !== $select; //To check if target is other ui-select + if (!skipFocusser) skipFocusser = ~focusableControls.indexOf(e.target.tagName.toLowerCase()); //Check if target is input, button or textarea + } else { + skipFocusser = true; + } + $select.close(skipFocusser); + scope.$digest(); + } + $select.clickTriggeredSelect = false; + } + + // See Click everywhere but here event http://stackoverflow.com/questions/12931369 + $document.on('click', onDocumentClick); + + scope.$on('$destroy', function() { + $document.off('click', onDocumentClick); + }); + + // Move transcluded elements to their correct position in main template + transcludeFn(scope, function(clone) { + // See Transclude in AngularJS http://blog.omkarpatil.com/2012/11/transclude-in-angularjs.html + + // One day jqLite will be replaced by jQuery and we will be able to write: + // var transcludedElement = clone.filter('.my-class') + // instead of creating a hackish DOM element: + var transcluded = angular.element('<div>').append(clone); + + var transcludedMatch = transcluded.querySelectorAll('.ui-select-match'); + transcludedMatch.removeAttr('ui-select-match'); //To avoid loop in case directive as attr + transcludedMatch.removeAttr('data-ui-select-match'); // Properly handle HTML5 data-attributes + if (transcludedMatch.length !== 1) { + throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-match but got '{0}'.", transcludedMatch.length); + } + element.querySelectorAll('.ui-select-match').replaceWith(transcludedMatch); + + var transcludedChoices = transcluded.querySelectorAll('.ui-select-choices'); + transcludedChoices.removeAttr('ui-select-choices'); //To avoid loop in case directive as attr + transcludedChoices.removeAttr('data-ui-select-choices'); // Properly handle HTML5 data-attributes + if (transcludedChoices.length !== 1) { + throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-choices but got '{0}'.", transcludedChoices.length); + } + element.querySelectorAll('.ui-select-choices').replaceWith(transcludedChoices); + + var transcludedNoChoice = transcluded.querySelectorAll('.ui-select-no-choice'); + transcludedNoChoice.removeAttr('ui-select-no-choice'); //To avoid loop in case directive as attr + transcludedNoChoice.removeAttr('data-ui-select-no-choice'); // Properly handle HTML5 data-attributes + if (transcludedNoChoice.length == 1) { + element.querySelectorAll('.ui-select-no-choice').replaceWith(transcludedNoChoice); + } + }); + + // Support for appending the select field to the body when its open + var appendToBody = scope.$eval(attrs.appendToBody); + if (appendToBody !== undefined ? appendToBody : uiSelectConfig.appendToBody) { + scope.$watch('$select.open', function(isOpen) { + if (isOpen) { + positionDropdown(); + } else { + resetDropdown(); + } + }); + + // Move the dropdown back to its original location when the scope is destroyed. Otherwise + // it might stick around when the user routes away or the select field is otherwise removed + scope.$on('$destroy', function() { + resetDropdown(); + }); + } + + // Hold on to a reference to the .ui-select-container element for appendToBody support + var placeholder = null, + originalWidth = ''; + + function positionDropdown() { + // Remember the absolute position of the element + var offset = uisOffset(element); + + // Clone the element into a placeholder element to take its original place in the DOM + placeholder = angular.element('<div class="ui-select-placeholder"></div>'); + placeholder[0].style.width = offset.width + 'px'; + placeholder[0].style.height = offset.height + 'px'; + element.after(placeholder); + + // Remember the original value of the element width inline style, so it can be restored + // when the dropdown is closed + originalWidth = element[0].style.width; + + // Now move the actual dropdown element to the end of the body + $document.find('body').append(element); + + element[0].style.position = 'absolute'; + element[0].style.left = offset.left + 'px'; + element[0].style.top = offset.top + 'px'; + element[0].style.width = offset.width + 'px'; + } + + function resetDropdown() { + if (placeholder === null) { + // The dropdown has not actually been display yet, so there's nothing to reset + return; + } + + // Move the dropdown element back to its original location in the DOM + placeholder.replaceWith(element); + placeholder = null; + + element[0].style.position = ''; + element[0].style.left = ''; + element[0].style.top = ''; + element[0].style.width = originalWidth; + + // Set focus back on to the moved element + $select.setFocus(); + } + + // Hold on to a reference to the .ui-select-dropdown element for direction support. + var dropdown = null, + directionUpClassName = 'direction-up'; + + // Support changing the direction of the dropdown if there isn't enough space to render it. + scope.$watch('$select.open', function() { + + if ($select.dropdownPosition === 'auto' || $select.dropdownPosition === 'up'){ + scope.calculateDropdownPos(); + } + + }); + + var setDropdownPosUp = function(offset, offsetDropdown){ + + offset = offset || uisOffset(element); + offsetDropdown = offsetDropdown || uisOffset(dropdown); + + dropdown[0].style.position = 'absolute'; + dropdown[0].style.top = (offsetDropdown.height * -1) + 'px'; + element.addClass(directionUpClassName); + + }; + + var setDropdownPosDown = function(offset, offsetDropdown){ + + element.removeClass(directionUpClassName); + + offset = offset || uisOffset(element); + offsetDropdown = offsetDropdown || uisOffset(dropdown); + + dropdown[0].style.position = ''; + dropdown[0].style.top = ''; + + }; + + var calculateDropdownPosAfterAnimation = function() { + // Delay positioning the dropdown until all choices have been added so its height is correct. + $timeout(function() { + if ($select.dropdownPosition === 'up') { + //Go UP + setDropdownPosUp(); + } else { + //AUTO + element.removeClass(directionUpClassName); + + var offset = uisOffset(element); + var offsetDropdown = uisOffset(dropdown); + + //https://code.google.com/p/chromium/issues/detail?id=342307#c4 + var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox). + + // Determine if the direction of the dropdown needs to be changed. + if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) { + //Go UP + setDropdownPosUp(offset, offsetDropdown); + }else{ + //Go DOWN + setDropdownPosDown(offset, offsetDropdown); + } + } + + // Display the dropdown once it has been positioned. + dropdown[0].style.opacity = 1; + }); + }; + + var opened = false; + + scope.calculateDropdownPos = function() { + if ($select.open) { + dropdown = angular.element(element).querySelectorAll('.ui-select-dropdown'); + + if (dropdown.length === 0) { + return; + } + + // Hide the dropdown so there is no flicker until $timeout is done executing. + if ($select.search === '' && !opened) { + dropdown[0].style.opacity = 0; + opened = true; + } + + if (!uisOffset(dropdown).height && $select.$animate && $select.$animate.on && $select.$animate.enabled(dropdown)) { + var needsCalculated = true; + + $select.$animate.on('enter', dropdown, function (elem, phase) { + if (phase === 'close' && needsCalculated) { + calculateDropdownPosAfterAnimation(); + needsCalculated = false; + } + }); + } else { + calculateDropdownPosAfterAnimation(); + } + } else { + if (dropdown === null || dropdown.length === 0) { + return; + } + + // Reset the position of the dropdown. + dropdown[0].style.opacity = 0; + dropdown[0].style.position = ''; + dropdown[0].style.top = ''; + element.removeClass(directionUpClassName); + } + }; + }; + } + }; +}]); + +uis.directive('uiSelectMatch', ['uiSelectConfig', function(uiSelectConfig) { + return { + restrict: 'EA', + require: '^uiSelect', + replace: true, + transclude: true, + templateUrl: function(tElement) { + // Needed so the uiSelect can detect the transcluded content + tElement.addClass('ui-select-match'); + + var parent = tElement.parent(); + // Gets theme attribute from parent (ui-select) + var theme = getAttribute(parent, 'theme') || uiSelectConfig.theme; + var multi = angular.isDefined(getAttribute(parent, 'multiple')); + + return theme + (multi ? '/match-multiple.tpl.html' : '/match.tpl.html'); + }, + link: function(scope, element, attrs, $select) { + $select.lockChoiceExpression = attrs.uiLockChoice; + attrs.$observe('placeholder', function(placeholder) { + $select.placeholder = placeholder !== undefined ? placeholder : uiSelectConfig.placeholder; + }); + + function setAllowClear(allow) { + $select.allowClear = (angular.isDefined(allow)) ? (allow === '') ? true : (allow.toLowerCase() === 'true') : false; + } + + attrs.$observe('allowClear', setAllowClear); + setAllowClear(attrs.allowClear); + + if($select.multiple){ + $select.sizeSearchInput(); + } + + } + }; + + function getAttribute(elem, attribute) { + if (elem[0].hasAttribute(attribute)) + return elem.attr(attribute); + + if (elem[0].hasAttribute('data-' + attribute)) + return elem.attr('data-' + attribute); + + if (elem[0].hasAttribute('x-' + attribute)) + return elem.attr('x-' + attribute); + } +}]); + +uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelectMinErr, $timeout) { + return { + restrict: 'EA', + require: ['^uiSelect', '^ngModel'], + + controller: ['$scope','$timeout', function($scope, $timeout){ + + var ctrl = this, + $select = $scope.$select, + ngModel; + + if (angular.isUndefined($select.selected)) + $select.selected = []; + + //Wait for link fn to inject it + $scope.$evalAsync(function(){ ngModel = $scope.ngModel; }); + + ctrl.activeMatchIndex = -1; + + ctrl.updateModel = function(){ + ngModel.$setViewValue(Date.now()); //Set timestamp as a unique string to force changes + ctrl.refreshComponent(); + }; + + ctrl.refreshComponent = function(){ + //Remove already selected items + //e.g. When user clicks on a selection, the selected array changes and + //the dropdown should remove that item + if($select.refreshItems){ + $select.refreshItems(); + } + if($select.sizeSearchInput){ + $select.sizeSearchInput(); + } + }; + + // Remove item from multiple select + ctrl.removeChoice = function(index){ + + // if the choice is locked, don't remove it + if($select.isLocked(null, index)) return false; + + var removedChoice = $select.selected[index]; + + var locals = {}; + locals[$select.parserResult.itemName] = removedChoice; + + $select.selected.splice(index, 1); + ctrl.activeMatchIndex = -1; + $select.sizeSearchInput(); + + // Give some time for scope propagation. + $timeout(function(){ + $select.onRemoveCallback($scope, { + $item: removedChoice, + $model: $select.parserResult.modelMapper($scope, locals) + }); + }); + + ctrl.updateModel(); + + return true; + }; + + ctrl.getPlaceholder = function(){ + //Refactor single? + if($select.selected && $select.selected.length) return; + return $select.placeholder; + }; + + + }], + controllerAs: '$selectMultiple', + + link: function(scope, element, attrs, ctrls) { + + var $select = ctrls[0]; + var ngModel = scope.ngModel = ctrls[1]; + var $selectMultiple = scope.$selectMultiple; + + //$select.selected = raw selected objects (ignoring any property binding) + + $select.multiple = true; + + //Input that will handle focus + $select.focusInput = $select.searchInput; + + //Properly check for empty if set to multiple + ngModel.$isEmpty = function(value) { + return !value || value.length === 0; + }; + + //From view --> model + ngModel.$parsers.unshift(function () { + var locals = {}, + result, + resultMultiple = []; + for (var j = $select.selected.length - 1; j >= 0; j--) { + locals = {}; + locals[$select.parserResult.itemName] = $select.selected[j]; + result = $select.parserResult.modelMapper(scope, locals); + resultMultiple.unshift(result); + } + return resultMultiple; + }); + + // From model --> view + ngModel.$formatters.unshift(function (inputValue) { + var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search + locals = {}, + result; + if (!data) return inputValue; + var resultMultiple = []; + var checkFnMultiple = function(list, value){ + if (!list || !list.length) return; + for (var p = list.length - 1; p >= 0; p--) { + locals[$select.parserResult.itemName] = list[p]; + result = $select.parserResult.modelMapper(scope, locals); + if($select.parserResult.trackByExp){ + var propsItemNameMatches = /(\w*)\./.exec($select.parserResult.trackByExp); + var matches = /\.([^\s]+)/.exec($select.parserResult.trackByExp); + if(propsItemNameMatches && propsItemNameMatches.length > 0 && propsItemNameMatches[1] == $select.parserResult.itemName){ + if(matches && matches.length>0 && result[matches[1]] == value[matches[1]]){ + resultMultiple.unshift(list[p]); + return true; + } + } + } + if (angular.equals(result,value)){ + resultMultiple.unshift(list[p]); + return true; + } + } + return false; + }; + if (!inputValue) return resultMultiple; //If ngModel was undefined + for (var k = inputValue.length - 1; k >= 0; k--) { + //Check model array of currently selected items + if (!checkFnMultiple($select.selected, inputValue[k])){ + //Check model array of all items available + if (!checkFnMultiple(data, inputValue[k])){ + //If not found on previous lists, just add it directly to resultMultiple + resultMultiple.unshift(inputValue[k]); + } + } + } + return resultMultiple; + }); + + //Watch for external model changes + scope.$watchCollection(function(){ return ngModel.$modelValue; }, function(newValue, oldValue) { + if (oldValue != newValue){ + //update the view value with fresh data from items, if there is a valid model value + if(angular.isDefined(ngModel.$modelValue)) { + ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters + } + $selectMultiple.refreshComponent(); + } + }); + + ngModel.$render = function() { + // Make sure that model value is array + if(!angular.isArray(ngModel.$viewValue)){ + // Have tolerance for null or undefined values + if (isNil(ngModel.$viewValue)){ + ngModel.$viewValue = []; + } else { + throw uiSelectMinErr('multiarr', "Expected model value to be array but got '{0}'", ngModel.$viewValue); + } + } + $select.selected = ngModel.$viewValue; + $selectMultiple.refreshComponent(); + scope.$evalAsync(); //To force $digest + }; + + scope.$on('uis:select', function (event, item) { + if($select.selected.length >= $select.limit) { + return; + } + $select.selected.push(item); + var locals = {}; + locals[$select.parserResult.itemName] = item; + + $timeout(function(){ + $select.onSelectCallback(scope, { + $item: item, + $model: $select.parserResult.modelMapper(scope, locals) + }); + }); + $selectMultiple.updateModel(); + }); + + scope.$on('uis:activate', function () { + $selectMultiple.activeMatchIndex = -1; + }); + + scope.$watch('$select.disabled', function(newValue, oldValue) { + // As the search input field may now become visible, it may be necessary to recompute its size + if (oldValue && !newValue) $select.sizeSearchInput(); + }); + + $select.searchInput.on('keydown', function(e) { + var key = e.which; + scope.$apply(function() { + var processed = false; + // var tagged = false; //Checkme + if(KEY.isHorizontalMovement(key)){ + processed = _handleMatchSelection(key); + } + if (processed && key != KEY.TAB) { + //TODO Check si el tab selecciona aun correctamente + //Crear test + e.preventDefault(); + e.stopPropagation(); + } + }); + }); + function _getCaretPosition(el) { + if(angular.isNumber(el.selectionStart)) return el.selectionStart; + // selectionStart is not supported in IE8 and we don't want hacky workarounds so we compromise + else return el.value.length; + } + // Handles selected options in "multiple" mode + function _handleMatchSelection(key){ + var caretPosition = _getCaretPosition($select.searchInput[0]), + length = $select.selected.length, + // none = -1, + first = 0, + last = length-1, + curr = $selectMultiple.activeMatchIndex, + next = $selectMultiple.activeMatchIndex+1, + prev = $selectMultiple.activeMatchIndex-1, + newIndex = curr; + + if(caretPosition > 0 || ($select.search.length && key == KEY.RIGHT)) return false; + + $select.close(); + + function getNewActiveMatchIndex(){ + switch(key){ + case KEY.LEFT: + // Select previous/first item + if(~$selectMultiple.activeMatchIndex) return prev; + // Select last item + else return last; + break; + case KEY.RIGHT: + // Open drop-down + if(!~$selectMultiple.activeMatchIndex || curr === last){ + $select.activate(); + return false; + } + // Select next/last item + else return next; + break; + case KEY.BACKSPACE: + // Remove selected item and select previous/first + if(~$selectMultiple.activeMatchIndex){ + if($selectMultiple.removeChoice(curr)) { + return prev; + } else { + return curr; + } + + } else { + // If nothing yet selected, select last item + return last; + } + break; + case KEY.DELETE: + // Remove selected item and select next item + if(~$selectMultiple.activeMatchIndex){ + $selectMultiple.removeChoice($selectMultiple.activeMatchIndex); + return curr; + } + else return false; + } + } + + newIndex = getNewActiveMatchIndex(); + + if(!$select.selected.length || newIndex === false) $selectMultiple.activeMatchIndex = -1; + else $selectMultiple.activeMatchIndex = Math.min(last,Math.max(first,newIndex)); + + return true; + } + + $select.searchInput.on('keyup', function(e) { + + if ( ! KEY.isVerticalMovement(e.which) ) { + scope.$evalAsync( function () { + $select.activeIndex = $select.taggingLabel === false ? -1 : 0; + }); + } + // Push a "create new" item into array if there is a search string + if ( $select.tagging.isActivated && $select.search.length > 0 ) { + + // return early with these keys + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || KEY.isVerticalMovement(e.which) ) { + return; + } + // always reset the activeIndex to the first item when tagging + $select.activeIndex = $select.taggingLabel === false ? -1 : 0; + // taggingLabel === false bypasses all of this + if ($select.taggingLabel === false) return; + + var items = angular.copy( $select.items ); + var stashArr = angular.copy( $select.items ); + var newItem; + var item; + var hasTag = false; + var dupeIndex = -1; + var tagItems; + var tagItem; + + // case for object tagging via transform `$select.tagging.fct` function + if ( $select.tagging.fct !== undefined) { + tagItems = $select.$filter('filter')(items,{'isTag': true}); + if ( tagItems.length > 0 ) { + tagItem = tagItems[0]; + } + // remove the first element, if it has the `isTag` prop we generate a new one with each keyup, shaving the previous + if ( items.length > 0 && tagItem ) { + hasTag = true; + items = items.slice(1,items.length); + stashArr = stashArr.slice(1,stashArr.length); + } + newItem = $select.tagging.fct($select.search); + // verify the new tag doesn't match the value of a possible selection choice or an already selected item. + if ( + stashArr.some(function (origItem) { + return angular.equals(origItem, newItem); + }) || + $select.selected.some(function (origItem) { + return angular.equals(origItem, newItem); + }) + ) { + scope.$evalAsync(function () { + $select.activeIndex = 0; + $select.items = items; + }); + return; + } + if (newItem) newItem.isTag = true; + // handle newItem string and stripping dupes in tagging string context + } else { + // find any tagging items already in the $select.items array and store them + tagItems = $select.$filter('filter')(items,function (item) { + return item.match($select.taggingLabel); + }); + if ( tagItems.length > 0 ) { + tagItem = tagItems[0]; + } + item = items[0]; + // remove existing tag item if found (should only ever be one tag item) + if ( item !== undefined && items.length > 0 && tagItem ) { + hasTag = true; + items = items.slice(1,items.length); + stashArr = stashArr.slice(1,stashArr.length); + } + newItem = $select.search+' '+$select.taggingLabel; + if ( _findApproxDupe($select.selected, $select.search) > -1 ) { + return; + } + // verify the the tag doesn't match the value of an existing item from + // the searched data set or the items already selected + if ( _findCaseInsensitiveDupe(stashArr.concat($select.selected)) ) { + // if there is a tag from prev iteration, strip it / queue the change + // and return early + if ( hasTag ) { + items = stashArr; + scope.$evalAsync( function () { + $select.activeIndex = 0; + $select.items = items; + }); + } + return; + } + if ( _findCaseInsensitiveDupe(stashArr) ) { + // if there is a tag from prev iteration, strip it + if ( hasTag ) { + $select.items = stashArr.slice(1,stashArr.length); + } + return; + } + } + if ( hasTag ) dupeIndex = _findApproxDupe($select.selected, newItem); + // dupe found, shave the first item + if ( dupeIndex > -1 ) { + items = items.slice(dupeIndex+1,items.length-1); + } else { + items = []; + if (newItem) items.push(newItem); + items = items.concat(stashArr); + } + scope.$evalAsync( function () { + $select.activeIndex = 0; + $select.items = items; + + if ($select.isGrouped) { + // update item references in groups, so that indexOf will work after angular.copy + var itemsWithoutTag = newItem ? items.slice(1) : items; + $select.setItemsFn(itemsWithoutTag); + if (newItem) { + // add tag item as a new group + $select.items.unshift(newItem); + $select.groups.unshift({name: '', items: [newItem], tagging: true}); + } + } + }); + } + }); + function _findCaseInsensitiveDupe(arr) { + if ( arr === undefined || $select.search === undefined ) { + return false; + } + var hasDupe = arr.filter( function (origItem) { + if ( $select.search.toUpperCase() === undefined || origItem === undefined ) { + return false; + } + return origItem.toUpperCase() === $select.search.toUpperCase(); + }).length > 0; + + return hasDupe; + } + function _findApproxDupe(haystack, needle) { + var dupeIndex = -1; + if(angular.isArray(haystack)) { + var tempArr = angular.copy(haystack); + for (var i = 0; i <tempArr.length; i++) { + // handle the simple string version of tagging + if ( $select.tagging.fct === undefined ) { + // search the array for the match + if ( tempArr[i]+' '+$select.taggingLabel === needle ) { + dupeIndex = i; + } + // handle the object tagging implementation + } else { + var mockObj = tempArr[i]; + if (angular.isObject(mockObj)) { + mockObj.isTag = true; + } + if ( angular.equals(mockObj, needle) ) { + dupeIndex = i; + } + } + } + } + return dupeIndex; + } + + $select.searchInput.on('blur', function() { + $timeout(function() { + $selectMultiple.activeMatchIndex = -1; + }); + }); + + } + }; +}]); + +uis.directive('uiSelectNoChoice', + ['uiSelectConfig', function (uiSelectConfig) { + return { + restrict: 'EA', + require: '^uiSelect', + replace: true, + transclude: true, + templateUrl: function (tElement) { + // Needed so the uiSelect can detect the transcluded content + tElement.addClass('ui-select-no-choice'); + + // Gets theme attribute from parent (ui-select) + var theme = tElement.parent().attr('theme') || uiSelectConfig.theme; + return theme + '/no-choice.tpl.html'; + } + }; + }]); + +uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $compile) { + return { + restrict: 'EA', + require: ['^uiSelect', '^ngModel'], + link: function(scope, element, attrs, ctrls) { + + var $select = ctrls[0]; + var ngModel = ctrls[1]; + + //From view --> model + ngModel.$parsers.unshift(function (inputValue) { + // Keep original value for undefined and null + if (isNil(inputValue)) { + return inputValue; + } + + var locals = {}, + result; + locals[$select.parserResult.itemName] = inputValue; + result = $select.parserResult.modelMapper(scope, locals); + return result; + }); + + //From model --> view + ngModel.$formatters.unshift(function (inputValue) { + // Keep original value for undefined and null + if (isNil(inputValue)) { + return inputValue; + } + + var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search + locals = {}, + result; + if (data){ + var checkFnSingle = function(d){ + locals[$select.parserResult.itemName] = d; + result = $select.parserResult.modelMapper(scope, locals); + return result === inputValue; + }; + //If possible pass same object stored in $select.selected + if ($select.selected && checkFnSingle($select.selected)) { + return $select.selected; + } + for (var i = data.length - 1; i >= 0; i--) { + if (checkFnSingle(data[i])) return data[i]; + } + } + return inputValue; + }); + + //Update viewValue if model change + scope.$watch('$select.selected', function(newValue) { + if (ngModel.$viewValue !== newValue) { + ngModel.$setViewValue(newValue); + } + }); + + ngModel.$render = function() { + $select.selected = ngModel.$viewValue; + }; + + scope.$on('uis:select', function (event, item) { + $select.selected = item; + var locals = {}; + locals[$select.parserResult.itemName] = item; + + $timeout(function() { + $select.onSelectCallback(scope, { + $item: item, + $model: isNil(item) ? item : $select.parserResult.modelMapper(scope, locals) + }); + }); + }); + + scope.$on('uis:close', function (event, skipFocusser) { + $timeout(function(){ + $select.focusser.prop('disabled', false); + if (!skipFocusser) $select.focusser[0].focus(); + },0,false); + }); + + scope.$on('uis:activate', function () { + focusser.prop('disabled', true); //Will reactivate it on .close() + }); + + //Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954 + var focusser = angular.element("<input ng-disabled='$select.disabled' class='ui-select-focusser ui-select-offscreen' type='text' id='{{ $select.focusserId }}' aria-label='{{ $select.focusserTitle }}' aria-haspopup='true' role='button' />"); + $compile(focusser)(scope); + $select.focusser = focusser; + + //Input that will handle focus + $select.focusInput = focusser; + + element.parent().append(focusser); + focusser.bind("focus", function(){ + scope.$evalAsync(function(){ + $select.focus = true; + }); + }); + focusser.bind("blur", function(){ + scope.$evalAsync(function(){ + $select.focus = false; + }); + }); + focusser.bind("keydown", function(e){ + + if (e.which === KEY.BACKSPACE && $select.backspaceReset !== false) { + e.preventDefault(); + e.stopPropagation(); + $select.select(undefined); + scope.$apply(); + return; + } + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) { + return; + } + + if (e.which == KEY.DOWN || e.which == KEY.UP || e.which == KEY.ENTER || e.which == KEY.SPACE){ + e.preventDefault(); + e.stopPropagation(); + $select.activate(); + } + + scope.$digest(); + }); + + focusser.bind("keyup input", function(e){ + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || e.which == KEY.ENTER || e.which === KEY.BACKSPACE) { + return; + } + + $select.activate(focusser.val()); //User pressed some regular key, so we pass it to the search input + focusser.val(''); + scope.$digest(); + + }); + + + } + }; +}]); + +// Make multiple matches sortable +uis.directive('uiSelectSort', ['$timeout', 'uiSelectConfig', 'uiSelectMinErr', function($timeout, uiSelectConfig, uiSelectMinErr) { + return { + require: ['^^uiSelect', '^ngModel'], + link: function(scope, element, attrs, ctrls) { + if (scope[attrs.uiSelectSort] === null) { + throw uiSelectMinErr('sort', 'Expected a list to sort'); + } + + var $select = ctrls[0]; + var $ngModel = ctrls[1]; + + var options = angular.extend({ + axis: 'horizontal' + }, + scope.$eval(attrs.uiSelectSortOptions)); + + var axis = options.axis; + var draggingClassName = 'dragging'; + var droppingClassName = 'dropping'; + var droppingBeforeClassName = 'dropping-before'; + var droppingAfterClassName = 'dropping-after'; + + scope.$watch(function(){ + return $select.sortable; + }, function(newValue){ + if (newValue) { + element.attr('draggable', true); + } else { + element.removeAttr('draggable'); + } + }); + + element.on('dragstart', function(event) { + element.addClass(draggingClassName); + + (event.dataTransfer || event.originalEvent.dataTransfer).setData('text', scope.$index.toString()); + }); + + element.on('dragend', function() { + removeClass(draggingClassName); + }); + + var move = function(from, to) { + /*jshint validthis: true */ + this.splice(to, 0, this.splice(from, 1)[0]); + }; + + var removeClass = function(className) { + angular.forEach($select.$element.querySelectorAll('.' + className), function(el){ + angular.element(el).removeClass(className); + }); + }; + + var dragOverHandler = function(event) { + event.preventDefault(); + + var offset = axis === 'vertical' ? event.offsetY || event.layerY || (event.originalEvent ? event.originalEvent.offsetY : 0) : event.offsetX || event.layerX || (event.originalEvent ? event.originalEvent.offsetX : 0); + + if (offset < (this[axis === 'vertical' ? 'offsetHeight' : 'offsetWidth'] / 2)) { + removeClass(droppingAfterClassName); + element.addClass(droppingBeforeClassName); + + } else { + removeClass(droppingBeforeClassName); + element.addClass(droppingAfterClassName); + } + }; + + var dropTimeout; + + var dropHandler = function(event) { + event.preventDefault(); + + var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text'), 10); + + // prevent event firing multiple times in firefox + $timeout.cancel(dropTimeout); + dropTimeout = $timeout(function() { + _dropHandler(droppedItemIndex); + }, 20); + }; + + var _dropHandler = function(droppedItemIndex) { + var theList = scope.$eval(attrs.uiSelectSort); + var itemToMove = theList[droppedItemIndex]; + var newIndex = null; + + if (element.hasClass(droppingBeforeClassName)) { + if (droppedItemIndex < scope.$index) { + newIndex = scope.$index - 1; + } else { + newIndex = scope.$index; + } + } else { + if (droppedItemIndex < scope.$index) { + newIndex = scope.$index; + } else { + newIndex = scope.$index + 1; + } + } + + move.apply(theList, [droppedItemIndex, newIndex]); + + $ngModel.$setViewValue(Date.now()); + + scope.$apply(function() { + scope.$emit('uiSelectSort:change', { + array: theList, + item: itemToMove, + from: droppedItemIndex, + to: newIndex + }); + }); + + removeClass(droppingClassName); + removeClass(droppingBeforeClassName); + removeClass(droppingAfterClassName); + + element.off('drop', dropHandler); + }; + + element.on('dragenter', function() { + if (element.hasClass(draggingClassName)) { + return; + } + + element.addClass(droppingClassName); + + element.on('dragover', dragOverHandler); + element.on('drop', dropHandler); + }); + + element.on('dragleave', function(event) { + if (event.target != element) { + return; + } + + removeClass(droppingClassName); + removeClass(droppingBeforeClassName); + removeClass(droppingAfterClassName); + + element.off('dragover', dragOverHandler); + element.off('drop', dropHandler); + }); + } + }; +}]); + +uis.directive('uisOpenClose', ['$parse', '$timeout', function ($parse, $timeout) { + return { + restrict: 'A', + require: 'uiSelect', + link: function (scope, element, attrs, $select) { + $select.onOpenCloseCallback = $parse(attrs.uisOpenClose); + + scope.$watch('$select.open', function (isOpen, previousState) { + if (isOpen !== previousState) { + $timeout(function () { + $select.onOpenCloseCallback(scope, { + isOpen: isOpen + }); + }); + } + }); + } + }; +}]); + +/** + * Parses "repeat" attribute. + * + * Taken from AngularJS ngRepeat source code + * See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L211 + * + * Original discussion about parsing "repeat" attribute instead of fully relying on ng-repeat: + * https://github.com/angular-ui/ui-select/commit/5dd63ad#commitcomment-5504697 + */ + +uis.service('uisRepeatParser', ['uiSelectMinErr','$parse', function(uiSelectMinErr, $parse) { + var self = this; + + /** + * Example: + * expression = "address in addresses | filter: {street: $select.search} track by $index" + * itemName = "address", + * source = "addresses | filter: {street: $select.search}", + * trackByExp = "$index", + */ + self.parse = function(expression) { + + + var match; + //var isObjectCollection = /\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)/.test(expression); + // If an array is used as collection + + // if (isObjectCollection){ + // 000000000000000000000000000000111111111000000000000000222222222222220033333333333333333333330000444444444444444444000000000000000055555555555000000000000000000000066666666600000000 + match = expression.match(/^\s*(?:([\s\S]+?)\s+as\s+)?(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(\s*[\s\S]+?)?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); + + // 1 Alias + // 2 Item + // 3 Key on (key,value) + // 4 Value on (key,value) + // 5 Source expression (including filters) + // 6 Track by + + if (!match) { + throw uiSelectMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", + expression); + } + + var source = match[5], + filters = ''; + + // When using (key,value) ui-select requires filters to be extracted, since the object + // is converted to an array for $select.items + // (in which case the filters need to be reapplied) + if (match[3]) { + // Remove any enclosing parenthesis + source = match[5].replace(/(^\()|(\)$)/g, ''); + // match all after | but not after || + var filterMatch = match[5].match(/^\s*(?:[\s\S]+?)(?:[^\|]|\|\|)+([\s\S]*)\s*$/); + if(filterMatch && filterMatch[1].trim()) { + filters = filterMatch[1]; + source = source.replace(filters, ''); + } + } + + return { + itemName: match[4] || match[2], // (lhs) Left-hand side, + keyName: match[3], //for (key, value) syntax + source: $parse(source), + filters: filters, + trackByExp: match[6], + modelMapper: $parse(match[1] || match[4] || match[2]), + repeatExpression: function (grouped) { + var expression = this.itemName + ' in ' + (grouped ? '$group.items' : '$select.items'); + if (this.trackByExp) { + expression += ' track by ' + this.trackByExp; + } + return expression; + } + }; + + }; + + self.getGroupNgRepeatExpression = function() { + return '$group in $select.groups track by $group.name'; + }; + +}]); + +}()); +angular.module("ui.select").run(["$templateCache", function($templateCache) {$templateCache.put("bootstrap/choices.tpl.html","<ul class=\"ui-select-choices ui-select-choices-content ui-select-dropdown dropdown-menu\" ng-show=\"$select.open && $select.items.length > 0\"><li class=\"ui-select-choices-group\" id=\"ui-select-choices-{{ $select.generatedId }}\"><div class=\"divider\" ng-show=\"$select.isGrouped && $index > 0\"></div><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label dropdown-header\" ng-bind=\"$group.name\"></div><div ng-attr-id=\"ui-select-choices-row-{{ $select.generatedId }}-{{$index}}\" class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this), disabled: $select.isDisabled(this)}\" role=\"option\"><span class=\"ui-select-choices-row-inner\"></span></div></li></ul>"); +$templateCache.put("bootstrap/match-multiple.tpl.html","<span class=\"ui-select-match\"><span ng-repeat=\"$item in $select.selected track by $index\"><span class=\"ui-select-match-item btn btn-default btn-xs\" tabindex=\"-1\" type=\"button\" ng-disabled=\"$select.disabled\" ng-click=\"$selectMultiple.activeMatchIndex = $index;\" ng-class=\"{\'btn-primary\':$selectMultiple.activeMatchIndex === $index, \'select-locked\':$select.isLocked(this, $index)}\" ui-select-sort=\"$select.selected\"><span class=\"close ui-select-match-close\" ng-hide=\"$select.disabled\" ng-click=\"$selectMultiple.removeChoice($index)\"> ×</span> <span uis-transclude-append=\"\"></span></span></span></span>"); +$templateCache.put("bootstrap/match.tpl.html","<div class=\"ui-select-match\" ng-hide=\"$select.open && $select.searchEnabled\" ng-disabled=\"$select.disabled\" ng-class=\"{\'btn-default-focus\':$select.focus}\"><span tabindex=\"-1\" class=\"btn btn-default form-control ui-select-toggle\" aria-label=\"{{ $select.baseTitle }} activate\" ng-disabled=\"$select.disabled\" ng-click=\"$select.activate()\" style=\"outline: 0;\"><span ng-show=\"$select.isEmpty()\" class=\"ui-select-placeholder text-muted\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty()\" class=\"ui-select-match-text pull-left\" ng-class=\"{\'ui-select-allow-clear\': $select.allowClear && !$select.isEmpty()}\" ng-transclude=\"\"></span> <i class=\"caret pull-right\" ng-click=\"$select.toggle($event)\"></i> <a ng-show=\"$select.allowClear && !$select.isEmpty() && ($select.disabled !== true)\" aria-label=\"{{ $select.baseTitle }} clear\" style=\"margin-right: 10px\" ng-click=\"$select.clear($event)\" class=\"btn btn-xs btn-link pull-right\"><i class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></i></a></span></div>"); +$templateCache.put("bootstrap/no-choice.tpl.html","<ul class=\"ui-select-no-choice dropdown-menu\" ng-show=\"$select.items.length == 0\"><li ng-transclude=\"\"></li></ul>"); +$templateCache.put("bootstrap/select-multiple.tpl.html","<div class=\"ui-select-container ui-select-multiple ui-select-bootstrap dropdown form-control\" ng-class=\"{open: $select.open}\"><div><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"ui-select-search input-xs\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-disabled=\"$select.disabled\" ng-click=\"$select.activate()\" ng-model=\"$select.search\" role=\"combobox\" aria-expanded=\"{{$select.open}}\" aria-label=\"{{$select.baseTitle}}\" ng-class=\"{\'spinner\': $select.refreshing}\" ondrop=\"return false;\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>"); +$templateCache.put("bootstrap/select.tpl.html","<div class=\"ui-select-container ui-select-bootstrap dropdown\" ng-class=\"{open: $select.open}\"><div class=\"ui-select-match\"></div><span ng-show=\"$select.open && $select.refreshing && $select.spinnerEnabled\" class=\"ui-select-refreshing {{$select.spinnerClass}}\"></span> <input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" aria-expanded=\"true\" aria-label=\"{{ $select.baseTitle }}\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" class=\"form-control ui-select-search\" ng-class=\"{ \'ui-select-search-hidden\' : !$select.searchEnabled }\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-show=\"$select.open\"><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>"); +$templateCache.put("select2/choices.tpl.html","<ul tabindex=\"-1\" class=\"ui-select-choices ui-select-choices-content select2-results\"><li class=\"ui-select-choices-group\" ng-class=\"{\'select2-result-with-children\': $select.choiceGrouped($group) }\"><div ng-show=\"$select.choiceGrouped($group)\" class=\"ui-select-choices-group-label select2-result-label\" ng-bind=\"$group.name\"></div><ul id=\"ui-select-choices-{{ $select.generatedId }}\" ng-class=\"{\'select2-result-sub\': $select.choiceGrouped($group), \'select2-result-single\': !$select.choiceGrouped($group) }\"><li role=\"option\" ng-attr-id=\"ui-select-choices-row-{{ $select.generatedId }}-{{$index}}\" class=\"ui-select-choices-row\" ng-class=\"{\'select2-highlighted\': $select.isActive(this), \'select2-disabled\': $select.isDisabled(this)}\"><div class=\"select2-result-label ui-select-choices-row-inner\"></div></li></ul></li></ul>"); +$templateCache.put("select2/match-multiple.tpl.html","<span class=\"ui-select-match\"><li class=\"ui-select-match-item select2-search-choice\" ng-repeat=\"$item in $select.selected track by $index\" ng-class=\"{\'select2-search-choice-focus\':$selectMultiple.activeMatchIndex === $index, \'select2-locked\':$select.isLocked(this, $index)}\" ui-select-sort=\"$select.selected\"><span uis-transclude-append=\"\"></span> <a href=\"javascript:;\" class=\"ui-select-match-close select2-search-choice-close\" ng-click=\"$selectMultiple.removeChoice($index)\" tabindex=\"-1\"></a></li></span>"); +$templateCache.put("select2/match.tpl.html","<a class=\"select2-choice ui-select-match\" ng-class=\"{\'select2-default\': $select.isEmpty()}\" ng-click=\"$select.toggle($event)\" aria-label=\"{{ $select.baseTitle }} select\"><span ng-show=\"$select.isEmpty()\" class=\"select2-chosen\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty()\" class=\"select2-chosen\" ng-transclude=\"\"></span> <abbr ng-if=\"$select.allowClear && !$select.isEmpty()\" class=\"select2-search-choice-close\" ng-click=\"$select.clear($event)\"></abbr> <span class=\"select2-arrow ui-select-toggle\"><b></b></span></a>"); +$templateCache.put("select2/no-choice.tpl.html","<div class=\"ui-select-no-choice dropdown\" ng-show=\"$select.items.length == 0\"><div class=\"dropdown-content\"><div data-selectable=\"\" ng-transclude=\"\"></div></div></div>"); +$templateCache.put("select2/select-multiple.tpl.html","<div class=\"ui-select-container ui-select-multiple select2 select2-container select2-container-multi\" ng-class=\"{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled}\"><ul class=\"select2-choices\"><span class=\"ui-select-match\"></span><li class=\"select2-search-field\"><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" role=\"combobox\" aria-expanded=\"true\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" aria-label=\"{{ $select.baseTitle }}\" aria-activedescendant=\"ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}\" class=\"select2-input ui-select-search\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-disabled=\"$select.disabled\" ng-hide=\"$select.disabled\" ng-model=\"$select.search\" ng-click=\"$select.activate()\" style=\"width: 34px;\" ondrop=\"return false;\"></li></ul><div class=\"ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open || $select.items.length === 0}\"><div class=\"ui-select-choices\"></div></div></div>"); +$templateCache.put("select2/select.tpl.html","<div class=\"ui-select-container select2 select2-container\" ng-class=\"{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled, \'select2-container-active\': $select.focus, \'select2-allowclear\': $select.allowClear && !$select.isEmpty()}\"><div class=\"ui-select-match\"></div><div class=\"ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open}\"><div class=\"search-container\" ng-class=\"{\'ui-select-search-hidden\':!$select.searchEnabled, \'select2-search\':$select.searchEnabled}\"><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" ng-class=\"{\'select2-active\': $select.refreshing}\" role=\"combobox\" aria-expanded=\"true\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" aria-label=\"{{ $select.baseTitle }}\" class=\"ui-select-search select2-input\" ng-model=\"$select.search\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div></div>"); +$templateCache.put("selectize/choices.tpl.html","<div ng-show=\"$select.open\" class=\"ui-select-choices ui-select-dropdown selectize-dropdown\" ng-class=\"{\'single\': !$select.multiple, \'multi\': $select.multiple}\"><div class=\"ui-select-choices-content selectize-dropdown-content\"><div class=\"ui-select-choices-group optgroup\"><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label optgroup-header\" ng-bind=\"$group.name\"></div><div role=\"option\" class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this), disabled: $select.isDisabled(this)}\"><div class=\"option ui-select-choices-row-inner\" data-selectable=\"\"></div></div></div></div></div>"); +$templateCache.put("selectize/match-multiple.tpl.html","<div class=\"ui-select-match\" data-value=\"\" ng-repeat=\"$item in $select.selected track by $index\" ng-click=\"$selectMultiple.activeMatchIndex = $index;\" ng-class=\"{\'active\':$selectMultiple.activeMatchIndex === $index}\" ui-select-sort=\"$select.selected\"><span class=\"ui-select-match-item\" ng-class=\"{\'select-locked\':$select.isLocked(this, $index)}\"><span uis-transclude-append=\"\"></span> <span class=\"remove ui-select-match-close\" ng-hide=\"$select.disabled\" ng-click=\"$selectMultiple.removeChoice($index)\">×</span></span></div>"); +$templateCache.put("selectize/match.tpl.html","<div ng-hide=\"$select.searchEnabled && ($select.open || $select.isEmpty())\" class=\"ui-select-match\"><span ng-show=\"!$select.searchEnabled && ($select.isEmpty() || $select.open)\" class=\"ui-select-placeholder text-muted\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty() || $select.open\" ng-transclude=\"\"></span></div>"); +$templateCache.put("selectize/no-choice.tpl.html","<div class=\"ui-select-no-choice selectize-dropdown\" ng-show=\"$select.items.length == 0\"><div class=\"selectize-dropdown-content\"><div data-selectable=\"\" ng-transclude=\"\"></div></div></div>"); +$templateCache.put("selectize/select-multiple.tpl.html","<div class=\"ui-select-container selectize-control multi plugin-remove_button\" ng-class=\"{\'open\': $select.open}\"><div class=\"selectize-input\" ng-class=\"{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}\" ng-click=\"$select.open && !$select.searchEnabled ? $select.toggle($event) : $select.activate()\"><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" class=\"ui-select-search\" ng-class=\"{\'ui-select-search-hidden\':!$select.searchEnabled}\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-model=\"$select.search\" ng-disabled=\"$select.disabled\" aria-expanded=\"{{$select.open}}\" aria-label=\"{{ $select.baseTitle }}\" ondrop=\"return false;\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>"); +$templateCache.put("selectize/select.tpl.html","<div class=\"ui-select-container selectize-control single\" ng-class=\"{\'open\': $select.open}\"><div class=\"selectize-input\" ng-class=\"{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}\" ng-click=\"$select.open && !$select.searchEnabled ? $select.toggle($event) : $select.activate()\"><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" class=\"ui-select-search ui-select-toggle\" ng-class=\"{\'ui-select-search-hidden\':!$select.searchEnabled}\" ng-click=\"$select.toggle($event)\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-hide=\"!$select.isEmpty() && !$select.open\" ng-disabled=\"$select.disabled\" aria-label=\"{{ $select.baseTitle }}\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>");}]);
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/api_doc.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/api_doc.html deleted file mode 100644 index 342406c..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/api_doc.html +++ /dev/null @@ -1,26 +0,0 @@ -<!-- - ============LICENSE_START========================================== - =================================================================== - Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - =================================================================== - - Unless otherwise specified, all software contained herein is licensed - under the Apache License, Version 2.0 (the "License"); - you may not use this software except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - ============LICENSE_END============================================ - --> -<div id="page-content"> - <iframe scrolling="yes" frameborder="0" style="width:100%; height: 800px;" - ng-src="api-specs.html"> - </iframe> -</div>
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/appDS2.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/appDS2.js index ebb35cd..f29d7ad 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/appDS2.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/appDS2.js @@ -1,30 +1,14 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ - /* Angular application for the EC Dashboard web UI */ var appDS2 = angular.module("abs", [ 'ngCookies', 'ngRoute', 'ngMessages','ngSanitize', - 'ui.bootstrap', 'ui.bootstrap.modal', + 'ui.bootstrap', 'ui.bootstrap.modal', 'ui.select', 'b2b.att', - 'modalServices' + 'modalServices', 'LocalStorageModule' ] - ); + ).config(function($sceDelegateProvider) { + $sceDelegateProvider.resourceUrlWhitelist(['**']); + }).config(['localStorageServiceProvider', function(localStorageServiceProvider) { + localStorageServiceProvider.setPrefix('eom') + .setStorageType('sessionStorage'); + }]); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller-service.js index 65495f1..cfa8be7 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller-service.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller-service.js @@ -1,24 +1,3 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ - appDS2.factory('ControllerService', function ($http, $q, $log) { return { /** @@ -39,20 +18,20 @@ appDS2.factory('ControllerService', function ($http, $q, $log) { return $q.reject(error.statusText); }); }, - getApiSwaggerSpec: function() { - return $http({ - method: 'GET', - url: 'nb-api/api-docs', - cache: true, - responseType: 'json' - }).then(function(response) { - return response.data; - }, - function(error) { - $log.error('ControllerService.getApiSwaggerSpec failed: ' + JSON.stringify(error)); - return $q.reject(error.statusText); - }); - }, + getApiSwaggerSpec: function() { + return $http({ + method: 'GET', + url: 'api-docs', + cache: true, + responseType: 'json' + }).then(function(response) { + return response.data; + }, + function(error) { + $log.error('ControllerService.getApiSwaggerSpec failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, /** * Gets the cloudify tenant names. * @@ -74,70 +53,114 @@ appDS2.factory('ControllerService', function ($http, $q, $log) { return $q.reject(error.statusText); }); }, + getConsulLink: function() { + return $http({ + method: 'GET', + url: 'consul_url', + cache: false, + responseType: 'text' + }).then(function(response) { + if (response.data == null) + return $q.reject('ControllerService.getConsulLink: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('ControllerService.getConsulLink failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, /** * Gets the ops tools info * */ - getOpsUrls: function() { + getDcaeLinks: function() { return $http({ method: 'GET', - url: 'ops', - cache: true, - responseType: 'json' + url: 'dcae_links', + cache: false, + responseType: 'text' }).then(function(response) { - if (response.data == null || typeof response.data != 'object') - return $q.reject('ControllerService.getOpsUrls: response.data null or not object'); + if (response.data == null) + return $q.reject('ControllerService.getDcaeLinks: response.data null or not object'); else return response.data; }, function(error) { - $log.error('ControllerService.getOpsUrls failed: ' + JSON.stringify(error)); + $log.error('ControllerService.getDcaeLinks failed: ' + JSON.stringify(error)); return $q.reject(error.statusText); }); }, - /** - * Gets ECOMP-C Endpoint objects. - * No provision for pagination here. - * @return {JSON} Response object from remote side - */ - getControllers: function() { - // cache control for IE - var cc = "?cc=" + new Date().getTime().toString(); + + getOpsToolUrls: function() { return $http({ - method: 'GET', - url: 'controllers' + cc, - cache: true, - responseType: 'json' + method: 'GET', + url: 'ops_links', + cache: false, + responseType: 'json' }).then(function(response) { if (response.data == null || typeof response.data != 'object') - return $q.reject('ControllerService.getControllers: response.data null or not object'); + return $q.reject('ControllerService.getOpsToolUrls: response.data null or not object'); else return response.data; }, function(error) { - $log.error('ControllerService.getControllers failed: ' + JSON.stringify(error)); + $log.error('ControllerService.getOpsToolUrls failed: ' + JSON.stringify(error)); return $q.reject(error.statusText); - }); + }); }, - setControllerSelection: function(row) { - // $log.debug('ControllerService.setControllerSelection: invoked with ' + JSON.stringify(row)); + //Get the links from database table along with site/tenant list + getOpsToolMenuLinks: function() { return $http({ - method: 'POST', - url: 'controllers', - data: row, - responseType: 'json' + method: 'GET', + url: 'ops_menu_links', + cache: false, + responseType: 'json' }).then(function(response) { if (response.data == null || typeof response.data != 'object') - return $q.reject('ControllerService.setControllerSelection: response.data null or not object'); + return $q.reject('ControllerService.getOpsToolMenuLinks: response.data null or not object'); else return response.data; }, function(error) { - $log.error('ControllerService.setControllerSelection failed: ' + JSON.stringify(error)); + $log.error('ControllerService.getOpsToolMenuLinks failed: ' + JSON.stringify(error)); return $q.reject(error.statusText); - }); - } - + }); + }, + getUserRoleData: function() { + return $http({ + method: 'GET', + url: 'user-role-details', + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('ControllerService.getUserRoleData: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('ControllerService.getUserRoleData failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getPluginsCount: function() { + return $http({ + method: 'GET', + url: 'plugins-count', + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('ControllerService.getPluginsCount: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('ControllerService.getPluginsCount failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + } }; }); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_popup_templates.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/ecd_popup_templates.html index fe4d505..9e640e9 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_popup_templates.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/ecd_popup_templates.html @@ -62,4 +62,4 @@ </button> </div> </div> -</script> +</script>
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions-view-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions-view-controller.js deleted file mode 100644 index 2491e50..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions-view-controller.js +++ /dev/null @@ -1,45 +0,0 @@ -appDS2.controller('executionsViewController', function($scope, $rootScope, ControllerService, $modal, ExecutionService, $log) { - - $scope.parent = { 'blueprint_id': 'Root', 'parent': 'parent' }; - $scope.ecdapp = {}; - $scope.ecdapp.isDataLoading = false; - $scope.ecdapp.appLabel = ""; - $rootScope.tenantList = { - tenant: '', - data: {} - }; - var debug = false; - - var getTenants = function() { - ControllerService.getTenants() - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("executionsViewController.getTenants failed: " + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - $rootScope.tenantList.data = jsonObj.items; - $rootScope.tenantList.tenant = jsonObj.items[0].name; - } - }, function(error) { - $log.error("executionsViewController.loadTable failed: " + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - }); - }; - - var getAppLabel = function() { - ControllerService.getAppLabel().then(function(jsonObj) { - if (debug) - $log.debug("Controller.getAppLabel succeeded: " + JSON.stringify(jsonObj)); - $scope.ecdapp.appLabel = jsonObj; - }, function(error) { - $log.error("Controller.getAppLabel failed: " + error); - }); - }; - // Initialize the page - getAppLabel(); - getTenants(); - -}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions_view.html deleted file mode 100644 index 5623b1c..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions_view.html +++ /dev/null @@ -1,5 +0,0 @@ -<div id="page-content"> - - <h4 class="heading-page" id="controllers">DCAE Dashboard</h4> -</div> - diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/http-interceptor.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/http-interceptor.js deleted file mode 100644 index 0f5410d..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/http-interceptor.js +++ /dev/null @@ -1,29 +0,0 @@ -appDS2.factory('httpInterceptor', function ($q, $rootScope, $location) { - return { - 'request': function (config) { - return config; - }, - /* - 'requestError': function (rejection) { - }, - */ - 'response': function (response) { - if (response.data == null) { - var loc = location.pathname; - console.log("location path name: " + loc); - var loc1 = loc.replace("/", ""); - var loc2 = loc1.replace("/ecd", "/login.htm"); - console.log("location url: " + loc2); - alert("Your session has expired. Please log in again..."); - location.replace("/"+loc2); - } - return response; - }, - // optional method - 'responseError': function (rejection) { - } - }; - }) - .config(function($httpProvider) { - $httpProvider.interceptors.push('httpInterceptor'); - });
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-instances-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-instances-controller.js deleted file mode 100644 index f07d1b3..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-instances-controller.js +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - *******************************************************************************/ -appDS2.controller('selectEcompcController', function( - $scope, $rootScope, $log, $modalInstance, message, ControllerService) { - - // message brings the table items - - 'use strict'; - - // Set to true for verbose output - var debug = false; - - // this object holds data and functions - $scope.ecdapp = {}; - $scope.ecdapp.tableData = message.items; - - // Populate the model that drives the radio buttons. - // Radio buttons require a model with the value of the button - // that is selected. The data comes across with a boolean - // indicator on each row, selected or not, which is useless - // for driving the radio buttons. This model uses the URL - // as the unique value. - $scope.ecdapp.radiobutton = { - url : null - }; - for (var rowNum in message.items) { - let row = message.items[rowNum]; - if (debug) - $log.debug('selectEcompcController: row is ' + JSON.stringify(row)); - if (row.selected) - $scope.ecdapp.radiobutton.url = row.url; - } - - /** - * Handles a click on radio button to select a controller. - */ - $scope.ecdapp.selectController = function(row) { - if (debug) - $log.debug('selectController: row is ' + JSON.stringify(row)); - if (row == null || row.url == null) - $log.error('selectController invoked with bad argument'); - else - ControllerService.setControllerSelection(row).then(function(data) { - $rootScope.$broadcast('controllerChange', {name: row.name}) - }, - function(error) { - $log.error('selectController failed: ' + error); - }); - }; - -}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-router.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-router.js deleted file mode 100644 index 0b43341..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-router.js +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * =============LICENSE_START========================================================= - * - * ================================================================================= - * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ -appDS2.config(function($routeProvider) { - $routeProvider - .when('/api', { - templateUrl: 'app/ccsdk/home/api_doc.html', - controller : '' - }) - .when('/api-spec', { - templateUrl: 'app/ccsdk/home/rest-api-spec.html', - controller : 'apiDocsController' - }) - .when('/ibp', { - templateUrl: 'app/ccsdk/inventory/inventory_blueprint_table.html', - controller : 'inventoryBlueprintTableController' - }) - .when('/idep', { - templateUrl: 'app/ccsdk/inventory/inventory_deployment_table.html', - controller : 'inventoryDeploymentTableController' - }) - .when('/idep/:depId', { - templateUrl: 'app/ccsdk/inventory/inventory_deployment_table.html', - controller : 'inventoryDeploymentTableController' - }) - .when('/sh', { - templateUrl: 'app/ccsdk/consul/service_health_table.html', - controller : 'serviceHealthTableController' - }) - .when('/nh', { - templateUrl: 'app/ccsdk/consul/node_table.html', - controller : 'nodeTableController' - }) - .when('/dc', { - templateUrl: 'app/ccsdk/consul/datacenter_table.html', - controller : 'datacenterTableController' - }) - .when('/profile/:profileId', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html', - controller: 'selfProfileController' - }) - .when('/profile_search', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html', - controller : "profileSearchCtrlDS2" - }) - .when('/post_search', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/post.html', - controller: 'postController' - }) - .when('/self_profile', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html', - controller: 'selfProfileController' - }) - .when('/role_list', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html', - controller : 'adminController' - }) - .when('/role_function_list', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html', - controller : "adminController" - }) - .when('/jcs_admin', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html', - controller: 'adminController' - }) - .when('/admin_menu_edit', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html', - controller: 'AdminMenuEditController' - }) - .when('/usage_list', { - templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/usage.html', - controller: 'usageListControllerDS2' - }) - .otherwise({ - templateUrl: 'app/ccsdk/home/executions_view.html', - controller : 'executionsViewController' - }) - ; - -});
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-style.css b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-style.css deleted file mode 100644 index a4e9a97..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-style.css +++ /dev/null @@ -1,301 +0,0 @@ -/* Styles for ECOMP Controller Dashboard */ - -.content-container { - min-height: 650px; - width: calc(100% - 50px); -} - -.ecd-error-message { - font-size: 14px; - font-weight: bold; - color: red; -} - -.ecd-icon-display { - font-size: 18px; -} - -.ecd-icon-action { - font-size: 18px; -} - -.ecd-icon-action:hover { - color: red; - text-decoration: none; -} - -.selected { - background-color:black; - color:white; - font-weight:bold; -} -.red-background { - background-color: #ff0000b3; - } -.green-background { - background-color: #bbf0bb; - } -.td-error { - border-top: 5px dotted red; - border-bottom: 5px dotted red; - } -.menu { - display: none; - z-index: 1000; - border: 1px dotted; - border-radius: 5px; - padding: 10px; - width: 50%; - background: azure; - position: fixed; - overflow: scroll; -} - -.show-menu { - z-index: 800; -} - -#show-menu { - display: none; -} - -#show-menu:checked ~ .menu { - display: block; -} - -#show-menu:checked ~ .show-menu { - color: blue; -} - -.menu-off { - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - z-index: 700; - display: none; -} - -.menu-off { - display: none; -} - -#show-menu:checked ~ .menu-off { - display: block; -} - -#show-menu:checked ~ .show-menu { - display: none; -} - -.menu-off input[type=checkbox]:checked ~ .menu { - display: none; -} - -.menu-off input[type=checkbox]:checked ~ .show-menu { - display: block; -} - -td > .btn-group { - min-width: 0; - width: auto; -} - -.dropup, -.dropdown { - position: relative; -} -.dropdown-toggle:focus { - outline: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #777; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-menu-right { - right: 0; - left: auto; -} -.dropdown-menu-left { - right: auto; - left: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap; -} -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px dashed; - border-bottom: 4px solid \9; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } -} - -.dropdown-menu li { - margin-bottom: 10px; -} - -.dropdown-menu li div { - padding-left: 5px; -} - -.dropdown-menu li div i { - margin-right: 5px; -} - -td > .btn-group > .btn { - min-width: 0; - color: #0568ae; -} - -td > .btn-group > .btn> i { - font-size: 30px; -} - -li > a.active { - font-weight: bolder; - outline: thin dotted #666; -} - -tr:hover { - background-color: #f2f2f2; -} - -tr:focus { - background-color: #f2f2f2; -} - -.modalwrapper.modal-docked .modal-jumbo { - max-height: 100%; - height: 100%; - overflow: hidden; - top: 0; - width: 100%; - max-width: 100%; -} - -#addAppDiv { - padding-left: 10px; - background: lightgray; - border-radius: 5px; - padding-bottom: 15px; -} - -.field-group.error .error-msg { - color: red; - display: block; - font-size: 14px; - line-height: 14px; - font-family: "Omnes-ATT-W02-Medium"; - position: relative; - padding-left: 18px; - margin-top: 10px; -} - -.heading-page { - margin-bottom: 20px; -} diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_instances_popup.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_instances_popup.html deleted file mode 100644 index bc523aa..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_instances_popup.html +++ /dev/null @@ -1,86 +0,0 @@ -<script type="text/ng-template" id="ecompc_instances_popup.html"> -<style> - .ecd-parameter-table - { - border: 1px; - width: 550px; - height: 225px; - overflow: auto; - } - .modal - { - display:block - } - .radio input:checked + .skin:after{ - height: 22px; - width: 22px; - } - .close-button - { - background: #0568ae; - color: #ffffff;"; - } - -</style> - - <div class="b2b-modal-header ng-scope"> - <h1 class="heading-page" id="controllerInstance">Select ECOMP-C Instance</h1> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <div b2b-table - id="controllers-modal" - class="b2b-table-div" - table-data="ecdapp.tableData" - search-string="ecdapp.searchString" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - <table> - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header sortable="false">Selected</th> - <th b2b-table-header key="name">Name</th> - <th b2b-table-header key="url">URL</th> - </tr> - </thead> - - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData"> - <tr id="tr-rowData"> - <td b2b-table-body> - <label class="radio"> - <input - type="radio" - name="ecdSelGroup" - title="rowData.url" - ng-value="rowData.url" - ng-model="ecdapp.radiobutton.url" - ng-change="ecdapp.selectController(rowData);"> - <i class="skin"></i> - <span></span> - </label> - </td> - <td b2b-table-body - ng-bind="rowData.name"/> - <td b2b-table-body - ng-bind="rowData.url"/> - </tr> - </tbody> - </table> - </div> - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-small close-button" type="button" ng-click="$close()"> - Close - </button> - </div> - </div> - -</script> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-controller.js deleted file mode 100644 index 99005fb..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-controller.js +++ /dev/null @@ -1,113 +0,0 @@ -appDS2.controller('treeViewController',function( - $scope, $rootScope, $log, $modal, ExecutionService, ControllerService){ - - 'use strict'; - - // Set to true for verbose output - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.isDataLoading = false; - $scope.ecdapp.isRequestFailed = false; - $scope.orgChart = true; - $scope.status = ''; - var selectedItem = { - name: '' - }; - // Initial data as eye candy - $scope.orgChartData = [ { 'blueprint_id': 'Root', 'parent': 'parent' } ]; - var controllersList = []; - - var getControllers = function(){ - ControllerService.getControllers().then(function(jsonObj) { - if (debug) - $log.debug("treeViewController.getControllers succeeded: " + JSON.stringify(jsonObj)); - // Empty - controllersList.length = 0; - // Refill - jsonObj.filter(function(d) { - controllersList.push(d); - if (d.selected) - selectedItem = d; - return; - }); - $scope.ecdapp.loadTable(); - }, function(error) { - alert('Failed to load controllers. Please retry.'); - $log.error("treeViewController.getControllers failed: " + error); - }); - } - - /** - * Called from the directive when user picks a status value. - */ - $scope.ecdapp.loadTable = function(status) { - $scope.ecdapp.isDataLoading = true; - $scope.status = status; - // Empty list and create the root controller item - $scope.orgChartData.length = 0; - $scope.orgChartData.push({ - "blueprint_id": selectedItem.name, - "parent": "parent" - }); - ExecutionService.getExecutionsByStatus(status).then( - function(jsonObj) { - if (jsonObj.error) { - $log.error("treeViewController.loadTable failed: " - + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - } else { - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - for (var i=0; i < jsonObj.items.length; i++) { - $scope.orgChartData.push(jsonObj.items[i]); - } - $scope.$broadcast('listenEvent', {data: $scope.orgChartData} ); - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error("treeViewController.loadTable failed: " - + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.isDataLoading = false; - }); - }; - - // Listens for change of the selected controller - $rootScope.$on('controllerChange', function(e, d){ - $scope.orgChartData[0].blueprint_id = d.name; - $scope.$broadcast('listenEvent', {data: $scope.orgChartData}); - }) - - // Shows popup with list of controllers - $scope.ecdapp.showEcompCInstancesModalPopup = function() { - var modalInstance = $modal.open({ - templateUrl : 'ecompc_instances_popup.html', - controller : 'selectEcompcController', - windowClass: 'modal-docked', - sizeClass: 'modal-medium', - resolve : { - message : function() { - return { items: controllersList } - } - } - }); - modalInstance.result.then(function(response) { - // Always reload the table - // $log.debug('modalInstance: reloading controllers'); - getControllers('active'); - }, - function(error) { - // Should never happen - $log.error('modalInstance: ERROR!?'); - }); - }; - - // Populate the table on load. - getControllers('active'); - -}); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-directive.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-directive.js deleted file mode 100644 index 834026b..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-directive.js +++ /dev/null @@ -1,165 +0,0 @@ -(function() { - 'use strict'; - - appDS2.directive("orgChart", supervisorOrgChart); - supervisorOrgChart.$inject = ['$http', '$templateCache', 'ExecutionService']; - - function supervisorOrgChart($http, $templateCache, ExecutionService) { - return { - restrict: 'E', - scope: { - data: '=', - getCall: '&', - modalCall: '&', - status: '=' - }, - - link: function(scope, elem, attrs) { - - scope.$on('listenEvent', function(event, data) { - data = data.data; - scope.data = data; - $('.jOrgChart').remove(); - drawOrgChart(data); - }); - - - var items = [], - mCheck = []; - var currentZoom = 100; - var data = scope.data; - var selectedStatus = scope.status; - function statusSelectoin(status){ - $('#statusclick li').removeClass('active'); - scope.getCall()(status); - } - - function drawOrgChart(data, supervisorOrg) { - items = []; - var itemHtml = ""; - for(var i=0; i<data.length; i++){ - loops(data[i]); - } - function loops(root) { - var className; - if (root.parent == "parent") { - items.push("<li class='root '>" + - "<div><div class='label_node' style='position:relative'>" + - "<span class='' style='position:absolute; left:1px; top:5px'>"+ - "<div class='dropdown dd_"+root.id+"'>"+ - "<div style='float: right;'>"+ - "<button id='dd_"+root.id+"' class='btn btn-default dropdown-toggle icon-misc-filter' type='button' data-toggle='dropdown'>"+ - "</button>"+ - "<ul class='dropdown-menu' id='statusclick'>"+ - "<li id='active'>Active</li>"+ - "<li id='cancelled'>Cancelled</li>"+ - "<li id='terminated'>Terminated</li>"+ - "<li id='failed'>Failed</li>"+ - "</ul>"+ - "</div>"+ - "</div>"+ - "</span>"+ - "<span style='position: absolute; font-size: 12px; left:30px; top:10px' class='title-span'>" + root.blueprint_id + "</span>"+ - "<button id='dd_"+root.id+"' style='margin-top: 5px; position: absolute; right: 2px;' class='openmodal btn btn-default dropdown-toggle icon-controls-gear' " + - "type='button' data-toggle='dropdown'>"+ - "</button>"+ - "</div></div></br>"+ - "<div style='padding-top:25px'><img src='app/ecdapp/images/ecomp-login-550x360.jpg' width='180' height='100'></div>"+ - "<div class='expandBtn'><span id='exp_"+root.id+"'><i class='icon-controls-add-maximize'></i></span></div><ul>"); - } else { - itemHtml = "<li class='child'>"+ - "<div style='padding-top:3px'><span class='label_node'>"+ - - "<span class='title-span'>" + root.blueprint_id + "</span>"+ - "<span class='icon-span ddIcon'>"+ - "<div class='dropdown dd_"+root.id+"'>"+ - "<div style='float: right; margin-top: -14px;'>"+ - "<button id='dd_"+root.id+"' class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown'><i class='icon-people-preview'></i>"+ - "<span id='dd_"+root.id+"'></span></button>"+ - "<ul class='dropdown-menu'>"+ - "<li><a tabindex='-1' href='javascript:void(0);'>Execution Id: " + root.id + "</a></li>"+ - "<li><a tabindex='-1' href='javascript:void(0);'>Health Check Status: </a></li>"+ - "<li><a tabindex='-1' href='javascript:void(0);'>Please click here for more information </a></li>"+ - "</ul>"+ - "</div>"+ - "</div>"+ - "</span>"+ - "</span></div></br>"+ - "<div style='padding-top:35px'><img src='app/ecdapp/images/ecomp.png' width='180' height='100'></div></li>"; - items.push(itemHtml); - } - } // End the generate html code - - items.push('</ul></li>'); - var listElem = $("<ul/>", { - "class": "org", - "style": "float:right;", - html: items.join("") - }).appendTo(elem); - - var opts = { - chartElement: elem, - rowcolor: false - }; - //elem.html(''); - $(elem).find(".org").jOrgChart(opts); - listElem.remove(); - - setTimeout(function(){ - $('.dropdown .dropdown-toggle').on("click", function(e){ - var cls = '.'+ e.target.id; - var subcls = cls + ' a.test'; - if($(cls).hasClass('open')){ - $(cls).removeClass('open'); - $(subcls).next('ul').css({display: 'none'}); - } else{ - $(cls).addClass('open'); - } - }); - - $('.dropdown-submenu a.test').on("mouseover", function(e){ - console.log("hi"); - $('#'+e.target.id).next('ul').toggle(); - }); - - $('#statusclick li').click(function(event){ - statusSelectoin(event.target.id); - }) - - $('.openmodal').click(function(event){ - openModal(); - }) - - $(document).on('click','.expandBtn', function(event, data) { - event.stopImmediatePropagation() - var $this = $(this); - var $tr = $this.closest("tr"); - if ($tr.hasClass('contracted')) { - $(this).addClass('fa-minus').removeClass('fa-plus'); - $tr.removeClass('contracted').addClass('expanded'); - $tr.nextAll("tr").css('visibility', ''); - } else { - $(this).addClass('fa-plus').removeClass('fa-minus'); - $tr.removeClass('expanded').addClass('contracted'); - $tr.nextAll("tr").css('visibility', 'hidden'); - } - }); - - var selectedStatus = scope.status; - if(selectedStatus){ - $('#'+selectedStatus).addClass('active'); - } - - function openModal(){ - scope.modalCall()(); - } - - },0); - } - - drawOrgChart(data); - - }, - }; - }; -})();
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-style.css b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-style.css deleted file mode 100644 index 5a3e056..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-style.css +++ /dev/null @@ -1,132 +0,0 @@ -/* Basic styling */ - -::-webkit-scrollbar -{ - width: 12px; /* for vertical scrollbars */ - height: 7px; /* for horizontal scrollbars */ -} - -::-webkit-scrollbar-track -{ - background: rgba(0, 0, 0, 0.1); -} - -::-webkit-scrollbar-thumb -{ - background: rgba(0, 0, 0, 0.5); -} - -.orgChart .label_node{ - padding-bottom: 5px; -} - -.orgChart .icon-span{ - float:left;width:25px; - padding-top: 3px; -} -.orgChart .title-span{ - width:110px;float:left; font-size:14px; - padding-top: 3px; -} - -/* Draw the lines */ -.jOrgChart{ - position: relative; - /* left: 245px; */ - width:100%; - min-width: 100%; - overflow-x: auto; - -} -.jOrgChart .line { - height : 20px; - width : 4px; -} - -.jOrgChart .down { - background-color : black; - margin : 0px auto; -} - -.jOrgChart .top { - border-top : 3px solid black; -} - -.jOrgChart button{ - min-width : 20px; - width : 20px; - height : 20px; - padding : 0; -} - -.jOrgChart .dropdown{ - display: inline-block; -} - -.jOrgChart .downloadIcon{ - position: relative; - left: 1px; - float:left; -} - -.jOrgChart .ddIcon{ - position: relative; - float: right; - top: 6px; -} - -.jOrgChart .left { - border-right : 2px solid black; -} - -.jOrgChart .right { - border-left : 2px solid black; -} - -/* node cell */ -.jOrgChart td { - text-align : center; - vertical-align : top; - padding : 0 !important; - border : none; - border-bottom : 1px solid white; -} - -/* The node */ -.jOrgChart .node { - background-color : #efefef; - display : inline-block; - width : 180px; - height : 200px; - z-index : 10; - margin : 0 2px; -} - -.expandBtn { - background-color: #efefef; - padding-top:9px; -} - -/* jQuery drag 'n drop */ - -.drag-active { - border-style : dotted !important; -} - -.drop-hover { - border-style : solid !important; - border-color : #E05E00 !important; -} - -#statusclick{ - padding: 0 !important -} - -#statusclick li { - padding :5px; -} - -#statusclick li.active{ - background: #337ab7; - color: white; -}
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree_view.html deleted file mode 100644 index d5364e8..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree_view.html +++ /dev/null @@ -1,24 +0,0 @@ -<!-- Included bootstrap files at a page level to avoid issues with DS2 library --> -<script src="app/ecdapp/external/bootstrap.min.js"></script> -<link rel="stylesheet" href="app/ecdapp/external/bootstrap.min.css"/> - -<div id="page-content"> - - <org-chart data=orgChartData status="status" showOrgTable="showOrgTable" get-call="ecdapp.loadTable" modal-call="ecdapp.showEcompCInstancesModalPopup"> - </org-chart> - <div ng-show="ecdapp.isDataLoading"> - <div class="text-center" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - <div ng-hide="ecdapp.isDataLoading"> - <div ng-if="orgChartData.length == 1" class="col-xs-12 text-center" style="position:relative;"> - <b>No components found</b> - </div> - </div> - <div ng-show="ecdapp.isRequestFailed"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - -</div> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-controllers.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-controllers.js index fceab0e..b474348 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-controllers.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-controllers.js @@ -1,1037 +1,1329 @@ appDS2.controller('inventoryBlueprintTableController', function( - $rootScope, $scope, $log, $modal, modalService, InventoryBlueprintService, InventoryDeploymentService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - // models for controls on screen - $scope.ecdapp.tableData = []; - $scope.ecdapp.currentPageNum = 1; - $scope.ecdapp.viewPerPage = 10; - // other - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; - // sorting - $scope.ecdapp.sortBy = null; - // searching - $scope.ecdapp.searchBy = null; - - $scope.ecdapp.trackBpRowIndex = function(indx) { - $scope.ecdapp.tableData[indx].expanded = !$scope.ecdapp.tableData[indx].expanded; - }; - - $scope.ecdapp.updateTable = function() { - $scope.ecdapp.isSrvcDataLoading = true; - var srvcTypIds = []; - var srvcIds = []; - var bpDepls =[]; - var cloneGrid = $scope.ecdapp.tableData; - angular.forEach($scope.ecdapp.tableData, function(item, index) { - angular.forEach(item, function(value, key) { - if (key === "typeId") { - srvcTypIds.push(value); - } - }); - }); - - InventoryBlueprintService.getDeploymentForBp(srvcTypIds) - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryBlueprintController.updateTable failed: " + jsonObj.error); - } else { - bpDepls = jsonObj; - for (var typIndx = 0; typIndx < bpDepls.length; typIndx++) { - srvcIds.push(bpDepls[typIndx].serviceRefList); - } - angular.forEach(cloneGrid, function(item, index) { - item.deployments = srvcIds[index]; - item.expanded = false; - }); - $scope.ecdapp.tableData = cloneGrid; - } - $scope.ecdapp.isSrvcDataLoading = false; - }, function(error) { - $log.error("inventoryBlueprintController.updateTable failed: " + error); - bpDepls = []; - $scope.ecdapp.isSrvcDataLoading = false; - }); - - } - - $scope.ecdapp.JSONToCSVConverter = function(blueprint) - { - var array = typeof blueprint != 'object' ? JSON.parse(blueprint) : blueprint; - var str = ''; - for (var i = 0; i < array.length; i++) { - var line = ''; - - for (var index in array[i]) { - line += array[i][index] + ','; + $rootScope, $scope, $log, $modal, modalService, ControllerService, $interval, $routeParams, + InventoryBlueprintService, InventoryDeploymentService, localStorageService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + var stop; + + // this object holds all app data and functions + $scope.ecdapp = {}; + // models for controls on screen + $scope.ecdapp.tableData = []; + $scope.ecdapp.currentPage = 1; + $scope.ecdapp.viewPerPage = 10; + // other + $scope.ecdapp.errMsg = null; + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.filterByUser = true; + // sorting + $scope.ecdapp.sortBy = null; + + // searching + $scope.ecdapp.searchBy = $routeParams.bpId; + if ($scope.ecdapp.searchBy == undefined) { + $scope.ecdapp.searchBy = "owner:" + $scope.userId + ";"; + } else { + if ($scope.ecdapp.searchBy.includes("owner")) { + if ($scope.ecdapp.searchBy.split(":")[1] === "group") { + $scope.ecdapp.filterByUser = false; + $scope.ecdapp.searchBy = undefined; + } + } + } + + $scope.ecdapp.searchString; + $scope.ecdapp.availableTenants = JSON.parse(localStorageService.get('tenants')); + $scope.ecdapp.isInternal = localStorageService.get('internal'); + if ($scope.ecdapp.isInternal) { + $scope.ecdapp.components = JSON.parse(localStorageService.get('appComponents')); + $scope.ecdapp.apps = JSON.parse(localStorageService.get('apps')); + $scope.ecdapp.selectedApp; + $scope.ecdapp.selectedComp; + $scope.ecdapp.availableComp = JSON.parse(localStorageService.get('components')); + } + $scope.ecdapp.selectedBp; + $scope.ecdapp.availableBp = JSON.parse(localStorageService.get('bpNames')); + + $scope.ecdapp.selectedOwner; + + $scope.ecdapp.showingMoreFilters = false; + + $scope.ecdapp.toggleMoreFilters = function() { + $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters; + }; + + $scope.ecdapp.trackBpRowIndex = function(indx) { + $scope.ecdapp.tableData[indx].expanded = !$scope.ecdapp.tableData[indx].expanded; + }; + + $scope.ecdapp.updateTable = function() { + $scope.ecdapp.isSrvcDataLoading = true; + var srvcTypIds = []; + var srvcIds = []; + var bpDepls =[]; + var cloneGrid = $scope.ecdapp.tableData; + angular.forEach($scope.ecdapp.tableData, function(item, index) { + angular.forEach(item, function(value, key) { + if (key === "typeId") { + srvcTypIds.push(value); + } + }); + }); + + InventoryBlueprintService.getDeploymentForBp(srvcTypIds) + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryBlueprintController.updateTable failed: " + jsonObj.error); + } else { + bpDepls = jsonObj; + for (var typIndx = 0; typIndx < bpDepls.length; typIndx++) { + srvcIds.push(bpDepls[typIndx].serviceRefList); + } + angular.forEach(cloneGrid, function(item, index) { + item.deployments = srvcIds[index]; + item.expanded = false; + }); + $scope.ecdapp.tableData = cloneGrid; + } + $scope.ecdapp.isSrvcDataLoading = false; + }, function(error) { + $log.error("inventoryBlueprintController.updateTable failed: " + error); + bpDepls = []; + $scope.ecdapp.isSrvcDataLoading = false; + }); + } + + $scope.ecdapp.JSONToCSVConverter = function(blueprint) { + var array = typeof blueprint != 'object' ? JSON.parse(blueprint) : blueprint; + var str = ''; + for (var i = 0; i < array.length; i++) { + var line = ''; + for (var index in array[i]) { + line += array[i][index] + ','; + } + line.slice(0, line.Length - 1); + str += line + '\r\n'; + } + + var uri = 'data:text/csv;charset=utf-8,' + escape(str); + var fileName = 'exported'; + + var link = document.createElement("a"); + link.href= uri; + + link.style = "visibility:hidden"; + link.download = fileName + ".csv"; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + $scope.ecdapp.createcsv = function(blueprint) { + var bpArr =[]; + bpArr.push(blueprint); + $scope.ecdapp.JSONToCSVConverter(bpArr); + }; + + $scope.ecdapp.exportJson = function(blueprint) { + var bpExportObj = {}; + bpExportObj.application = blueprint.application; + bpExportObj.component = blueprint.component; + bpExportObj.typeName = blueprint.typeName; + bpExportObj.typeVersion = blueprint.typeVersion; + bpExportObj.blueprintTemplate = blueprint.blueprintTemplate; + + var bpStr = JSON.stringify(bpExportObj); + var uri = 'data:text/json;charset=utf-8,' + escape(bpStr); + var fileName = blueprint.application + '_' + blueprint.component + + '_' + blueprint.typeName + '_' + blueprint.typeVersion; + + var link = document.createElement("a"); + link.href= uri; + + link.style = "visibility:hidden"; + link.download = fileName + ".json"; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + $scope.ecdapp.getTenants = function() { + ControllerService.getTenants() + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("blueprintController.getTenants failed: " + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + var tenants = []; + for (var tenIndx = 0; tenIndx < jsonObj.items.length; tenIndx++) { + tenants.push(jsonObj.items[tenIndx].name); } + localStorageService.set('tenants', JSON.stringify(tenants)); + $scope.ecdapp.availableTenants = JSON.parse(localStorageService.get('tenants')); + } + }, function(error) { + $log.error("blueprintController.getTenants failed: " + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + }); + }; + + $scope.ecdapp.getOwnersList = function() { + $scope.ecdapp.bpOwners = JSON.parse(localStorageService.get('bpOwners')); + if ($scope.ecdapp.bpOwners == null) { + InventoryBlueprintService.getOwnersList().then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("bpCtlr.getOwnersList failed: " + + jsonObj.error); + $scope.ecdapp.bpOwners = []; + } else { + $scope.ecdapp.bpOwners = jsonObj; + localStorageService.set('bpOwners', JSON.stringify(jsonObj)); + } + }, + function(error) { + $log.error("inventoryDeploymentController.getOwnersList failed: " + + error); + $scope.ecdapp.bpOwners = []; + }); + } + }; + + $scope.ecdapp.getBlueprintsList = function() { + $scope.ecdapp.availableBp = JSON.parse(localStorageService.get('bpNames')); + if ($scope.ecdapp.availableBp == null) { + InventoryBlueprintService.getBlueprintsList().then( + function(jsonObj) { + if (jsonObj.error) { + $log.error("execViewCtlr.getBlueprintsList failed: " + + jsonObj.error); + $scope.ecdapp.availableBp = []; + } else { + $scope.ecdapp.availableBp = jsonObj.items; + localStorageService.set('bpNames', JSON.stringify(jsonObj.items)); + //$scope.ecdapp.availableBp = JSON.parse(localStorageService.get('bpNames')); + } + }, + function(error) { + $log.error("inventoryDeploymentController.getDeploymentList failed: " + + error); + $scope.ecdapp.availableBp = []; + }); + } + }; + + /** + * Get the components from database + * + */ + $scope.ecdapp.getAppComponents = function() { + InventoryBlueprintService.getComponents() + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryBlueprintController.loadComponents failed: " + jsonObj.error); + $scope.ecdapp.components = []; + } else { + if (debug) + $log.debug("inventoryBlueprintController.loadComponents succeeded, size " + jsonObj.data.length); + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.components = jsonObj; + if (Array.isArray($scope.ecdapp.components) ) { + angular.forEach($scope.ecdapp.components, function(item, index) { + angular.forEach(item, function(value, key) { + if (key === "app") { + $scope.ecdapp.apps.push(value); + } else { + angular.forEach(value, function(item, index) { + angular.forEach(item, function(value, key) { + if (key === "cname") { + if (!$scope.ecdapp.availableComp.includes(value)) { + $scope.ecdapp.availableComp.push(value); + } + } + }); + }); + } + }); + }); + } + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $log.error("inventoryBlueprintController.loadComponents failed: " + error); + $scope.ecdapp.components = []; + }); + }; + + /** + * Loads the table. Interprets the remote controller's response and copies + * to scope variables. The response is either list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.loadTable = function(sortBy, searchBy) { + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.sortBy = sortBy; + //$scope.ecdapp.searchBy = searchBy; + InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy) + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + //if (debug) + //$log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.tableData = jsonObj.items; + //$scope.ecdapp.updateTable(); + $scope.ecdapp.getBlueprintsList(); + $scope.ecdapp.getOwnersList(); + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $log.error("inventoryBlueprintController.loadTable failed: " + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + var loc = location.pathname; + var loc1 = loc.replace("/", ""); + var loc2 = loc1.replace("/ecd", "/login.htm"); + alert("Session expired - Sign in again"); + location.replace("/"+loc2); + }); + }; + + stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 300000, 100, false); + + $scope.ecdapp.stopLoading = function() { + if (angular.isDefined(stop)) { + $interval.cancel(stop); + stop = undefined; + } + }; + + /** + * Loads the table. Interprets the remote controller's response and copies + * to scope variables. The response is either list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.sortTable = function(sortBy) { + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.sortBy = sortBy; + InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage, sortBy, $scope.ecdapp.searchBy) + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + if (debug) + $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.tableData = jsonObj.items; + //$scope.ecdapp.updateTable(); + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $log.error("inventoryBlueprintController.loadTable failed: " + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + }); + }; - line.slice(0, line.Length - 1); + $scope.ecdapp.filterBySvc = function() { + if ( typeof $scope.ecdapp.searchString != "undefined" && + $scope.ecdapp.searchString != '') { + if ($scope.ecdapp.searchString.includes("serviceRef:") || + $scope.ecdapp.searchString.includes("app:") || + $scope.ecdapp.searchString.includes("comp:")) { + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy = $scope.ecdapp.searchString + ";" + "owner:" + $scope.userId + ";" + ";"; + } else { + $scope.ecdapp.searchBy = $scope.ecdapp.searchString; + } + } else { + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy = 'contains:' + $scope.ecdapp.searchString + ";" + "owner:" + $scope.userId + ";"; + } else { + $scope.ecdapp.searchBy = 'contains:' + $scope.ecdapp.searchString; + } + } + $scope.ecdapp.searchTable(); + } + }; - str += line + '\r\n'; + $scope.ecdapp.extendedfilterSrch = function() { + if ( typeof $scope.ecdapp.selectedBp != "undefined" && + $scope.ecdapp.selectedBp != '') { + var svcFilterStr = 'serviceRef:' + $scope.ecdapp.selectedBp.toString(); + $scope.ecdapp.searchBy = svcFilterStr + ';' + if ( typeof $scope.ecdapp.selectedApp != "undefined" && + $scope.ecdapp.selectedApp != '') { + var appFilterStr = 'app:' + $scope.ecdapp.selectedApp.toString(); + $scope.ecdapp.searchBy += appFilterStr + ';' + } + if ( typeof $scope.ecdapp.selectedComp != "undefined" && + $scope.ecdapp.selectedComp != '') { + var compFilterStr = 'comp:' + $scope.ecdapp.selectedComp.toString(); + $scope.ecdapp.searchBy += compFilterStr + ';' } + if ( typeof $scope.ecdapp.selectedOwner != "undefined" && + $scope.ecdapp.selectedOwner != '') { + var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString(); + $scope.ecdapp.searchBy += ownerFilterStr + ';' + } + } else { + if ( typeof $scope.ecdapp.selectedApp != "undefined" && + $scope.ecdapp.selectedApp != '') { + var appFilterStr = 'app:' + $scope.ecdapp.selectedApp.toString(); + $scope.ecdapp.searchBy = appFilterStr + ';' + if ( typeof $scope.ecdapp.selectedComp != "undefined" && + $scope.ecdapp.selectedComp != '' ) { + var compFilterStr = 'comp:' + $scope.ecdapp.selectedComp.toString(); + $scope.ecdapp.searchBy += compFilterStr + ';' + } + if ( typeof $scope.ecdapp.selectedOwner != "undefined" && + $scope.ecdapp.selectedOwner != '') { + var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString(); + $scope.ecdapp.searchBy += ownerFilterStr + ';' + } + } else { + if ( typeof $scope.ecdapp.selectedComp != "undefined" && + $scope.ecdapp.selectedComp != '') { + var compFilterStr = 'comp:' + $scope.ecdapp.selectedComp.toString(); + $scope.ecdapp.searchBy = compFilterStr + ';' + if ( typeof $scope.ecdapp.selectedOwner != "undefined" && + $scope.ecdapp.selectedOwner != '') { + var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString(); + $scope.ecdapp.searchBy += ownerFilterStr + ';' + } + } else { + if ( typeof $scope.ecdapp.selectedOwner != "undefined" && + $scope.ecdapp.selectedOwner != '') { + var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString(); + $scope.ecdapp.searchBy = ownerFilterStr + ';' + } + } + + } + } + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";"; + } + $scope.ecdapp.searchString = $scope.ecdapp.searchBy; + $scope.ecdapp.searchTable(); + }; + + /** + * Loads the table. Interprets the remote controller's response and copies + * to scope variables. The response is either list to be assigned to + * tableData, or an error to be shown. + */ + $scope.ecdapp.searchTable = function() { + $scope.ecdapp.isDataLoading = true; + $scope.ecdapp.showingMoreFilters = false; + if ($scope.ecdapp.currentPage != 1) { + $scope.ecdapp.currentPage = 1; + } else { + InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy) + .then(function(jsonObj) { + if (jsonObj.error) { + $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = jsonObj.error; + $scope.ecdapp.tableData = []; + } else { + if (debug) + $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); + $scope.ecdapp.isRequestFailed = false; + $scope.ecdapp.errMsg = null; + $scope.ecdapp.totalPages = jsonObj.totalPages; + $scope.ecdapp.tableData = jsonObj.items; + //$scope.ecdapp.updateTable(); + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $log.error("inventoryBlueprintController.loadTable failed: " + error); + $scope.ecdapp.isRequestFailed = true; + $scope.ecdapp.errMsg = error; + $scope.ecdapp.tableData = []; + $scope.ecdapp.isDataLoading = false; + var loc = location.pathname; + var loc1 = loc.replace("/", ""); + var loc2 = loc1.replace("/ecd", "/login.htm"); + alert("Session expired - Sign in again"); + location.replace("/"+loc2); + }); + } + }; + + $scope.ecdapp.resetFilters = function() { + $scope.ecdapp.selectedBp = ''; + $scope.ecdapp.selectedApp = ''; + $scope.ecdapp.selectedComp = ''; + $scope.ecdapp.selectedOwner = ''; + $scope.ecdapp.searchString = ''; + }; + + $scope.ecdapp.reloadTable = function() { + $scope.ecdapp.currentPage = 1; + if ($scope.ecdapp.filterByUser) { + $scope.ecdapp.searchBy = "owner:" + $scope.userId + ";"; + } else { + $scope.ecdapp.searchBy = ''; + } + $scope.ecdapp.searchString = ''; + $scope.ecdapp.resetFilters(); + $scope.ecdapp.loadTable(); + }; + + $scope.ecdapp.toggleUserFilt = function() { + $scope.ecdapp.reloadTable(); + /* + if ($scope.ecdapp.filterByUser === false) { + $scope.ecdapp.searchString = ''; + } + */ + } + /** + * Invoked at first page load AND when + * user clicks on the B2B pagination control. + */ + $scope.pageChangeHandler = function(page) { + $scope.ecdapp.currentPage = page; + $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy); + } + + /** + * Shows a modal pop-up to update a blueprint. + * Passes data in via an object named "message". + * On success, updates the table. + */ + $scope.ecdapp.updateBlueprintModalPopup = function(blueprint) { + $scope.ecdapp.editBlueprint = null; + var modalInstance = $modal.open({ + templateUrl : 'inventory_blueprint_update_popup.html', + controller : 'inventoryBlueprintUpdateCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + blueprint : blueprint + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + + if (debug) + $log.debug('updateBlueprintModalPopup: response: ' + JSON.stringify(response)); + if (response == null) { + if (debug) + $log.debug('user closed dialog'); + } + else { + if (response.error != null) { + $log.error('updateBlueprintModalPopup failed: ' + response.error); + alert('Failed to update blueprint:\n' + response.error); + } + else { + // success, get the updated list. + $scope.ecdapp.loadTable() + } + } + }); + }; + + /** + * Shows a modal pop-up with blueprint content. + * Passes data in via an object named "message". + */ + $scope.ecdapp.viewBlueprintModalPopup = function(blueprint) { + $scope.ecdapp.editBlueprint = null; + var modalInstance = $modal.open({ + templateUrl : 'inventory_blueprint_view_popup.html', + controller : 'inventoryBlueprintViewCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + blueprint : blueprint + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + // No response. + }); + }; - var uri = 'data:text/csv;charset=utf-8,' + escape(str); - var fileName = 'exported'; - - var link = document.createElement("a"); - link.href= uri; - - link.style = "visibility:hidden"; - link.download = fileName + ".csv"; - - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - }; - - $scope.ecdapp.createcsv = function(blueprint) - { - var bpArr =[]; - bpArr.push(blueprint); - $scope.ecdapp.JSONToCSVConverter(bpArr); - }; - - $scope.ecdapp.exportJson = function(blueprint) - { - var bpExportObj = {}; - bpExportObj.application = blueprint.application; - bpExportObj.component = blueprint.component; - bpExportObj.typeName = blueprint.typeName; - bpExportObj.typeVersion = blueprint.typeVersion; - bpExportObj.blueprintTemplate = blueprint.blueprintTemplate; - - var bpStr = JSON.stringify(bpExportObj); - var uri = 'data:text/json;charset=utf-8,' + escape(bpStr); - var fileName = blueprint.application + '_' + blueprint.component + - '_' + blueprint.typeName + '_' + blueprint.typeVersion; - - var link = document.createElement("a"); - link.href= uri; - - link.style = "visibility:hidden"; - link.download = fileName + ".json"; - - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - }; - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.loadTable = function(sortBy, searchBy) { - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.sortBy = sortBy; - $scope.ecdapp.searchBy = searchBy; - InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage, sortBy, searchBy) - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - //if (debug) - //$log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - $scope.ecdapp.updateTable(); - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $log.error("inventoryBlueprintController.loadTable failed: " + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - }; - - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.sortTable = function(sortBy) { - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.sortBy = sortBy; - InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage, sortBy, $scope.ecdapp.searchBy) - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - if (debug) - $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - $scope.ecdapp.updateTable(); - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $log.error("inventoryBlueprintController.loadTable failed: " + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - }; - - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.searchTable = function(searchBy) { - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.searchBy = searchBy; - InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, searchBy) - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - if (debug) - $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - $scope.ecdapp.updateTable(); - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $log.error("inventoryBlueprintController.loadTable failed: " + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - }; - - /** - * Invoked at first page load AND when - * user clicks on the B2B pagination control. - */ - $scope.pageChangeHandler = function(page) { - // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); - $scope.ecdapp.currentPageNum = page; - $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy); - } - - /** - * Shows a modal pop-up to update a blueprint. - * Passes data in via an object named "message". - * On success, updates the table. - */ - $scope.ecdapp.updateBlueprintModalPopup = function(blueprint) { - $scope.ecdapp.editBlueprint = null; - var modalInstance = $modal.open({ - templateUrl : 'inventory_blueprint_update_popup.html', - controller : 'inventoryBlueprintUpdateCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - blueprint : blueprint - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - - if (debug) - $log.debug('updateBlueprintModalPopup: response: ' + JSON.stringify(response)); - if (response == null) { - if (debug) - $log.debug('user closed dialog'); - } - else { - if (response.error != null) { - $log.error('updateBlueprintModalPopup failed: ' + response.error); - alert('Failed to update blueprint:\n' + response.error); - } - else { - // success, get the updated list. - $scope.ecdapp.loadTable() - } - } - }); - }; - - /** - * Shows a modal pop-up with blueprint content. - * Passes data in via an object named "message". - */ - $scope.ecdapp.viewBlueprintModalPopup = function(blueprint) { - $scope.ecdapp.editBlueprint = null; - var modalInstance = $modal.open({ - templateUrl : 'inventory_blueprint_view_popup.html', - controller : 'inventoryBlueprintViewCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - blueprint : blueprint - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - // No response. - }); - }; - - /** - * Shows a modal pop-up to upload a blueprint. - * Passes data in via an object named "message". - * On success, updates the table. - */ - $scope.ecdapp.uploadBlueprintModalPopup = function() { - $scope.ecdapp.editBlueprint = null; - var modalInstance = $modal.open({ - templateUrl : 'inventory_blueprint_upload_popup.html', - controller : 'inventoryBlueprintUploadCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - blueprint : $scope.ecdapp.editBlueprint, - blueprintList : $scope.ecdapp.tableData, - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - if (debug) - $log.debug('uploadBlueprintModalPopup: response: ' + JSON.stringify(response)); - if (response == null) { - if (debug) - $log.debug('user closed dialog'); - } - else { - if (response.error != null) { - $log.error('uploadBlueprintModalPopup failed: ' + response.error); - alert('Failed to upload blueprint:\n' + response.error); - } - else { - // success, get the updated list. - $scope.ecdapp.loadTable() - } - } - }); - }; - - /** - * Shows a modal pop-up to create a deployment from a blueprint. - * Passes data in via an object named "message". - */ - $scope.ecdapp.deployBlueprintModalPopup = function(blueprint) { - var modalInstance = $modal.open({ - templateUrl : 'inventory_blueprint_deploy_popup.html', - controller : 'inventoryBlueprintDeployCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - blueprint : blueprint, - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - if (debug) - $log.debug('deployBlueprintModalPopup: response: ' + JSON.stringify(response)); - if (response == null) { - if (debug) - $log.debug('user closed dialog'); - } - else { - if (response.error != null) { - $log.error('deployBlueprintModalPopup failed: ' + response.error); - alert('Failed to deploy blueprint:\n' + response.error); - // No need to update THIS table. - // Must switch to deployments page to see result? Awkward. - } - } - }); - }; - - /** - * Shows a modal pop-up to confirm deletion. - * On successful completion, updates the table. - */ - $scope.ecdapp.deleteBlueprintModalPopup = function(blueprint) { - modalService.popupConfirmWin("Confirm", "Delete blueprint with name '" - + blueprint.typeName + "'?", function() { - InventoryBlueprintService.deleteBlueprint(blueprint.typeId).then( - function(response) { - if (debug) - $log.debug('deleteBlueprintModalPopup: response: ' + JSON.stringify(response)); - if (response && response.error) { - // $log.error('deleteBlueprint failed: ' + response.error); - alert('Failed to delete blueprint:\n' + response.error); - } - else { - // No response body on success. - $scope.ecdapp.loadTable(); - } - }, - function(error) { - $log.error('InventoryBlueprintService.deleteBlueprint failed: ' + error); - alert('Service failed to delete blueprint:\n' + error); - }); - }) - }; + /** + * Shows a modal pop-up to upload a blueprint. + * Passes data in via an object named "message". + * On success, updates the table. + */ + $scope.ecdapp.uploadBlueprintModalPopup = function() { + $scope.ecdapp.editBlueprint = null; + var modalInstance = $modal.open({ + templateUrl : 'inventory_blueprint_upload_popup.html', + controller : 'inventoryBlueprintUploadCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + apps : $scope.ecdapp.apps, + appComps: $scope.ecdapp.components + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + if (debug) + $log.debug('uploadBlueprintModalPopup: response: ' + JSON.stringify(response)); + if (response == null) { + if (debug) + $log.debug('user closed dialog'); + } + else { + if (response.error != null) { + $log.error('uploadBlueprintModalPopup failed: ' + response.error); + alert('Failed to upload blueprint:\n' + response.error); + } + else { + // success, get the updated list. + $scope.ecdapp.loadTable() + } + } + }); + }; + + /** + * Shows a modal pop-up to create a deployment from a blueprint. + * Passes data in via an object named "message". + */ + $scope.ecdapp.deployBlueprintModalPopup = function(blueprint) { + var modalInstance = $modal.open({ + templateUrl : 'inventory_blueprint_deploy_popup.html', + controller : 'inventoryBlueprintDeployCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + blueprint : blueprint, + tenantList : $scope.ecdapp.availableTenants + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + if (debug) + $log.debug('deployBlueprintModalPopup: response: ' + JSON.stringify(response)); + if (response == null) { + if (debug) + $log.debug('user closed dialog'); + } + else { + if (response.error != null) { + $log.error('deployBlueprintModalPopup failed: ' + response.error); + alert('Failed to deploy blueprint:\n' + response.error); + // No need to update THIS table. + // Must switch to deployments page to see result? Awkward. + } + } + }); + }; + /** + * Shows a modal pop-up to confirm deletion. + * On successful completion, updates the table. + */ + $scope.ecdapp.deleteBlueprintModalPopup = function(blueprint) { + modalService.popupConfirmWin("Confirm", "Delete blueprint with name '" + + blueprint.typeName + "'?", function() { + InventoryBlueprintService.deleteBlueprint(blueprint.typeId).then( + function(response) { + if (debug) + $log.debug('deleteBlueprintModalPopup: response: ' + JSON.stringify(response)); + if (response && response.error) { + // $log.error('deleteBlueprint failed: ' + response.error); + alert('Failed to delete blueprint:\n' + response.error); + } + else { + // No response body on success. + $scope.ecdapp.loadTable(); + } + }, + function(error) { + $log.error('InventoryBlueprintService.deleteBlueprint failed: ' + error); + alert('Service failed to delete blueprint:\n' + error); + }); + }) + }; + + $scope.ecdapp.getTenants(); + + $scope.$on('$destroy', function() { + // Make sure that the interval is destroyed too + $scope.ecdapp.stopLoading(); + }); + }); /*************************************************************************/ appDS2.controller('inventoryBlueprintUpdateCtrl', function( - $scope, $log, $modalInstance, message, InventoryBlueprintService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Update Blueprint'; - $scope.ecdapp.updateInProgress = false; - // Create a ServiceTypeRequest object for edit - $scope.ecdapp.serviceType = angular.copy(message.blueprint); - - /** - * Validates content of user-editable fields. - * Returns null if all is well, - * a descriptive error message otherwise. - */ - $scope.ecdapp.validateRequest = function(serviceType) { - if (serviceType == null) - return 'No data found.\nPlease enter some values.'; - if (serviceType.blueprintTemplate == null || serviceType.blueprintTemplate.trim() == '') - return 'Blueprint Template is required.\nPlease enter a value.'; - let blueprintTemplate = {}; - try { - blueprintTemplate = YAML.parse(serviceType.blueprintTemplate); - } - catch (ex) { - return ('Blueprint template is not in YAML format:\n' + ex); - } - return null; - } - - $scope.ecdapp.updateBlueprint = function(serviceType) { - $scope.ecdapp.updateInProgress = true; - if (debug) - $log.debug('updateBlueprint: serviceType is ' + JSON.stringify($scope.ecdapp.serviceType)); - var validateMsg = $scope.ecdapp.validateRequest(serviceType); - if (validateMsg != null) { - alert('Invalid Request:\n' + validateMsg); - return; - } - - InventoryBlueprintService.updateBlueprint(serviceType) - .then(function(response) { - if (debug) - $log.debug('inventoryBlueprintUpdateCtrl.updateBlueprint: ' + JSON.stringify(response)); - if (response && response.error) { - $log.error('InventoryBlueprintService.updateBlueprint failed: ' + response.error); - alert('Failed to update blueprint:\n' + response.error); - } - else { - // Delete service returns null on success. - $modalInstance.close("success"); - } - $scope.ecdapp.updateInProgress = false; - }, - function(error) { - $log.error('InventoryBlueprintService.updateBlueprint failed: ' + error); - $scope.ecdapp.updateInProgress = false; - alert('Service failed to update blueprint:\n' + error); - }); - - }; + $scope, $log, $modalInstance, message, InventoryBlueprintService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'Update Blueprint'; + $scope.ecdapp.updateInProgress = false; + // Create a ServiceTypeRequest object for edit + $scope.ecdapp.serviceTypeRequest = angular.copy(message.blueprint); + + $scope.ecdapp.serviceType = + { + asdcResourceId : '', + asdcServiceId : '', + asdcServiceURL : '', + blueprintTemplate : '', + owner : $scope.ecdapp.serviceTypeRequest.owner, + serviceIds : [], + serviceLocations : [], + typeName : $scope.ecdapp.serviceTypeRequest.typeName, + typeVersion : $scope.ecdapp.serviceTypeRequest.typeVersion, + vnfTypes : [], + application: $scope.ecdapp.serviceTypeRequest.application, + component: $scope.ecdapp.serviceTypeRequest.component + }; + + // Fetch the blueprint + $scope.ecdapp.isDataLoading = true; + InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) { + if (debug) + $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed'; + } + else { + $scope.ecdapp.serviceType.blueprintTemplate = jsonObj.blueprintTemplate; + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $scope.ecdapp.isDataLoading = false; + $log.error("blueprintViewCtrl failed: " + error); + }); + + /** + * Validates content of user-editable fields. + * Returns null if all is well, + * a descriptive error message otherwise. + */ + $scope.ecdapp.validateRequest = function(serviceType) { + if (serviceType == null) + return 'No data found.\nPlease enter some values.'; + if (serviceType.blueprintTemplate == null || serviceType.blueprintTemplate.trim() == '') + return 'Blueprint Template is required.\nPlease enter a value.'; + let blueprintTemplate = {}; + try { + blueprintTemplate = YAML.parse(serviceType.blueprintTemplate); + } + catch (ex) { + return ('Blueprint template is not in YAML format:\n' + ex); + } + return null; + } + + $scope.ecdapp.updateBlueprint = function(serviceType) { + $scope.ecdapp.updateInProgress = true; + if (debug) + $log.debug('updateBlueprint: serviceType is ' + JSON.stringify($scope.ecdapp.serviceType)); + var validateMsg = $scope.ecdapp.validateRequest(serviceType); + if (validateMsg != null) { + alert('Invalid Request:\n' + validateMsg); + return; + } + + InventoryBlueprintService.updateBlueprint(serviceType) + .then(function(response) { + if (debug) + $log.debug('inventoryBlueprintUpdateCtrl.updateBlueprint: ' + JSON.stringify(response)); + if (response && response.error) { + $log.error('InventoryBlueprintService.updateBlueprint failed: ' + response.error); + alert('Failed to update blueprint:\n' + response.error); + } + else { + $modalInstance.close("success"); + } + $scope.ecdapp.updateInProgress = false; + }, + function(error) { + $log.error('InventoryBlueprintService.updateBlueprint failed: ' + error); + $scope.ecdapp.updateInProgress = false; + alert('Service failed to update blueprint:\n' + error); + }); + + }; }); appDS2.controller('inventoryBlueprintUploadCtrl', function( - $scope, $log, $modalInstance, message, InventoryBlueprintService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Upload Blueprint'; - $scope.ecdapp.uploadInProgress = false; - $scope.ecdapp.serviceTypeRequest = - { - asdcResourceId : '', - asdcServiceId : '', - asdcServiceURL : '', - blueprintTemplate : '', - owner : $scope.userId, - serviceIds : '', - serviceLocations : '', - typeName : '', - typeVersion : '', - vnfTypes : '', - application: '', - component: '' - }; - $scope.ecdapp.writeRole = false; - $scope.ecdapp.newCompName = ""; - $scope.ecdapp.newCompDisplayName = ""; - $scope.ecdapp.newCompId = null; - $scope.ecdapp.enableAppForm = false; - $scope.ecdapp.apps = []; - $scope.ecdapp.comps = []; - $scope.ecdapp.validAppl = false; - $scope.ecdapp.validComp = false; - $scope.ecdapp.isImport = false; - - /** - * Handler for file-read event reads file, parses JSON, validates content. - */ - var importFileReader = new FileReader(); - importFileReader.onload = function(event) { - let jsonString = importFileReader.result; - if (debug) - $log.debug('fileReader.onload: read: ' + jsonString); - let ydict = {}; - try { - ydict = JSON.parse(jsonString); - } - catch (ex) { - alert('Failed to parse file as JSON:\n' + ex); - } - // Process the file - for (var ykey in ydict) { - let yval = ydict[ykey]; - if (debug) - $log.debug('importFileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); - - if (ykey === "application") { - $scope.ecdapp.serviceTypeRequest.application = yval; - $scope.ecdapp.validAppl = true; - } else if (ykey === "component") { - $scope.ecdapp.serviceTypeRequest.component = yval; - $scope.ecdapp.validComp = true; - } else if (ykey === "typeName") { - $scope.ecdapp.serviceTypeRequest.typeName = yval; - } else if (ykey === "typeVersion") { - $scope.ecdapp.serviceTypeRequest.typeVersion = yval; - } else if (ykey === "blueprintTemplate") { - $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yval; - } - } - } - - $scope.ecdapp.handleImportCb = function($event) { - var checkbox = $event.target; - var action = (checkbox.checked ? 'import' : 'regular'); - if (action === 'import') { - $scope.ecdapp.serviceTypeRequest.application = ''; - $scope.ecdapp.serviceTypeRequest.component = ''; - $scope.ecdapp.isImport = true; - } - if (action === 'regular') { - $scope.ecdapp.serviceTypeRequest.application = 'Select Application'; - $scope.ecdapp.serviceTypeRequest.component = 'Select Component'; - $scope.ecdapp.isImport = false; - } - } - // Handler for file-select event - $scope.ecdapp.handleImportFile = function() { - if (debug) - $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name); - importFileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel); - }; - - /** - * Get the components from database - * - */ - InventoryBlueprintService.getComponents() - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryBlueprintController.loadComponents failed: " + jsonObj.error); - $scope.ecdapp.components = []; - } else { - if (debug) - $log.debug("inventoryBlueprintController.loadComponents succeeded, size " + jsonObj.data.length); - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.components = jsonObj; - if (Array.isArray($scope.ecdapp.components) ) { - angular.forEach($scope.ecdapp.components, function(item, index) { - angular.forEach(item, function(value, key) { - if (key === "app") { - $scope.ecdapp.apps.push(value); - } - }); - }); - } - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $log.error("inventoryBlueprintController.loadComponents failed: " + error); - $scope.ecdapp.components = []; - }); - - //$scope.ecdapp.components = [{"ECOMPC":[{"compId":1,"cname":"controller","dname":"CONTROLLER"},{"compId":2,"cname":"mso","dname":"MSO"},{"compId":3,"cname":"appc","dname":"APP-C"},{"compId":4,"cname":"clamp","dname":"CLAMP"},{"compId":5,"cname":"ecompscheduler","dname":"ECOMP SCHEDULER"},{"compId":6,"cname":"policy","dname":"POLICY"},{"compId":7,"cname":"eipam","dname":"EIPAM"},{"compId":181,"cname":"pdasms","dname":"PDAS-MS"},{"cname":"true"}]}, - // {"DCAE": [{"compId":8,"cname":"dcae","dname":"DCAE"}]}]; - $scope.ecdapp.selectAppComp = function(appName) { - if(appName === "Select Application"){ - $scope.ecdapp.validAppl = false; - } else { - $scope.ecdapp.validAppl = true; - for (var appIndx = 0; appIndx < $scope.ecdapp.components.length; appIndx++) { - if ($scope.ecdapp.components[appIndx].app === appName) { - $scope.ecdapp.comps = $scope.ecdapp.components[appIndx].comps; - break; - } - } - } - } - $scope.ecdapp.validateComp = function(appName) { - if($scope.ecdapp.serviceTypeRequest.component === "Select Component"){ - $scope.ecdapp.validComp = false; - } else { - $scope.ecdapp.validComp = true; - } - } - var fileReader = new FileReader(); - fileReader.onload = function(event) { - let yamlString = fileReader.result; - $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yamlString; - } - $scope.ecdapp.enableAddApp = function() { - if ($scope.ecdapp.enableAppForm) { - $scope.ecdapp.enableAppForm = false; - } else { - $scope.ecdapp.enableAppForm = true; - } - } - $scope.ecdapp.addApplication = function(appName, compId, compName, compDisplayName) { - // save new application to database, reload components list - if (compName.trim().length < 1 || compDisplayName.trim().length < 1) { - alert("Must enter value for Component name and display name"); - return; + $scope, $log, $modalInstance, message, InventoryBlueprintService, localStorageService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'Upload Blueprint'; + $scope.ecdapp.uploadInProgress = false; + + $scope.ecdapp.serviceTypeRequest = + { + asdcResourceId : '', + asdcServiceId : '', + asdcServiceURL : '', + blueprintTemplate : '', + owner : $scope.userId, + serviceIds : '', + serviceLocations : '', + typeName : '', + typeVersion : '', + vnfTypes : '', + application: '', + component: '' + }; + + if (!$scope.ecdapp.isInternal) { + $scope.ecdapp.serviceTypeRequest.application = 'DCAE'; + $scope.ecdapp.serviceTypeRequest.component = 'dcae'; + } + $scope.ecdapp.writeRole = false; + $scope.ecdapp.isImport = false; + + /** + * Handler for file-read event reads file, parses JSON, validates content. + */ + var importFileReader = new FileReader(); + importFileReader.onload = function(event) { + let jsonString = importFileReader.result; + if (debug) + $log.debug('fileReader.onload: read: ' + jsonString); + let ydict = {}; + try { + ydict = JSON.parse(jsonString); + } + catch (ex) { + alert('Failed to parse file as JSON:\n' + ex); + } + // Process the file + for (var ykey in ydict) { + let yval = ydict[ykey]; + if (debug) + $log.debug('importFileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); + + if (ykey === "application") { + $scope.ecdapp.serviceTypeRequest.application = yval; + $scope.ecdapp.validAppl = true; + } else if (ykey === "component") { + $scope.ecdapp.serviceTypeRequest.component = yval; + $scope.ecdapp.validComp = true; + } else if (ykey === "typeName") { + $scope.ecdapp.serviceTypeRequest.typeName = yval; + } else if (ykey === "typeVersion") { + $scope.ecdapp.serviceTypeRequest.typeVersion = yval; + } else if (ykey === "blueprintTemplate") { + $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yval; + } + } + } + + $scope.ecdapp.handleImportCb = function($event) { + var checkbox = $event.target; + var action = (checkbox.checked ? 'import' : 'regular'); + if (action === 'import' && $scope.ecdapp.isInternal) { + $scope.ecdapp.serviceTypeRequest.application = ''; + $scope.ecdapp.serviceTypeRequest.component = ''; + $scope.ecdapp.isImport = true; + } + if (action === 'regular' && $scope.ecdapp.isInternal) { + $scope.ecdapp.serviceTypeRequest.application = 'Select Application'; + $scope.ecdapp.serviceTypeRequest.component = 'Select Component'; + $scope.ecdapp.isImport = false; + } + } + // Handler for file-select event + $scope.ecdapp.handleImportFile = function() { + if (debug) + $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name); + importFileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel); + }; + + + //$scope.ecdapp.components = [{"ECOMPC":[{"compId":1,"cname":"controller","dname":"CONTROLLER"},{"compId":2,"cname":"mso","dname":"MSO"},{"compId":3,"cname":"appc","dname":"APP-C"},{"compId":4,"cname":"clamp","dname":"CLAMP"},{"compId":5,"cname":"ecompscheduler","dname":"ECOMP SCHEDULER"},{"compId":6,"cname":"policy","dname":"POLICY"},{"compId":7,"cname":"eipam","dname":"EIPAM"},{"compId":181,"cname":"pdasms","dname":"PDAS-MS"},{"cname":"true"}]}, + // {"DCAE": [{"compId":8,"cname":"dcae","dname":"DCAE"}]}]; + $scope.ecdapp.selectAppComp = function(appName) { + if(appName === "Select Application") { + $scope.ecdapp.validAppl = false; + } else { + $scope.ecdapp.comps = []; + $scope.ecdapp.serviceTypeRequest.component = ""; + $scope.ecdapp.validAppl = true; + for (var appIndx = 0; appIndx < $scope.ecdapp.components.length; appIndx++) { + if ($scope.ecdapp.components[appIndx].app === appName) { + $scope.ecdapp.comps = $scope.ecdapp.components[appIndx].comps; + break; } - //console.log("Saving " + applicationName + " to components list"); - InventoryBlueprintService.insertComponent(compName, compDisplayName.toUpperCase()).then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryBlueprintController.loadComponents failed: " + jsonObj.error); - } else { - if (debug) - $log.debug("inventoryBlueprintController.loadComponents succeeded, size " + jsonObj.data.length); - //console.log(jsonObj); - InventoryBlueprintService.getComponents().then(function(jsonObj) { - /* - $scope.ecdapp.newApplicationName = ""; - $scope.ecdapp.newApplicationDisplayName = ""; - $scope.ecdapp.selectedOption = $scope.ecdapp.components[0]; - */ - $scope.ecdapp.components = jsonObj; - $scope.ecdapp.enableAppForm = false; - $scope.ecdapp.selectAppComp(appName); - }); - } - }, function(error) { - $log.error("inventoryBlueprintController.addApplication failed: " + error); - }); - }; - - // Handler for file-select event - $scope.handleFileSelect = function() { - if (debug) - $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name); - fileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel); - }; - // Convert serviceIds, serviceLocations, and vnfTypes to JSON Array - $scope.ecdapp.convertStringsToArrays = function(serviceTypeRequest) { - if (serviceTypeRequest.serviceIds || serviceTypeRequest.serviceIds.trim() != '') { - try { - serviceTypeRequest.serviceIds = angular.fromJson(serviceTypeRequest.serviceIds.split(",")); - } catch (error) { - return 'Service Ids is not in the correct format.'; - } - } else { - serviceTypeRequest.serviceIds = []; - } - - if (serviceTypeRequest.serviceLocations || serviceTypeRequest.serviceLocations.trim() != '') { - try { - serviceTypeRequest.serviceLocations = angular.fromJson(serviceTypeRequest.serviceLocations.split(",")); - } catch (error) { - return 'Service Locations is not in the correct format.'; - } - } else { - serviceTypeRequest.serviceLocations = []; - } - - if (serviceTypeRequest.vnfTypes || serviceTypeRequest.vnfTypes.trim() != '') { - try { - serviceTypeRequest.vnfTypes = angular.fromJson(serviceTypeRequest.vnfTypes.split(",")); - } catch (error) { - return 'VNF Types is not in the correct format.'; - } - } else { - serviceTypeRequest.vnfTypes = []; - } - - try { - if (isNaN(serviceTypeRequest.typeVersion)) { - serviceTypeRequest.typeVersion = serviceTypeRequest.typeVersion.replace(/\./gi, ""); - serviceTypeRequest.typeVersion = angular.fromJson(serviceTypeRequest.typeVersion); - } - } catch (error) { - return 'typeVersion is not in the correct format.'; - } - - return null; - } - - /** - * Validates content of user-editable fields. - * Returns null if all is well, - * a descriptive error message otherwise. - */ - $scope.ecdapp.validateRequest = function(serviceTypeRequest) { - if (!serviceTypeRequest) - return 'No data found.\nPlease enter some values.'; - if (!serviceTypeRequest.owner || serviceTypeRequest.owner.trim() == '') { - return 'Application/Owner is required.\nPlease enter a value.'; - } - if (!serviceTypeRequest.typeName || serviceTypeRequest.typeName.trim() == '') { - return 'Type Name is required.\nPlease enter a value.'; - } - if (!serviceTypeRequest.typeVersion ) { - //|| serviceTypeRequest.typeVersion.trim() == '') { - return 'Type Version is required.\nPlease enter a value.'; - } - if (!serviceTypeRequest.blueprintTemplate || serviceTypeRequest.blueprintTemplate.trim() == '') - return 'Blueprint Template is required.\nPlease enter a value.'; - - return null; - } - - $scope.ecdapp.uploadBlueprint = function(serviceTypeRequest) { - if (debug) - $log.debug('uploadBlueprint: serviceType is ' + JSON.stringify(serviceTypeRequest)); - $scope.ecdapp.uploadInProgress = true; - var validateMsg = $scope.ecdapp.validateRequest(serviceTypeRequest); - if (validateMsg != null) { - editServiceType = angular.copy(serviceTypeRequest); - alert('Invalid Request:\n' + validateMsg); - $scope.ecdapp.uploadInProgress = false; - return; - } - //var authUser = $scope.userId; - //serviceTypeRequest.owner = serviceTypeRequest.owner + ':' + authUser; - // Create a editServiceTypeRequest object for edit - var editServiceType = angular.copy(serviceTypeRequest); - var convertMsg = $scope.ecdapp.convertStringsToArrays(editServiceType); - if (convertMsg != null) { - editServiceType = angular.copy(serviceTypeRequest); - alert('Invalid Request:\n' + convertMsg); - return; - } - - InventoryBlueprintService.uploadBlueprint(editServiceType) - .then(function(response) { - if (debug) - $log.debug('inventoryBlueprintUploadCtrl.uploadBlueprint: ' + JSON.stringify(response)); - if (response && response.error) { - $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + response.error); - alert('Failed to upload blueprint:\n' + response.error); - } - else { - // Upload service returns null on success. - $modalInstance.close("success"); - } - $scope.ecdapp.uploadInProgress = false; - }, - function(error) { - $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + error); - $scope.ecdapp.uploadInProgress = false; - alert('Service failed to upload blueprint:\n' + error); - }); - - }; + } + } + } + + $scope.ecdapp.validateComp = function(appName) { + if($scope.ecdapp.serviceTypeRequest.component === "Select Component"){ + $scope.ecdapp.validComp = false; + } else { + $scope.ecdapp.validComp = true; + } + } + var fileReader = new FileReader(); + fileReader.onload = function(event) { + let yamlString = fileReader.result; + $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yamlString; + } + + // Handler for file-select event + $scope.handleFileSelect = function() { + if (debug) + $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name); + fileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel); + }; + // Convert serviceIds, serviceLocations, and vnfTypes to JSON Array + + $scope.ecdapp.convertStringsToArrays = function(serviceTypeRequest) { + if (serviceTypeRequest.serviceIds || serviceTypeRequest.serviceIds.trim() != '') { + try { + serviceTypeRequest.serviceIds = angular.fromJson(serviceTypeRequest.serviceIds.split(",")); + } catch (error) { + return 'Service Ids is not in the correct format.'; + } + } else { + serviceTypeRequest.serviceIds = []; + } + + if (serviceTypeRequest.serviceLocations || serviceTypeRequest.serviceLocations.trim() != '') { + try { + serviceTypeRequest.serviceLocations = angular.fromJson(serviceTypeRequest.serviceLocations.split(",")); + } catch (error) { + return 'Service Locations is not in the correct format.'; + } + } else { + serviceTypeRequest.serviceLocations = []; + } + + if (serviceTypeRequest.vnfTypes || serviceTypeRequest.vnfTypes.trim() != '') { + try { + serviceTypeRequest.vnfTypes = angular.fromJson(serviceTypeRequest.vnfTypes.split(",")); + } catch (error) { + return 'VNF Types is not in the correct format.'; + } + } else { + serviceTypeRequest.vnfTypes = []; + } + return null; + } + + $scope.ecdapp.isInt = function(value) { + return !isNaN(value) && + parseInt(Number(value)) == value && + !isNaN(parseInt(value, 10)); + } + /** + * Validates content of user-editable fields. + * Returns null if all is well, + * a descriptive error message otherwise. + */ + $scope.ecdapp.validateRequest = function(serviceTypeRequest) { + if (!serviceTypeRequest) + return 'No data found.\nPlease enter some values.'; + if (!serviceTypeRequest.owner || serviceTypeRequest.owner.trim() == '') { + return 'Application/Owner is required.\nPlease enter a value.'; + } + if (!serviceTypeRequest.typeName || serviceTypeRequest.typeName.trim() == '') { + return 'Type Name is required.\nPlease enter a value.'; + } + if (!serviceTypeRequest.typeVersion ) { + //|| serviceTypeRequest.typeVersion.trim() == '') { + return 'Type Version is required.\nPlease enter a value.'; + } + if (!$scope.ecdapp.isInt(serviceTypeRequest.typeVersion) ) { + //|| serviceTypeRequest.typeVersion.trim() == '') { + return 'Type Version should be a valid Integer.'; + } + if (!serviceTypeRequest.blueprintTemplate || serviceTypeRequest.blueprintTemplate.trim() == '') + return 'Blueprint Template is required.\nPlease enter a value.'; + + return null; + } + + $scope.ecdapp.uploadBlueprint = function(serviceTypeRequest) { + if (debug) + $log.debug('uploadBlueprint: serviceType is ' + JSON.stringify(serviceTypeRequest)); + $scope.ecdapp.uploadInProgress = true; + var validateMsg = $scope.ecdapp.validateRequest(serviceTypeRequest); + if (validateMsg != null) { + editServiceType = angular.copy(serviceTypeRequest); + alert('Invalid Request:\n' + validateMsg); + $scope.ecdapp.uploadInProgress = false; + return; + } + //var authUser = $scope.userId; + //serviceTypeRequest.owner = serviceTypeRequest.owner + ':' + authUser; + // Create a editServiceTypeRequest object for edit + var editServiceType = angular.copy(serviceTypeRequest); + var convertMsg = $scope.ecdapp.convertStringsToArrays(editServiceType); + if (convertMsg != null) { + editServiceType = angular.copy(serviceTypeRequest); + alert('Invalid Request:\n' + convertMsg); + return; + } + + InventoryBlueprintService.uploadBlueprint(editServiceType) + .then(function(response) { + if (debug) + $log.debug('inventoryBlueprintUploadCtrl.uploadBlueprint: ' + JSON.stringify(response)); + if (response && response.error) { + $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + response.error); + alert('Failed to upload blueprint:\n' + response.error); + } + else { + // Upload service returns null on success. + $modalInstance.close("success"); + } + $scope.ecdapp.uploadInProgress = false; + }, + function(error) { + $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + error); + $scope.ecdapp.uploadInProgress = false; + alert('Service failed to upload blueprint:\n' + error); + }); + + }; }); /*************************************************************************/ appDS2.controller('inventoryBlueprintViewCtrl', function( - $scope, $log, message, InventoryBlueprintService) { - - 'use strict'; - - var debug = false; - - if (debug) - $log.debug("inventoryBlueprintViewCtrl.message: " + JSON.stringify(message)); - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.blueprintId = message.blueprint.typeId; - - $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.typeName; - - // Fetch the blueprint - $scope.ecdapp.isDataLoading = true; - InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) { - if (debug) - $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed'; - } - else { - $scope.ecdapp.blueprint = jsonObj.blueprintTemplate; - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $scope.ecdapp.isDataLoading = false; - alert('Failed to get blueprint. Please retry.'); - $log.error("blueprintViewCtrl failed: " + error); - }); - + $scope, $log, message, InventoryBlueprintService) { + + 'use strict'; + + var debug = false; + + if (debug) + $log.debug("inventoryBlueprintViewCtrl.message: " + JSON.stringify(message)); + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.blueprintId = message.blueprint.typeId; + + $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.typeName; + + // Fetch the blueprint + $scope.ecdapp.isDataLoading = true; + InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) { + if (debug) + $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed'; + } + else { + $scope.ecdapp.blueprint = jsonObj.blueprintTemplate; + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $scope.ecdapp.isDataLoading = false; + alert('Failed to get blueprint. Please retry.'); + $log.error("blueprintViewCtrl failed: " + error); + }); + }); +appDS2.directive('json', function() { + return { + restrict: 'A', // only activate on element attribute + require: 'ngModel', // get a hold of NgModelController + link: function(scope, element, attrs, ngModelCtrl) { + function toUser(object) { + if (typeof object === 'object') { + return angular.toJson(object, true); + } else { + return object; + } + } + ngModelCtrl.$formatters.push(toUser); + // $watch(attrs.ngModel) wouldn't work if this directive created a new scope; + // see http://stackoverflow.com/questions/14693052/watch-ngmodel-from-inside-directive-using-isolate-scope how to do it then + scope.$watch(attrs.ngModel, function(newValue, oldValue) { + if (newValue != oldValue) { + ngModelCtrl.$setViewValue(toUser(newValue)); + // TODO avoid this causing the focus of the input to be lost.. + ngModelCtrl.$render(); + } + }, true); // MUST use objectEquality (true) here, for some reason.. + } + }; +}); /*************************************************************************/ appDS2.controller('inventoryBlueprintDeployCtrl', function( - $scope, $rootScope, $log, $modal, $modalInstance, message, InventoryDeploymentService, InventoryBlueprintService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Deploy Blueprint'; - $scope.ecdapp.errMsg = ''; - - // deployment in progress - $scope.ecdapp.deploymentInProgress = false; - $scope.ecdapp.isDataLoading = false; - $scope.ecdapp.tenant = $rootScope.tenantList.tenant; - $scope.ecdapp.validTenant = false; - - // Cache the input parameter names for validation - if (debug) - $log.debug('inventoryBlueprintDeployCtrl: inputs: ' + JSON.stringify(message.blueprint.blueprintInputs)); - $scope.ecdapp.inputsDict = message.blueprint.blueprintInputs; - - // Copy the input parameter names and default values - let inputsAndDefaults = {}; - for (var pkey in message.blueprint.blueprintInputs) { - if (debug) - $log.debug('inventoryBlueprintDeployCtrl: checking key ' + pkey); - let dval = message.blueprint.blueprintInputs[pkey].defaultValue; - if ( typeof dval === "undefined" ) - dval = ''; - inputsAndDefaults[pkey] = dval; - } - if (debug) - $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults)); - - // Create an object for edit - //var genDeployId = message.blueprint.component + "_" + message.blueprint.typeName; - $scope.ecdapp.editRequest = { - deployment_id : '', - type_id : message.blueprint.typeId, - fileModel : null, - parmFileDict : inputsAndDefaults, - tenant : '', - component: message.blueprint.component, - tag : message.blueprint.typeName - }; - $scope.ecdapp.validateTenant = function(){ - if($scope.ecdapp.editRequest.tenant === "Select Tenant"){ - $scope.ecdapp.validTenant = false; - }else{ - $scope.ecdapp.validTenant = true; - } + $scope, $rootScope, $log, $modal, $modalInstance, message, InventoryDeploymentService, InventoryBlueprintService) { + + 'use strict'; + + // Controls logging in this controller + var debug = false; + + // this object holds all app data and functions + $scope.ecdapp = {}; + $scope.ecdapp.label = 'Deploy Blueprint'; + $scope.ecdapp.errMsg = ''; + $scope.ecdapp.availableTenants = message.tenantList; + + $scope.ecdapp.deploymentInProgress = false; + $scope.ecdapp.validTenant = false; + let inputsAndDefaults = {}; + let inputsAndDescriptions = {}; + + // Create an object for edit + $scope.ecdapp.editRequest = { + deployment_id : '', + type_id : message.blueprint.typeId, + fileModel : null, + parmFileDict : inputsAndDefaults, + descriptionDict : inputsAndDescriptions, + tenant : '', + component: message.blueprint.component, + tag : message.blueprint.typeName + }; + // Fetch the blueprint + $scope.ecdapp.isDataLoading = true; + InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) { + if (debug) + $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); + if (jsonObj.error) { + $scope.ecdapp.errMsg = 'Request Failed'; + } + else { + $scope.ecdapp.inputsDict = jsonObj.blueprintInputs; + for (var pkey in $scope.ecdapp.inputsDict) { + if (debug) + $log.debug('inventoryBlueprintDeployCtrl: checking key ' + pkey); + let dval = $scope.ecdapp.inputsDict[pkey].defaultValue; + let description = $scope.ecdapp.inputsDict[pkey].description; + if ( typeof dval === "undefined" ) + dval = ''; + if ( typeof description === "undefined" ) + description = ''; + inputsAndDefaults[pkey] = dval; + inputsAndDescriptions[pkey] = description; + if (debug) + $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults)); + } + } + $scope.ecdapp.isDataLoading = false; + }, function(error) { + $scope.ecdapp.isDataLoading = false; + alert('Failed to get blueprint. Please retry.'); + $log.error("blueprintViewCtrl failed: " + error); + }); + + $scope.ecdapp.validateTenant = function(){ + if($scope.ecdapp.editRequest.tenant === "Select Tenant"){ + $scope.ecdapp.validTenant = false; + }else{ + $scope.ecdapp.validTenant = true; + } + } + /** + * Handler for file-read event reads file, parses JSON, validates content. + */ + var fileReader = new FileReader(); + fileReader.onload = function(event) { + let jsonString = fileReader.result; + if (debug) + $log.debug('fileReader.onload: read: ' + jsonString); + let ydict = {}; + try { + ydict = JSON.parse(jsonString); + } + catch (ex) { + alert('Failed to parse file as JSON:\n' + ex); } - /** - * Handler for file-read event reads file, parses JSON, validates content. - */ - var fileReader = new FileReader(); - fileReader.onload = function(event) { - let jsonString = fileReader.result; - if (debug) - $log.debug('fileReader.onload: read: ' + jsonString); - let ydict = {}; - try { - ydict = JSON.parse(jsonString); - } - catch (ex) { - alert('Failed to parse file as JSON:\n' + ex); - } - // Process the file - for (var ykey in ydict) { - let yval = ydict[ykey]; - if (debug) - $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); - // Allow only expected keys with scalar values - if (! (ykey in $scope.ecdapp.editRequest.parmFileDict)) - alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey); - /* + // Process the file + for (var ykey in ydict) { + let yval = ydict[ykey]; + if (debug) + $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); + // Allow only expected keys with scalar values + if (! (ykey in $scope.ecdapp.editRequest.parmFileDict)) + alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey); + /* else if (typeof yval !== 'string' && typeof yval !== 'number') alert('Unexpected file content:\nNot a simple key-value pair:\n' + ykey); - */ - if (yval.constructor === {}.constructor) - $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval); - else - $scope.ecdapp.editRequest.parmFileDict[ykey] = yval; - } - if (debug) - $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict)); - - // Update table in all cases - $scope.$apply(); - } - - // Handler for file-select event - $scope.handleFileSelect = function() { - if (debug) - $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); - fileReader.readAsText($scope.ecdapp.editRequest.fileModel); - }; - - /** - * Validates content of user-editable fields. - * Returns null if all is well, - * a descriptive error message otherwise. - */ - $scope.ecdapp.validateRequest = function(editRequest) { - if (editRequest == null) - return 'No data found.\nPlease enter some values.'; - if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '') - return 'Deployment ID is required.\nPlease enter a value.'; - if (editRequest.type_id == null || editRequest.type_id.trim() == '') - return 'Type ID is required.\nPlease enter a value.'; - if (editRequest.tag == null || editRequest.tag.trim() == '') - return 'Deployment tag is required.\nPlease enter a value.'; - if (editRequest.tenant == null || editRequest.tenant.trim() == '') - return 'Tenant name is required.\nPlease enter a value.'; - // Check that every file parameter is defined by blueprint - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) { - // Defined in blueprint? - if (! $scope.ecdapp.inputsDict[pkey]) - return 'Unexpected input parameter\n' + pkey; - return null; - } - }; - - $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) { - var modalInstance = $modal.open({ - templateUrl : 'inventory_execution_view_popup.html', - controller : 'inventoryDeploymentExecutionsViewCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - deployment : deployment - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - // No response. - }); - }; - $scope.ecdapp.deployBlueprint = function(editRequest) { - //editRequest.tenant = $rootScope.tenantList.tenant; - $scope.ecdapp.errMsg = ''; - editRequest.deployment_id = editRequest.component + "_" + editRequest.tag; - if (debug) - $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest)); - var validateMsg = $scope.ecdapp.validateRequest(editRequest); - if (validateMsg != null) { - alert('Invalid Request:\n' + validateMsg); - return; - } - // Create request with key:value parameters dictionary - let deploymentRequestObject = { - deploymentId : editRequest.deployment_id, - serviceTypeId : editRequest.type_id, - inputs : {}, - tenant : editRequest.tenant, - method : "create" - }; - let deploymentExecObj = { - deploymentRef : editRequest.deployment_id, - tenant : editRequest.tenant - } - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) - try { - deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]); - } catch (error) { - deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey]; - } - if (debug) - $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject)); - - $scope.ecdapp.deploymentInProgress = true; - InventoryDeploymentService.deployBlueprint(deploymentRequestObject) - .then(function(response) { - $scope.ecdapp.deploymentInProgress = false; - if (response.error) { - $scope.ecdapp.errMsg = 'Failed to deploy blueprint: ' + response.error; - alert('Failed to deploy blueprint:\n' + response.error); - } - else { - $modalInstance.close(response); - // launch the view executions modal - $scope.ecdapp.viewDeploymentExecutionsModalPopup(deploymentExecObj); - } - }, - function (error) { - $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error); - $scope.ecdapp.errMsg = 'Server rejected deployment request: ' + error; - alert('Server rejected deployment request:\n' + error); - $scope.ecdapp.deploymentInProgress = false; - } - ); - }; + */ + if (yval.constructor === {}.constructor) + $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval); + else + $scope.ecdapp.editRequest.parmFileDict[ykey] = yval; + } + if (debug) + $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict)); + + // Update table in all cases + $scope.$apply(); + } + + // Handler for file-select event + $scope.handleFileSelect = function() { + if (debug) + $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); + fileReader.readAsText($scope.ecdapp.editRequest.fileModel); + }; + + /** + * Validates content of user-editable fields. + * Returns null if all is well, + * a descriptive error message otherwise. + */ + $scope.ecdapp.validateRequest = function(editRequest) { + if (editRequest == null) + return 'No data found.\nPlease enter some values.'; + if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '') + return 'Deployment ID is required.\nPlease enter a value.'; + if (editRequest.type_id == null || editRequest.type_id.trim() == '') + return 'Type ID is required.\nPlease enter a value.'; + if (editRequest.tag == null || editRequest.tag.trim() == '') + return 'Deployment tag is required.\nPlease enter a value.'; + if (editRequest.tenant == null || editRequest.tenant.trim() == '') + return 'Tenant name is required.\nPlease enter a value.'; + // Check that every file parameter is defined by blueprint + for (var pkey in $scope.ecdapp.editRequest.parmFileDict) { + // Defined in blueprint? + if (! $scope.ecdapp.inputsDict[pkey]) + return 'Unexpected input parameter\n' + pkey; + return null; + } + }; + + $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) { + var modalInstance = $modal.open({ + templateUrl : 'inventory_execution_view_popup.html', + controller : 'inventoryDeploymentExecutionsViewCtrl', + windowClass: 'modal-docked', + sizeClass: 'modal-jumbo', + resolve : { + message : function() { + var dataForPopup = { + deployment : deployment + }; + return dataForPopup; + } + } + }); + modalInstance.result.then(function(response) { + // No response. + }); + }; + $scope.ecdapp.deployBlueprint = function(editRequest) { + //editRequest.tenant = $rootScope.tenantList.tenant; + $scope.ecdapp.errMsg = ''; + editRequest.deployment_id = editRequest.component + "_" + editRequest.tag; + if (debug) + $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest)); + var validateMsg = $scope.ecdapp.validateRequest(editRequest); + if (validateMsg != null) { + alert('Invalid Request:\n' + validateMsg); + return; + } + // Create request with key:value parameters dictionary + let deploymentRequestObject = { + deploymentId : editRequest.deployment_id, + serviceTypeId : editRequest.type_id, + inputs : {}, + tenant : editRequest.tenant, + method : "create" + }; + let deploymentExecObj = { + deploymentRef : editRequest.deployment_id, + tenant : editRequest.tenant + } + for (var pkey in $scope.ecdapp.editRequest.parmFileDict) + try { + deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]); + } catch (error) { + deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey]; + } + if (debug) + $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject)); + + $scope.ecdapp.deploymentInProgress = true; + + InventoryDeploymentService.deployBlueprint(deploymentRequestObject) + .then(function(response) { + $scope.ecdapp.deploymentInProgress = false; + if (response.error) { + $scope.ecdapp.errMsg = 'Failed to deploy blueprint: ' + response.error; + alert('Failed to deploy blueprint:\n' + response.error); + InventoryDeploymentService.deleteBlueprint(editRequest.deployment_id, editRequest.tenant); + } + else { + $modalInstance.close(response); + // launch the view executions modal + $scope.ecdapp.viewDeploymentExecutionsModalPopup(deploymentExecObj); + } + }, + function (error) { + $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error); + $scope.ecdapp.errMsg = 'Server rejected deployment request: ' + error; + alert('Server rejected deployment request:\n' + error); + $scope.ecdapp.deploymentInProgress = false; + } + ); + }; }); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-service.js index b553c9e..02709d3 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-service.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-service.js @@ -35,11 +35,92 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) { return $q.reject(error.statusText); }); }, + getBlueprintsSummary: function() { + // cache control for IE + let cc = "&cc=" + new Date().getTime().toString(); + let url = null; + url = 'inventory/dcae-service-types?_include=typeName,typeVersion,typeId' + cc; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryBlueprintService.getBlueprintsSummary: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryBlueprintService.getBlueprintsSummary failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getOwnersList: function() { + let url = 'inventory/owners'; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryBlueprintService.getOwnersList: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryBlueprintService.getOwnersList failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getBlueprintsList: function() { + let url = 'inventory/service-type-list'; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryBlueprintService.getBlueprintsList: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryBlueprintService.getBlueprintsList failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getBlueprintIdsList: function(searchBy) { + let url = ''; + if (searchBy) { + url = 'inventory/service-type-id-list?searchBy=' + searchBy; + } else { + url = 'inventory/service-type-id-list'; + } + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryBlueprintService.getBlueprintIdsList: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryBlueprintService.getBlueprintIdsList failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, /** * get deployments for a blueprint */ getDeploymentForBp: function(bpArr) { - let url = 'inventory/dcae-services/typeIds'; + let url = 'deployment_blueprint_map'; + //let url = 'inventory/dcae-services/typeIds'; return $http({ method: 'POST', url: url, @@ -49,7 +130,6 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) { if (response.data == null) return $q.reject('InventoryBlueprintService.getDeploymentForBp: response.data null or not object'); else { - console.log(response.data); return response.data; } }, @@ -166,7 +246,6 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) { if (response.data == null) return $q.reject('InventoryBlueprintService.viewBlueprint: response.data null or not object'); else { - console.log(response.data); return response.data; } }, @@ -281,6 +360,12 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) { }, */ deleteBlueprint: function(typeId) { + /*var typeId = blueprint.typeId; + var deploymentItems = blueprint.deployments.items; + var deplIdList = []; + for (var i=0; i < deploymentItems.length; i++) { + deplIdList.push(deploymentItems.id); + }*/ let url = 'inventory/dcae-service-types/' + typeId; return $http({ method: 'DELETE', diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-controllers.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-controllers.js deleted file mode 100644 index e17dcae..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-controllers.js +++ /dev/null @@ -1,1352 +0,0 @@ -appDS2.controller('inventoryDeploymentTableController', function( - $rootScope, $scope, $routeParams, $route, - $interval, $log, $modal, modalService, - InventoryDeploymentService, InventoryBlueprintService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - // models for controls on screen - $scope.ecdapp.tableData = []; - $scope.ecdapp.currentPageNum = 1; - $scope.ecdapp.viewPerPage = 10; - // other - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; - // sorting - $scope.ecdapp.sortBy = null; - // searching - $scope.ecdapp.searchBy = $routeParams.depId; - $scope.ecdapp.selectedRow = null; // initialize our variable to null - $scope.ecdapp.setClickedRow = function(index){ //function that sets the value of selectedRow to current index - $scope.ecdapp.selectedRow = index; - } - - $scope.ecdapp.updateTable = function() { - $scope.ecdapp.isSrvcDataLoading = true; - var srvcIds = []; - var cloneGrid = $scope.ecdapp.tableData; - angular.forEach($scope.ecdapp.tableData, function(item, index) { - angular.forEach(item, function(value, key) { - if (key === "deploymentRef") { - srvcIds.push(value); - } - }); - }); - - InventoryDeploymentService.getDeploymentStatus(srvcIds) - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryDeploymentTableController.updateTable failed: " + jsonObj.error); - } else { - for (var indx = 0; indx < jsonObj.length; indx++) { - if (jsonObj[indx].status === "terminated") { - jsonObj[indx].status = "completed"; - jsonObj[indx].statusImg = "static/fusion/images/active.png"; - } else { - jsonObj[indx].statusImg = "static/fusion/images/inactive.png"; - } - cloneGrid[indx].statusInfo = jsonObj[indx]; - } - $scope.ecdapp.tableData = cloneGrid; - } - $scope.ecdapp.isSrvcDataLoading = false; - }, function(error) { - $log.error("inventoryBlueprintController.updateTable failed: " + error); - $scope.ecdapp.isSrvcDataLoading = false; - }); - } - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either a list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.loadTable = function(sortBy, searchBy) { - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.sortBy = sortBy; - $scope.ecdapp.searchBy = searchBy; - InventoryDeploymentService.getDeployments($scope.ecdapp.currentPageNum, - $scope.ecdapp.viewPerPage, sortBy, searchBy).then( - function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryDeploymentController.loadTable failed: " - + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - $scope.ecdapp.updateTable(); - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error("inventoryDeploymentController.loadTable failed: " - + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - }; - - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either a list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.sortTable = function(sortBy) { - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.sortBy = sortBy; - InventoryDeploymentService.getDeployments($scope.ecdapp.currentPageNum, - $scope.ecdapp.viewPerPage, sortBy, $scope.ecdapp.searchBy).then( - function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryDeploymentController.loadTable failed: " - + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - $scope.ecdapp.updateTable(); - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error("inventoryDeploymentController.loadTable failed: " - + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - }; - - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either a list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.searchTable = function(searchBy) { - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.searchBy = searchBy; - InventoryDeploymentService.getDeployments($scope.ecdapp.currentPageNum, - $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, searchBy).then( - function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryDeploymentController.loadTable failed: " - + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.tableData = []; - } else { - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - $scope.ecdapp.tableData = jsonObj.items; - $scope.ecdapp.updateTable(); - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error("inventoryDeploymentController.loadTable failed: " - + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - }); - }; - - $scope.ecdapp.checkHelmStatus = function(deployment) { - var selTenant = deployment.statusInfo.tenant_name; - if ( typeof selTenant === "undefined" ) { - selTenant = "default_tenant"; - } - deployment.onlyLatest = true; - - // This object holds data for this operation - $scope.ecdapp.helmStatusRequest = { - "deployment_id": deployment.deploymentRef, - "workflow_name": "status", - "tenant": selTenant - }; - InventoryDeploymentService.helmStatusFlow($scope.ecdapp.helmStatusRequest).then(function(jsonObj) { - if (debug) - $log.debug("checkHelmStatus response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; - $scope.ecdapp.updatingDeployment = false; - $scope.ecdapp.isDataLoading = false; - } else { - console.log('%c POSTED helm status request', 'color: magenta; font-weight: bold;'); - } - }, function(error) { - $log.error('helmStatusFlow failed: ' + error); - }); - $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment); - }; - /** - * Shows a modal pop-up with blueprint content. - * Passes data in via an object named "message". - */ - $scope.ecdapp.viewBlueprintDataModal = function(deployment) { - var modalInstance = $modal.open({ - templateUrl : 'blueprint_data_view_popup.html', - controller : 'deployBlueprintViewCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - blueprint : deployment - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - }); - }; - - /** - * Invoked at first page load AND when - * user clicks on the B2B pagination control. - */ - $scope.pageChangeHandler = function(page) { - // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); - $scope.ecdapp.currentPageNum = page; - $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy); - } - - /** - * Shows a modal pop-up to confirm deletion. - * On successful completion, updates the table. - */ - $scope.ecdapp.deleteDeploymentModalPopup = function(deployment) { - deployment.onlyLatest = true; - var modalInstance = $modal.open({ - templateUrl : 'inventory_deployment_delete_popup.html', - controller : 'inventoryDeploymentDeleteCtrl', - sizeClass: 'modal-small', - resolve : { - message : function() { - var dataForPopup = { - deployment : deployment, - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - if (debug) - $log.debug('deleteDeploymentPopup: response: ' + JSON.stringify(response)); - if (response == null) { - // $log.debug('user closed dialog'); - } - else { - if (response.error != null) { - $log.error('deleteDeploymentModalPopup failed: ' + response.error); - alert('Failed to delete deployment:\n' + response.error); - } - else { - $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment); - } - } - }); - }; - - /** - * Shows a modal pop-up with executions for a deployment. - * Passes data in via an object named "deployment". - */ - $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) { - var modalInstance = $modal.open({ - templateUrl : 'inventory_execution_view_popup.html', - controller : 'inventoryDeploymentExecutionsViewCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - deployment : deployment - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - // No response. - }); - }; - - /** - * Shows a modal pop-up with executions for a deployment. - * Passes data in via an object named "deployment". - */ - $scope.ecdapp.viewDeploymentInputsModalPopup = function(deployment) { - var modalInstance = $modal.open({ - templateUrl : 'inventory_deployment_inputs_view_popup.html', - controller : 'inventoryDeploymentInputsViewCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve : { - message : function() { - var dataForPopup = { - deployment : deployment - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - // No response. - }); - }; - - /** - * Shows a modal pop-up to initiate helm upgrade for a deployment - */ - $scope.ecdapp.upgradeDeploymentModalPopup = function(deployment) { - //console.log(deployment); - var modalInstance = $modal.open({ - templateUrl: 'inventory_deployment_upgrade_popup.html', - controller: 'inventoryDeploymentUpgradeCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve: { - message: function() { - var dataForPopup = { - deployment : deployment - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - // No response. - }); - }; - - /** - * Shows a modal pop-up to initiate helm rollback for a deployment - */ - $scope.ecdapp.rollbackDeploymentModalPopup = function(deployment) { - var modalInstance = $modal.open({ - templateUrl: 'inventory_deployment_rollback_popup.html', - controller: 'inventoryDeploymentRollbackCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve: { - message: function() { - var dataForPopup = { - deployment : deployment - }; - return dataForPopup; - } - } - }); - modalInstance.result.then(function(response) { - // No response. - }); - }; - - /** - * Shows a modal pop-up to initiate update blueprint for a deployment - */ - $scope.ecdapp.updateDeploymentModalPopup = function(deployment) { - var modalInstance = $modal.open({ - templateUrl: 'inventory_deployment_update_popup.html', - controller: 'inventoryDeploymentUpdateCtrl', - windowClass: 'modal-docked', - sizeClass: 'modal-jumbo', - resolve: { - message: function() { - var dataForPopup = { - deployment : deployment - }; - return dataForPopup; - } - } - }); - }; - - /** - * Shows a modal pop-up to confirm service deletion. - * On successful completion, updates the table. - */ - $scope.ecdapp.deleteServiceModalPopup = function(service) { - modalService.popupConfirmWin("Confirm", "Delete Service with ID '" - + service.serviceId + "'?", function() { - InventoryDeploymentService.deleteService(service.serviceId).then( - function(response) { - if (debug) - $log.debug('deleteServiceModalPopup: response: ' + JSON.stringify(response)); - if (response && response.error) { - alert('Failed to delete service:\n' + response.error); - } - else { - // No response body on success. - $scope.ecdapp.loadTable(); - } - }, - function(error) { - $log.error('InventoryDeploymentService.deleteService failed: ' + error); - alert('Service failed to delete service:\n' + error); - }); - }) - }; -}); - -/*************************************************************************/ - -appDS2.controller('inventoryDeploymentDeleteCtrl', function( - $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Undeploy?'; - $scope.ecdapp.deploymentRef = message.deployment.deploymentRef; - var selTenant = message.deployment.statusInfo.tenant_name; - $scope.ecdapp.ui_tenant = selTenant; - $scope.ecdapp.tenant = selTenant; - - $scope.ecdapp.deleteDeploymentById = function(){ - InventoryDeploymentService.deleteDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then( - function(response) { - if (debug) - $log.debug('inventoryDeploymentDeleteCtrl.deleteDeployment: ' + JSON.stringify(response)); - if (response && response.error) { - $log.error('InventoryDeploymentService.deleteDeployment failed: ' + response.error); - alert('Failed to delete deployment:\n' + response.error); - } - else { - // Delete service returns null on success. - $modalInstance.close("success"); - } - }, - function(error) { - $log.error('InventoryDeploymentService.deleteDeployment failed: ' + error); - alert('Service failed to delete deployment:\n' + error); - }); - } - -}); - -/*************************************************************************/ - -appDS2.controller('inventoryDeploymentExecutionsViewCtrl', function( - $scope, $rootScope, $interval, $log, $modalInstance, message, modalService, InventoryExecutionService, ExecutionService) { - - 'use strict'; - - var debug = false; - - if (debug) - $log.debug("inventoryDeploymentsExecutionsViewCtrl.message: " + JSON.stringify(message)); - - // this object holds all app data and functions - $scope.ecdapp = {}; - // models for controls on screen - $scope.ecdapp.label = 'Deployment Executions'; - $scope.ecdapp.tableData = []; - $scope.ecdapp.logTableData = []; - $scope.ecdapp.currentPageNum = 1; - $scope.ecdapp.viewPerPage = 50; - $scope.ecdapp.currentLogPageNum = 1; - - // other - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isEventLogQuery = false; - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.isLastExecution = message.deployment.onlyLatest; - $scope.ecdapp.isLogType = true; - $scope.ecdapp.refresh_switch = { - value: true - }; - $scope.ecdapp.options = { - "on":"On", - "off":"Off" - } - var selTenant = 'default_tenant'; - - if (typeof message.deployment.statusInfo === "undefined") { - selTenant = message.deployment.tenant; - } else { - selTenant = message.deployment.statusInfo.tenant_name; - } - - $scope.ecdapp.ui_tenant = selTenant; - $scope.ecdapp.tenant = selTenant; - $scope.ecdapp.deplRef = message.deployment.deploymentRef; - var stop; - /** - * Loads the table. Interprets the remote controller's response and copies - * to scope variables. The response is either a list to be assigned to - * tableData, or an error to be shown. - */ - $scope.ecdapp.loadTable = function() { - $scope.ecdapp.isDataLoading = true; - InventoryExecutionService.getExecutionsByDeployment(message.deployment.deploymentRef, - $scope.ecdapp.tenant, - $scope.ecdapp.currentPageNum, - $scope.ecdapp.viewPerPage).then( - function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryDeploymentExecutionsViewCtrl.loadTable failed: " - + jsonObj.error); - $scope.ecdapp.isRequestFailed = true; - if (jsonObj.error.includes("404")) { - $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; - } - $scope.ecdapp.tableData = []; - $scope.ecdapp.stopLoading(); - } else { - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.totalPages = jsonObj.totalPages; - var resultLen = jsonObj.items.length; - if (resultLen != undefined && resultLen > 0) { - var exec_id = jsonObj.items[resultLen-1].id; - if ($scope.ecdapp.isLastExecution) { - $scope.ecdapp.tableData = []; - $scope.ecdapp.tableData.push(jsonObj.items[resultLen-1]); - } else { - $scope.ecdapp.tableData = jsonObj.items; - } - $scope.ecdapp.getExecutionLogs(exec_id, $scope.ecdapp.tenant); - } - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error("inventoryDeploymentExecutionsViewCtrl.loadTable failed: " - + error); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.tableData = []; - $scope.ecdapp.isDataLoading = false; - $scope.ecdapp.stopLoading(); - }); - }; - $scope.$watch('ecdapp.refresh_switch["value"]', function(newValue,oldValue,scope) { - if (newValue != oldValue) { - if (newValue === true) { - $scope.ecdapp.loadTable(); - stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false); - } else { - $scope.ecdapp.stopLoading(); - } - } - }, true); - - if ($scope.ecdapp.refresh_switch.value === true) { - stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false); - } - - $scope.ecdapp.stopLoading = function() { - if (angular.isDefined(stop)) { - $interval.cancel(stop); - stop = undefined; - } - }; - - $scope.ecdapp.cancelExecutionModalPopup = function(execution, tenant) { - modalService.popupConfirmWin("Confirm", "Cancel execution with ID '" - + execution.id + "'?", function() { - $scope.ecdapp.isCancelOn = true; - // TODO: gather action from user - InventoryExecutionService.cancelExecution(execution.id, execution.deployment_id, "force-cancel", tenant).then( - function(response) { - if (debug) - $log.debug("Controller.cancelExecutionModalPopup: " + JSON.stringify(response)); - if (response && response.error) { - // $log.error('cancelExectuion failed: ' + response.error); - alert('Failed to cancel execution:\n' + response.error); - $scope.ecdapp.isCancelOn = false; - } - else { - // No response body on success. - $scope.ecdapp.isCancelOn = false; - $scope.ecdapp.loadTable(); - } - }, - function(error) { - $scope.ecdapp.isCancelOn = false; - $log.error('ExecutionService.cancelExecution failed: ' + error); - alert('Service failed to cancel execution:\n' + error); - }); - }) - }; - - /** - * Invoked at first page load AND when - * user clicks on the B2B pagination control. - */ - $scope.pageChangeHandler = function(page) { - if (debug) - console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page); - $scope.ecdapp.currentPageNum = page; - $scope.ecdapp.loadTable(); - - } - - $scope.ecdapp.selected = false; - $scope.ecdapp.toggleStatusDefinitions = function() { - $scope.ecdapp.selected = $scope.ecdapp.selected ? false :true; - } - - /** - * Shows a modal pop-up with the error. - */ - $scope.ecdapp.viewErrorModalPopup = function(row) { - $modalInstance.dismiss('cancel'); - modalService.showFailure('Error Details', row.error, function() { } ); - }; - - $scope.ecdapp.getExecutionLogs = function(id, tenant) { - $scope.ecdapp.executionId = id; - $scope.ecdapp.isEventLogQuery = false; - InventoryExecutionService.getEventsByExecution(id , $scope.ecdapp.isLogType, tenant, - $scope.ecdapp.currentLogPageNum, $scope.ecdapp.viewPerPage ).then( - function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: " - + jsonObj.error); - $scope.ecdapp.isEventLogQuery = false; - $scope.ecdapp.evtErrMsg = jsonObj.error; - $scope.ecdapp.logTableData = []; - } else { - $scope.ecdapp.isEventLogQuery = true; - $scope.ecdapp.evtErrMsg = null; - $scope.ecdapp.totalLogPages = jsonObj.totalPages; - $scope.ecdapp.logTableData = jsonObj.items; - /* - if ($scope.ecdapp.isLogType) { - $scope.ecdapp.logTableData = jsonObj.items; - } else { - $scope.ecdapp.logTableData = []; - angular.forEach(jsonObj.items, function(item, index) { - angular.forEach(item, function(value, key) { - if (key === "type" && value != "cloudify_log") { - $scope.ecdapp.logTableData.push(item); - } - }); - }); - } - */ - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: " - + error); - $scope.ecdapp.evtErrMsg = error; - $scope.ecdapp.logTableData = []; - $scope.ecdapp.isDataLoading = false; - }); - } - - $scope.$on('$destroy', function() { - // Make sure that the interval is destroyed too - $scope.ecdapp.stopLoading(); - }); -}); - -/*************************************************************************/ -appDS2.controller('inventoryDeploymentInputsViewCtrl', function( - $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Deployment Inputs'; - $scope.ecdapp.deployment = null; - $scope.ecdapp.deploymentRef = message.deployment.deploymentRef; - $scope.ecdapp.serviceId = message.deployment.serviceId; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; - var selTenant = message.deployment.statusInfo.tenant_name; - if ( typeof selTenant === "undefined" ) { - selTenant = "default_tenant"; - } - $scope.ecdapp.ui_tenant = selTenant; - $scope.ecdapp.tenant = selTenant; - - InventoryDeploymentService.getDeployment(message.deployment.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) { - if (deployment.items.length == 0) { - $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; - $log.error("InventoryDeploymentSerice.getDeployment failed: " - + $scope.ecdapp.errMsg); - $scope.ecdapp.isRequestFailed = true; - } - // Deployment IDs are unique, so this will always return exactly one item! - // retrieve blueprintId and inputs of deployment. - else { - $scope.ecdapp.errMsg = null; - $scope.ecdapp.deployment = deployment.items[0]; - $scope.ecdapp.isRequestFailed = false; - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error)); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.isDataLoading = false; - }); -}); - -/*************************************************************************/ -appDS2.controller('inventoryDeploymentUpdateCtrl', function( - $scope, $log, $modalInstance, message, InventoryBlueprintService, InventoryDeploymentService) { - - 'use strict'; - - var debug = false; - if (debug) - $log.debug("inventoryDeploymentUpdateCtrl.message: " + JSON.stringify(message)); - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.deploymentInProgress = false; - $scope.ecdapp.serviceTypeComplete = false; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.label = 'Update Deployment: ' + message.deployment.deploymentRef; - $scope.ecdapp.deploymentRef = message.deployment.deploymentRef; - var selTenant = message.deployment.statusInfo.tenant_name; - if ( typeof selTenant === "undefined" ) { - selTenant = "default_tenant"; - } - $scope.ecdapp.tenant = selTenant; - $scope.ecdapp.ui_tenant = selTenant; - $scope.ecdapp.typeName = ''; - $scope.ecdapp.typeId = ''; - $scope.ecdapp.inputsDict = {}; - $scope.ecdapp.editRequest = { - deployment_id : message.deployment.deploymentRef, - type_id : '', - fileModel : null, - parmFileDict : {}, - tenant : $scope.ecdapp.tenant - }; - - // get the blueprints from inventory matching deployment reference filter - $scope.ecdapp.bp = []; - var sortBy = ''; - var searchBy = message.deployment.deploymentRef.split("_", 1); - searchBy = searchBy[0]; - InventoryBlueprintService.getBlueprints(1, 100, sortBy, searchBy) - .then(function(jsonObj) { - if (jsonObj.error) { - $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + jsonObj.error); - $scope.ecdapp.errMsg = jsonObj.error; - $scope.ecdapp.bp = []; - } else { - $scope.ecdapp.errMsg = null; - $scope.ecdapp.bp = jsonObj.items; - if (Array.isArray($scope.ecdapp.bp) ) { - angular.forEach($scope.ecdapp.bp, function(item, index) { - item.checked = false; - }); - } - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + error); - $scope.ecdapp.errMsg = error; - $scope.ecdapp.bp = []; - $scope.ecdapp.isDataLoading = false; - }); - $scope.ecdapp.updateSelection = function(position) { - $scope.ecdapp.typeId = position; - $scope.ecdapp.editRequest.type_id = position; - angular.forEach($scope.ecdapp.bp, function(item, index) { - if (position != index+1) - item.checked = false; - }); - } - $scope.ecdapp.getBlueprint = function() { - $scope.ecdapp.isDataLoading = true; - InventoryBlueprintService.viewBlueprint($scope.ecdapp.typeId).then(function(jsonObj) { - if (debug) - $log.debug("inventoryDeploymentUpdateCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed'; - $scope.ecdapp.serviceTypeComplete = false; - $scope.ecdapp.isDataLoading = false; - } - else { - $scope.ecdapp.typeName = jsonObj.typeName; - $scope.ecdapp.typeVersion = jsonObj.typeVersion; - $scope.ecdapp.inputsDict = jsonObj.blueprintInputs; - // query the current deployment inputs - InventoryDeploymentService.getDeployment(message.deployment.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) { - if (deployment.items.length == 0) { - $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; - $log.error("InventoryDeploymentSerice.getDeployment failed: " - + $scope.ecdapp.errMsg); - //$scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.serviceTypeComplete = true; - } - // Deployment IDs are unique, so this will always return exactly one item! - // retrieve inputs of deployment. - else { - $scope.ecdapp.errMsg = null; - $scope.ecdapp.deployment = deployment.items[0]; - // Copy the input parameter names and default values - let inputsAndDefaults = {}; - for (var pkey in $scope.ecdapp.inputsDict) { - if (debug) - $log.debug('inventoryDeploymentUpdateCtrl: checking key ' + pkey); - let dval = $scope.ecdapp.deployment.inputs[pkey]; - //$scope.ecdapp.inputsDict[pkey].defaultValue; - if (dval === undefined || dval === null) { - dval = ''; - } - inputsAndDefaults[pkey] = dval; - } - $scope.ecdapp.editRequest.parmFileDict = inputsAndDefaults; - $scope.ecdapp.editRequest.type_id = $scope.ecdapp.typeId; - if (debug) - $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults)); - - $scope.ecdapp.serviceTypeComplete = true; - //$scope.$apply(); - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error)); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.isDataLoading = false; - }); - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $scope.ecdapp.isDataLoading = false; - $scope.ecdapp.serviceTypeComplete = false; - alert('Failed to get blueprint. Please retry with valid blueprint ID.'); - $log.error("inventoryDeploymentUpdateCtrl failed: " + error); - }); - }; - - /** - * Handler for file-read event reads file, parses JSON, validates content. - */ - var fileReader = new FileReader(); - fileReader.onload = function(event) { - let jsonString = fileReader.result; - if (debug) - $log.debug('fileReader.onload: read: ' + jsonString); - let ydict = {}; - try { - ydict = JSON.parse(jsonString); - } - catch (ex) { - alert('Failed to parse file as JSON:\n' + ex); - } - // Process the file - for (var ykey in ydict) { - let yval = ydict[ykey]; - if (debug) - $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); - // Allow only expected keys with scalar values - if (! (ykey in $scope.ecdapp.editRequest.parmFileDict)) - alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey); - if (yval.constructor === {}.constructor) - $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval); - else - $scope.ecdapp.editRequest.parmFileDict[ykey] = yval; - } - if (debug) - $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict)); - - // Update table in all cases - $scope.$apply(); - } - - // Handler for file-select event - $scope.handleFileSelect = function() { - if (debug) - $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); - fileReader.readAsText($scope.ecdapp.editRequest.fileModel); - }; - - $scope.ecdapp.validateRequest = function(editRequest) { - if (editRequest == null) - return 'No data found.\nPlease enter some values.'; - if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '') - return 'Deployment ID is required.\nPlease enter a value.'; - if (editRequest.type_id == null || editRequest.type_id.trim() == '') - return 'Type ID is required.\nPlease enter a value.'; - // Check that every file parameter is defined by blueprint - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) { - // Defined in blueprint? - if (! $scope.ecdapp.inputsDict[pkey]) - return 'Unexpected input parameter\n' + pkey; - } - return null; - } - - $scope.ecdapp.updateDeployment = function(editRequest) { - if (debug) - $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest)); - var validateMsg = $scope.ecdapp.validateRequest(editRequest); - if (validateMsg != null) { - alert('Invalid Request:\n' + validateMsg); - $scope.ecdapp.errMsg = validateMsg; - return; - } - // Create request with key:value parameters dictionary - let deploymentRequestObject = { - deploymentId : editRequest.deployment_id, - serviceTypeId : editRequest.type_id, - inputs : {}, - tenant : editRequest.tenant, - method : "update" - }; - for (var pkey in $scope.ecdapp.editRequest.parmFileDict) - try { - deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]); - } catch (error) { - deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey]; - } - if (debug) - $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject)); - - $scope.ecdapp.deploymentInProgress = true; - InventoryDeploymentService.deployBlueprint(deploymentRequestObject) - .then(function(response) { - $scope.ecdapp.deploymentInProgress = false; - if (response.error) { - alert('Failed to deploy blueprint:\n' + response.error); - $scope.ecdapp.errMsg = response.error; - } else { - alert('Deployment update request sent successfully, query the execution status for final outcome'); - $modalInstance.close(response); - } - }, - function (error) { - $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error); - alert('Server rejected deployment request:\n' + error); - $scope.ecdapp.deploymentInProgress = false; - } - ); - }; - -}); - - -/*************************************************************************/ - -appDS2.controller('deployBlueprintViewCtrl', function( - $scope, $log, message, InventoryBlueprintService) { - - 'use strict'; - - var debug = false; - - if (debug) - $log.debug("deployBlueprintViewCtrl.message: " + JSON.stringify(message)); - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.deploymentRef; - - var typeLink = message.blueprint.typeLink.href; - var n = typeLink.lastIndexOf("/"); - var typeId = typeLink.substring(n+1); - // Fetch the blueprint - $scope.ecdapp.isDataLoading = true; - InventoryBlueprintService.viewBlueprint(typeId).then(function(jsonObj) { - if (debug) - $log.debug("deployBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed'; - } - else { - $scope.ecdapp.typeName = jsonObj.typeName; - $scope.ecdapp.blueprint = jsonObj.blueprintTemplate; - } - $scope.ecdapp.isDataLoading = false; - }, function(error) { - $scope.ecdapp.isDataLoading = false; - alert('Failed to get blueprint. Please retry.'); - $log.error("blueprintViewCtrl failed: " + error); - }); -}); - -/*************************************************************************/ -appDS2.controller('inventoryDeploymentRollbackCtrl', function( - $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Deployment Rollback'; - $scope.ecdapp.revisions = []; - $scope.ecdapp.deploymentRef = message.deployment.deploymentRef; - $scope.ecdapp.serviceId = message.deployment.serviceId; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.updatingDeployment = false; - var selTenant = message.deployment.statusInfo.tenant_name; - if ( typeof selTenant === "undefined" ) { - selTenant = "default_tenant"; - } - $scope.ecdapp.tenant = selTenant; - $scope.ecdapp.ui_tenant = selTenant; - $scope.ecdapp.local_revisions = []; - // This object holds data for this operation - $scope.ecdapp.rollbackRequest = { - "deployment_id": message.deployment.deploymentRef, - "workflow_name": "rollback", - "tenant": selTenant, - "revision": 1 - }; - - InventoryDeploymentService.getNodeInstanceVersions($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(nodeRunTime) { - if (nodeRunTime == null) { - $scope.ecdapp.errMsg = "Failed to retrieve Node instance runtime information"; - $log.error("InventoryDeploymentSerice.getNodeInstanceVersions failed: " - + $scope.ecdapp.errMsg); - $scope.ecdapp.isRequestFailed = true; - } else { - $scope.ecdapp.errMsg = null; - $scope.ecdapp.revisions = nodeRunTime.items[0].runtime_properties['helm-history']; - if (Array.isArray($scope.ecdapp.revisions) ) { - var dLen = $scope.ecdapp.revisions.length; - - for (var i = 1; i < dLen; i++) { - var str = $scope.ecdapp.revisions[i].replace(/\s+/g, ' '); - var itemStrArr = str.split(" "); - var itemLen = itemStrArr.length; - var revObj = {}; - revObj.revision = itemStrArr[0].trim(); - revObj.updated = itemStrArr.slice(1,5).toString().replace(/,/g, ' '); - revObj.status = itemStrArr[6].trim(); - revObj.chart = itemStrArr[7].trim(); - revObj.description = itemStrArr.slice(8,itemLen).toString().replace(/,/g, ' '); - revObj.name = itemStrArr[0].trim(); - revObj.checked = false; - $scope.ecdapp.local_revisions.push(revObj); - } - } - console.log($scope.ecdapp.local_revisions); - $scope.ecdapp.isRequestFailed = false; - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error('InventoryDeploymentService.getNodeInstanceVersions failed: ' + JSON.stringify(error)); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.isDataLoading = false; - }); - $scope.ecdapp.updateSelection = function(position) { - $scope.ecdapp.rollbackRequest.revision = position; - angular.forEach($scope.ecdapp.local_revisions, function(item, index) { - if (position != index+1) - item.checked = false; - }); - } - /** - * rollback deployment based on parameters user enters/adjusts in modal popup - * First retrieves the node-id using the blueprintId - * Using the node-id and deploymentId, retrieves the node-instance-id - * Calls the update resource API, passing object with deploymentId, and changed parameters - */ - $scope.ecdapp.rollbackWorkflow = function(revision) { - $scope.ecdapp.updatingDeployment = true; - $scope.ecdapp.isDataLoading = true; - InventoryDeploymentService.rollbackFlow($scope.ecdapp.rollbackRequest).then(function(jsonObj) { - if (debug) - $log.debug("inventoryDeploymentRollbackCtrl.rollbackWorkflow response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; - $scope.ecdapp.updatingDeployment = false; - $scope.ecdapp.isDataLoading = false; - } else { - console.log('%c ROLLBACK RESOURCES COMPLETED', 'color: magenta; font-weight: bold;'); - alert('Rollback request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Rollback is now pending'); - $scope.ecdapp.updatingDeployment = false; - $scope.ecdapp.isDataLoading = false; - } - }, function(error) { - $scope.ecdapp.updatingDeployment = false; - $log.error('inventoryDeploymentRollbackCtrl failed: ' + error); - alert('Failed to rollback Deployment ' + $scope.ecdapp.deploymentRef + '. Please retry.'); - $scope.ecdapp.isDataLoading = false; - }); - } -}); - -/*************************************************************************/ -appDS2.controller('inventoryDeploymentUpgradeCtrl', function( - $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) { - - 'use strict'; - - // Controls logging in this controller - var debug = false; - - // this object holds all app data and functions - $scope.ecdapp = {}; - $scope.ecdapp.label = 'Deployment Upgrade'; - $scope.ecdapp.deployment = null; - $scope.ecdapp.deploymentRef = message.deployment.deploymentRef; //THIS IS THE BLUEPRINT ID - $scope.ecdapp.serviceId = message.deployment.serviceId; - $scope.ecdapp.errMsg = null; - $scope.ecdapp.isDataLoading = true; - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.updatingDeployment = false; - var selTenant = message.deployment.statusInfo.tenant_name; - if ( typeof selTenant === "undefined" ) { - selTenant = "default_tenant"; - } - $scope.ecdapp.tenant = selTenant; - $scope.ecdapp.ui_tenant = selTenant; - $scope.ecdapp.parmFileDict = {}; - - // This object holds data for editing the input parameters - $scope.ecdapp.editRequest = { - deployment_id: '', - type_id: '', - fileModel: null, - resourceConstants: {}, - resourceDefinitionChanges: {} - }; - //First get the blueprintId associated with the deployment, along with the inputs of the deployment - InventoryDeploymentService.getDeployment(message.deployment.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) { - if (deployment.items.length == 0) { - $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!"; - $log.error("InventoryDeploymentSerice.getDeployment failed: " - + $scope.ecdapp.errMsg); - $scope.ecdapp.isRequestFailed = true; - } - // Deployment IDs are unique, so this will always return exactly one item! - else { - $scope.ecdapp.errMsg = null; - $scope.ecdapp.deployment = deployment.items[0]; - $scope.ecdapp.isRequestFailed = false; - $scope.ecdapp.editRequest.type_id = deployment.items[0].blueprint_id; - $scope.ecdapp.parmFileDict = deployment.items[0].inputs; - Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) { - if (key == 'config-format' || key == 'config-url' || key == 'chart-version' || key == 'chart-repo-url') { - $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key]; - } else { - $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key]; - } - }); - } - $scope.ecdapp.isDataLoading = false; - }, - function(error) { - $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error)); - $scope.ecdapp.isRequestFailed = true; - $scope.ecdapp.errMsg = error; - $scope.ecdapp.isDataLoading = false; - }); - - /** - * Validates content of user-editable fields. - * Returns null if all is well, - * a descriptive error message otherwise. - */ - $scope.ecdapp.validateRequest = function(editRequest) { - if (editRequest == null) - return 'No data found.\nPlease enter some values.'; - if (editRequest["chart-version"] == null || editRequest["chart-version"].trim() == '') - return 'Chart version is required.\nPlease enter a value.'; - if (!editRequest["config-format"] || editRequest["config-format"].trim() == '') { - return 'config format is required.\nPlease enter a value.'; - } - if (!editRequest["config-url"] || editRequest["config-url"].trim() == '') { - return 'Config URL is required.\nPlease enter a value.'; - } - return null; - }; - - /** - * Helm upgrade for deployment based on parameters user enters in modal popup - * First retrieves the node-id using the blueprintId - * Using the node-id and deploymentId, retrieves the node-instance-id - * Calls the start execution API, passing object with deploymentId, and changed parameters - */ - - $scope.ecdapp.upgradeWorkflow = function(resourceDefinitionChanges) { - $scope.ecdapp.updatingDeployment = true; - let nodeId = ''; - - // validate request - var validateMsg = $scope.ecdapp.validateRequest(resourceDefinitionChanges); - if (validateMsg != null) { - alert('Invalid Request:\n' + validateMsg); - $scope.ecdapp.updatingDeployment = false; - return; - } - //get node id from blueprint - InventoryDeploymentService.getBlueprint($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(blueprint) { - if (debug) - $log.debug("inventoryDeploymentUpgradeCtrl.getBlueprint response: " + JSON.stringify(blueprint)); - if (blueprint.error) { - $scope.ecdapp.errMsg = 'Request Failed: ' + blueprint.error; - $scope.ecdapp.updatingDeployment = false; - } - else { - //console.log('returned blueprint:' + blueprint); - let count = 0; - //console.log("number of node objects in array: " + blueprint.items[0].plan.nodes.length); - //console.log(JSON.stringify(blueprint)); - blueprint.items[0].plan.nodes.map(function(node) { - if (node.type == 'onap.nodes.component') { - //want to get FIRST node with type 'cloudify.kubernetes.resources.Deployment' so only set nodeID for first matching type - if (count < 1) { - nodeId = node.id; - } - count = count + 1; - } - }); - //if no node has type 'cloudify.kubernetes.resources.Deployment', return message saying no deployment exists and exit (ie nodeId still is '') - if (nodeId == '') { - alert('Failed to retrieve Node Id. No matching deployment found (no deployment exists)'); - $scope.ecdapp.updatingDeployment = false; - return; - } - //found node id. now need to retrieve node-instance-id - console.log('%c RETRIEVED NODE ID: ' + nodeId, 'color: orange; font-weight: bold;'); - let nodeInstanceId = ''; - InventoryDeploymentService.getNodeInstanceId($scope.ecdapp.deploymentRef, nodeId, $scope.ecdapp.tenant).then(function(jsonObj) { - if (debug) - $log.debug("inventoryDeploymentUpgradeCtrl.getNodeInstanceId response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; - $scope.ecdapp.updatingDeployment = false; - } - else { - //if nodeInstanceId is still '' then it wasn't found, stop flow) - if (jsonObj.items[0].id == '') { - alert('Failed to retrieve Node Instance Id for Node Id' + nodeId); - $scope.ecdapp.updatingDeployment = false; - return; - } - //found node-instance-id. now need to update resources - nodeInstanceId = jsonObj.items[0].id; - console.log('%c RETRIEVED NODE INSTANCE ID:' + nodeInstanceId, 'color: green; font-weight: bold;'); - //console.log(resourceDefinitionChanges); - InventoryDeploymentService.upgradeFlow($scope.ecdapp.deploymentRef, nodeInstanceId, resourceDefinitionChanges, $scope.ecdapp.tenant).then(function(jsonObj) { - if (debug) - $log.debug("inventoryDeploymentUpgradeCtrl.updateResources response: " + JSON.stringify(jsonObj)); - if (jsonObj.error) { - $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error; - $scope.ecdapp.updatingDeployment = false; - } - else { - console.log('%c UPDATE RESOURCES COMPLETED', 'color: magenta; font-weight: bold;'); - //console.log(jsonObj); - $scope.ecdapp.updatingDeployment = false; - alert('Helm Upgrade request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Upgrade is now pending'); $modalInstance.dismiss('cancel'); - } - }, function(error) { - $scope.ecdapp.updatingDeployment = false; - alert('Failed to perform upgrade for Deployment Id ' + $scope.ecdapp.deploymentRef + ' and Node Instance Id ' + nodeInstanceId + '. Please retry.'); - $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error); - }); - } - }, function(error) { - $scope.ecdapp.updatingDeployment = false; - alert('Failed to get Node Instance Id for deploymentId ' + $scope.ecdapp.deploymentRef + ' and Node Id ' + nodeId + '. Please retry.'); - $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error); - }); - - } - }, function(error) { - $scope.ecdapp.updatingDeployment = false; - alert('Failed to get blueprint for blueprintId ' + $scope.ecdapp.deploymentRef + '. Please retry.'); - $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error); - }); - }; - - /** - * Handler for file-read event reads file, parses JSON, validates content. - */ - - var fileReader = new FileReader(); - fileReader.onload = function(event) { - let jsonString = fileReader.result; - if (debug) - $log.debug('fileReader.onload: read: ' + jsonString); - let ydict = {}; - try { - ydict = JSON.parse(jsonString); - } - catch (ex) { - alert('Failed to parse file as JSON:\n' + ex); - } - // Process the file - for (var ykey in ydict) { - let yval = ydict[ykey]; - if (debug) - $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey); - // Allow only expected keys with scalar values - if (! (ykey in $scope.ecdapp.parmFileDict)) - alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey); - if (yval.constructor === {}.constructor) - $scope.ecdapp.parmFileDict[ykey] = angular.toJson(yval); - else - $scope.ecdapp.parmFileDict[ykey] = yval; - } - if (debug) - $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.parmFileDict)); - - // Update table in all cases - //$scope.ecdapp.setResourceDefinitionChanges($scope.ecdapp.editRequest.resourceDefinitionChanges, $scope.ecdapp.editRequest.parmFileDict); - Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) { - if (key == 'config-format' || key == 'config-url' || key == 'chart-version') { - $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key]; - } else { - $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key]; - } - }); - //$scope.$apply(); - }; - - // Handler for file-select event - $scope.handleFileSelect = function() { - if (debug) - $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name); - fileReader.readAsText($scope.ecdapp.editRequest.fileModel); - }; - -});
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-service.js index 3fa2b2c..7b7a177 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-service.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-service.js @@ -4,7 +4,7 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) { * Gets one page of objects. * @param {Number} pageNum - page number; e.g., 1 * @param {Number} viewPerPage - number of items per page; e.g., 25 - * @return {JSON} Response object from remote side + * @return {JSON} Response object from remote side. */ getDeployments: function(pageNum,viewPerPage,sortBy,searchBy) { // cache control for IE @@ -17,7 +17,7 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) { } else if (searchBy) { url = 'inventory/dcae-services?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&searchBy=' + searchBy + cc; } else { - url = url = 'inventory/dcae-services?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc; + url = 'inventory/dcae-services?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc; } return $http({ method: 'GET', @@ -35,6 +35,94 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) { return $q.reject(error.statusText); }); }, + getDeploymentsAafFilter: function(pageNum,viewPerPage,aafUsername) { + // cache control for IE + let cc = "&cc=" + new Date().getTime().toString(); + let url = null; + + url = 'filtered-deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&inputKey=aaf_username' + '&inputValue=' + aafUsername + cc; + + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryDeploymentService.getDeploymentsAafFilter: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeploymentsAafFilter failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getDeploymentsDcaeTargetTypeFilter: function(pageNum,viewPerPage,dcaeTargetType) { + // cache control for IE + let cc = "&cc=" + new Date().getTime().toString(); + let url = null; + + url = 'filtered-deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&inputKey=dcae_target_type' + '&inputValue=' + dcaeTargetType + cc; + + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryDeploymentService.getDeploymentsDcaeTargetTypeFilter: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeploymentsDcaeTargetTypeFilter failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getDeploymentCount: function(searchBy) { + let url = 'service-list-count'; + if (searchBy) { + url = url + '?searchBy=' + searchBy; + } + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryDeploymentService.getDeploymentList: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeploymentList failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getDeploymentList: function(searchBy) { + let url = 'service-list'; + if (searchBy) { + url = url + '?searchBy=' + searchBy; + } + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryDeploymentService.getDeploymentList: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryDeploymentService.getDeploymentList failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, getDeploymentStatus: function(srvcIds) { let url = 'deployment-status'; return $http({ @@ -128,6 +216,26 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) { return $q.reject(error.statusText); }); }, + deleteBlueprint: function(blueprintId, tenant) { + let url = 'blueprints/' + blueprintId + '?tenant=' + tenant; + return $http({ + method: 'DELETE', + url: url, + responseType: 'json' + }).then(function(response) { + if (response.data == null) + return $q.reject('InventoryDeploymentService.deleteBlueprint: response.data null or not object'); + else { + console.log('%c DELETE BLUEPRINT FOR ID ' + blueprintId, 'color: blue; font-weight: bold;'); + console.log(response.data); + return response.data; + } + }, + function(error) { + $log.error('InventoryDeploymentService.deleteBlueprint failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, getBlueprint: function(blueprintId, tenant) { let url = 'blueprints/' + blueprintId + '?tenant=' + tenant; //console.log("url: " + url); @@ -191,6 +299,46 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) { return $q.reject(error.statusText); }); }, + getNodeInstances: function(deploymentId, tenant) { + console.log("entered getNodeInstances service function"); + let url = 'node-instances/' + deploymentId + '?tenant=' + tenant; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null) + return $q.reject('InventoryDeploymentService.getNodeInstances: response.data null or not object'); + else { + return response.data; + } + }, + function(error) { + $log.error('InventoryDeploymentService.getNodeInstances failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getNodeInstanceData: function(deploymentId, tenant) { + console.log("entered getNodeInstanceData service function"); + let url = 'node-instances-data?deployment=' + deploymentId + '&tenant=' + tenant; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null) + return $q.reject('InventoryDeploymentService.getNodeInstanceData: response.data null or not object'); + else { + return response.data; + } + }, + function(error) { + $log.error('InventoryDeploymentService.getNodeInstances failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, updateResources: function(deploymentId, nodeInstanceId, resource_definition_changes) { let body = { "deployment_id": deploymentId, @@ -291,6 +439,7 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) { let configFormat = resource_definition_changes["config-format"]; let chartUrl = resource_definition_changes["chart-repo-url"]; let chartVersion = resource_definition_changes["chart-version"]; + let configSet = resource_definition_changes["config-set"]; let body = { "deployment_id": deploymentId, "workflow_id": "upgrade", @@ -298,11 +447,12 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) { "force": true, "tenant": tenant, "parameters": { + "config_set": configSet, "node_instance_id": nodeInstanceId, + "chart_version": chartVersion, + "chart_repo_url": chartUrl, "config_url": configUrl, - "config_format": configFormat, - "chartRepo": chartUrl, - "chartVersion": chartVersion + "config_format": configFormat } }; let urlStr = 'executions'; diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/execution-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/execution-service.js index a4181f4..a756a2b 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/execution-service.js +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/execution-service.js @@ -6,6 +6,64 @@ appDS2.factory('InventoryExecutionService', function ($http, $q, $log) { * @param {Number} viewPerPage - number of items per page; e.g., 25 * @return {JSON} Response object from remote side */ + getActiveExecutions: function(pageNum, viewPerPage) { + let cc = "&cc=" + new Date().getTime().toString(); + let url = 'executions/active?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryExecutionService.getActiveExecutions: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryExecutionService.getActiveExecutions failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getExecutionsById: function(id, tenant, pageNum, viewPerPage) { + let cc = "&cc=" + new Date().getTime().toString(); + let url = 'executions/'+ id + '?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&tenant=' + tenant + '&status=' + status + cc; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryExecutionService.getExecutionsById: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryExecutionService.getExecutionsById failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, + getExecutionsByTenant: function(tenant, status, pageNum, viewPerPage) { + // cache control for IE + let cc = "&cc=" + new Date().getTime().toString(); + let url = 'executions/tenant?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&tenant=' + tenant + '&status=' + status + cc; + return $http({ + method: 'GET', + url: url, + cache: false, + responseType: 'json' + }).then(function(response) { + if (response.data == null || typeof response.data != 'object') + return $q.reject('InventoryExecutionService.getExecutionsByTenant: response.data null or not object'); + else + return response.data; + }, + function(error) { + $log.error('InventoryExecutionService.getExecutionsByTenant failed: ' + JSON.stringify(error)); + return $q.reject(error.statusText); + }); + }, getExecutionsByDeployment: function(deploymentId, tenant, pageNum, viewPerPage) { // cache control for IE let cc = "&cc=" + new Date().getTime().toString(); diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_popups.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_popups.html index eed1dfe..d17c065 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_popups.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_popups.html @@ -1,5 +1,5 @@ <script type="text/ng-template" - id="inventory_blueprint_update_popup.html"> + id="inventory_blueprint_update_popup.html"> <style> .ecd-parameter-table @@ -30,6 +30,13 @@ Blueprint <span style="font-weight: bolder;background: aqua;">{{ecdapp.serviceType.typeName}}</span> upload is in progress... </div> </div> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom:20px;"> + <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> + Please wait while the content loads. + </div> + </div> <form name="updateForm"> <div class="row-nowrap" style="margin-top:-20px;"> <div class="span4 form-row"> @@ -89,9 +96,9 @@ <div class="span6 form-row"> <label class="span12" for="typeName">*Blueprint Version</label> <div class="field-group tooltip-onclick" b2b-tooltip> - <input type="text" id="typeVer" name="typeVer" class="span12" data-ng-model="ecdapp.serviceType.typeVersion" disabled="disabled"> + <input type="text" id="typeVer" name="typeVer" class="span12" data-ng-model="ecdapp.serviceType.typeVersion"> <button class="reset-field" type="button" aria-label="Reset text field"></button> - <button id="tooltipButton3" class="btn icon-content-listguide tooltip-element icon-tooltip" data-toggle="button" aria-label="Email help" aria-describedby="tooltipContent4" > + <button id="tooltipButton33" class="btn icon-content-listguide tooltip-element icon-tooltip" data-toggle="button" aria-label="Email help" aria-describedby="tooltipContent4" > </button> <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent4"> <div class="popover-title">Blueprint or Type version - a required input</div> @@ -140,7 +147,7 @@ </div> <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> + <div ng-hide="ecdapp.updateInProgress" class="cta-button-group in"> <button class="btn btn-alt btn-small" type="submit" ng-disabled="updateForm.$invalid" ng-click="ecdapp.updateBlueprint(ecdapp.serviceType);"> Save @@ -153,9 +160,8 @@ </div> </script> - <script type="text/ng-template" - id="inventory_blueprint_upload_popup.html"> + id="inventory_blueprint_upload_popup.html"> <style> .ecd-parameter-table @@ -218,7 +224,7 @@ </div> </div> <form name="uploadForm"> - <div class="row-nowrap" style="margin-top:-20px;" ng-show="ecdapp.isImport"> + <div class="row-nowrap" style="margin-top:-20px;" ng-show="ecdapp.isImport && ecdapp.isInternal"> <div class="span3 form-row" ng-class="{'error':uploadForm.appl.$touched && !ecdapp.validAppl}"> <div class="tooltip" b2b-tooltip trigger="focus"> <a href="javascript:void(0)" class="tooltip-element" data-placement="bottom" role="button" aria-label="Help" aria-describedby="tooltiptext1" > @@ -302,7 +308,7 @@ </div> </div> </div> - <div class="row-nowrap" style="margin-top:-20px;" ng-hide="ecdapp.isImport"> + <div class="row-nowrap" style="margin-top:-20px;" ng-show="!ecdapp.isImport && ecdapp.isInternal"> <div class="span3 form-row" ng-class="{'error':uploadForm.appl.$touched && !ecdapp.validAppl}"> <div class="tooltip" b2b-tooltip trigger="focus"> <a href="javascript:void(0)" class="tooltip-element" data-placement="bottom" role="button" aria-label="Help" aria-describedby="tooltiptext1" > @@ -322,7 +328,8 @@ </div> </div> <div class="field-group"> - <select id="appl" name="appl" b2b-dropdown placeholder-text="Select Application" class="span8" data-ng-model="ecdapp.serviceTypeRequest.application" ng-change="ecdapp.selectAppComp(ecdapp.serviceTypeRequest.application)" required> + <select id="appl" name="appl" b2b-dropdown placeholder-text="Select Application" + class="span8" data-ng-model="ecdapp.serviceTypeRequest.application" ng-change="ecdapp.selectAppComp(ecdapp.serviceTypeRequest.application)" required> <option b2b-dropdown-list option-repeat="d in ecdapp.apps" value="{{d}}">{{d}}</option> </select> </div> @@ -356,7 +363,11 @@ </div> </div> <div class="field-group"> - <select b2b-dropdown name="comp" class="span8" placeholder-text="Select Component" data-ng-model="ecdapp.serviceTypeRequest.component" ng-change="ecdapp.validateComp()" ng-disabled="!ecdapp.validAppl" required> + + <select b2b-dropdown name="comp" class="span8" placeholder-text="Select Component" + data-ng-init="ecdapp.serviceTypeRequest.component" + data-ng-model="ecdapp.serviceTypeRequest.component" ng-change="ecdapp.validateComp()" + ng-disabled="!ecdapp.validAppl" required> <option b2b-dropdown-list option-repeat="d in ecdapp.comps" value="{{d.cname}}">{{d.dname}}</option> </select> </div> @@ -396,56 +407,13 @@ </div> </div> </div> - <div class="row-nowrap" ng-hide="ecdapp.isImport"> - <div id="addAppDiv" class="span12 row-nowrap" ng-show="ecdapp.enableAppForm"> - <div class="span4 form-row"> - <label>*Component Name</label> - <div class="field-group tooltip-onclick" b2b-tooltip> - <input type="text" class="span12" data-ng-model="ecdapp.newCompName" placeholder="Example: scheduler"> - <button class="reset-field" type="button" aria-label="Reset text field"></button> - <button id="tooltipButton1" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Comp Name" aria-describedby="tooltipContent1" > - </button> - <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent1"> - <div class="popover-title">Component name - a required input</div> - <div class="popover-content"> - <p>Component name is a sub-string of the application namespace in AAF. A non-admin user should only add a new component if that user's role belongs to the component namespace.</p> - <strong class="hidden-spoken">Double tap to close help message.</strong> - </div> - </div> - </div> - </div> - <div class="span4 form-row"> - <label>*Component Display Name</label> - <div class="field-group tooltip-onclick" b2b-tooltip> - <input type="text" class="span12" data-ng-model="ecdapp.newCompDisplayName" placeholder="Example: ECOMP SCHEDULER" style="text-transform:uppercase"> - <button class="reset-field" type="button" aria-label="Reset text field"></button> - <button id="tooltipButton2" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help" aria-describedby="tooltipContent2" > - </button> - <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent2"> - <div class="popover-title">Component Display Name - a required input</div> - <div class="popover-content"> - <p>Component display name in selection menu</p> - <strong class="hidden-spoken">Double tap to close help message.</strong> - </div> - </div> - </div> - </div> - <div class="span1 form-row"> - <label></label> - <div class="field-group" ng-click="ecdapp.addApplication(ecdapp.serviceTypeRequest.application, ecdapp.newCompId, - ecdapp.newCompName, ecdapp.newCompDisplayName);"> - <a href="" title="Add Component" class="icon-arrows-quick-sync ecd-icon-action"></a> - </div> - </div> - </div> - </div> <div class="row-nowrap"> <div class="span6 form-row" ng-class="{'error':uploadForm.typeName.$touched && uploadForm.typeName.$invalid}"> <label class="span12" for="typeName">*Blueprint Name</label> <div class="field-group tooltip-onclick" b2b-tooltip> <input type="text" id="typeName" name="typeName" class="span12" data-ng-model="ecdapp.serviceTypeRequest.typeName" placeholder="Example: mso_helm_chart" required> <button class="reset-field" type="button" aria-label="Reset text field"></button> - <button id="tooltipButton3" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help" aria-describedby="tooltipContent3" > + <button id="tooltipButton35" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help" aria-describedby="tooltipContent3" > </button> <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent3"> <div class="popover-title">Blueprint or Type name - a required input</div> @@ -465,12 +433,12 @@ <div class="field-group tooltip-onclick" b2b-tooltip> <input type="text" id="typeVer" name="typeVer" class="span12" data-ng-model="ecdapp.serviceTypeRequest.typeVersion" placeholder="Example: 181017" required> <button class="reset-field" type="button" aria-label="Reset text field"></button> - <button id="tooltipButton3" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help" aria-describedby="tooltipContent4" > + <button id="tooltipButton41" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help" aria-describedby="tooltipContent4" > </button> <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent4"> <div class="popover-title">Blueprint or Type version - a required input</div> <div class="popover-content"> - <p>Blueprint or Service Type version may be an integer, example: 10, 181017 or a semantic version string, example: 1902.01.03. Semantic version string is converted to an integer by removing "...", before inserting into inventory. This field is used to identify the blueprint template version or a component package version.</p> + <p>Blueprint or Service Type version should be an integer. This field is used to identify the blueprint template version or a component package version.</p> <strong class="hidden-spoken">Double tap to close help message.</strong> </div> </div> @@ -523,8 +491,12 @@ </div> <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="submit" ng-disabled="uploadForm.$invalid || !ecdapp.validAppl || !ecdapp.validComp" + <div ng-hide="ecdapp.uploadInProgress" class="cta-button-group in"> + <button class="btn btn-alt btn-small" type="submit" ng-show="ecdapp.isInternal" ng-disabled="uploadForm.$invalid || !ecdapp.validAppl || !ecdapp.validComp" + ng-click="ecdapp.uploadBlueprint(ecdapp.serviceTypeRequest);"> + Save + </button> + <button class="btn btn-alt btn-small" type="submit" ng-show="!ecdapp.isInternal" ng-disabled="uploadForm.$invalid" ng-click="ecdapp.uploadBlueprint(ecdapp.serviceTypeRequest);"> Save </button> @@ -535,7 +507,6 @@ </div> </div> </script> - <script type="text/ng-template" id="inventory_blueprint_view_popup.html"> <div class="b2b-modal-header ng-scope"> @@ -577,9 +548,8 @@ </div> </script> - <script type="text/ng-template" - id="inventory_blueprint_deploy_popup.html"> + id="inventory_blueprint_deploy_popup.html"> <style> .ecd-parameter-table @@ -685,7 +655,7 @@ </div> </div> <select id="cldTenants" name="tenant" b2b-dropdown placeholder-text="Select Tenant" class="span8" data-ng-model="ecdapp.editRequest.tenant" ng-change="ecdapp.validateTenant()"> - <option b2b-dropdown-list option-repeat="d in tenantList.data" value="{{d.name}}">{{d.name}}</option> + <option b2b-dropdown-list option-repeat="d in ecdapp.availableTenants" value="{{d}}">{{d}}</option> </select> <div ng-if="deployForm.tenant.$touched && !ecdapp.validTenant" id="tenantDropdown" role="alert" class="error-msg" aria-live="polite" aria-atomic="true" > <i class="icon-badgealert" aria-hidden="true"></i> @@ -710,7 +680,7 @@ </div> </div> - <div ng-hide="ecdapp.deploymentInProgress" class="row-nowrap"> + <div ng-hide="ecdapp.isDataLoading" class="row-nowrap"> <div class="span12"> <div class="form-row"> <label for="parameters">*Parameters</label> @@ -723,13 +693,17 @@ <div class="ecd-parameter-table"> <table id="parameters"> <tr id="ecd-table-header"> - <th width="60%">Name</th> - <th width="40%">Value</th> + <th width="30%">Name</th> + <!--<th width="40%">Description</th>--> + <th width="70%">Value</th> </tr> <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict"> <tr id="tr-rowData"> - <td ng-bind="pkey"/> - <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td> + <td> + <div style="font-weight: bold;">{{pkey}}</div> + <div style="margin-top: 8px; font-weight: lighter;">{{ecdapp.editRequest.descriptionDict[pkey]}}</div> + </td> + <td><input json id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td> </tr> </tbody> </table> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_table.html index 763d956..044db14 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_table.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_table.html @@ -1,177 +1,297 @@ <div id="page-content"> - - <h1 class="heading-page" id="blueprints">Blueprints</h1> - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-hide="ecdapp.isDataLoading"> - <div id="button-search-row"> - <span class="tooltip" b2b-tooltip> - <a href="#" class="btn btn-alt btn-small tooltip-element" tabindex="0" role="button" data-placement="bottom" - aria-label="Help" ng-click="ecdapp.uploadBlueprintModalPopup()" aria-describedby="tooltiptextBtn"> - Create - <span class="arrow"></span> - </a> - <span class="tooltip-wrapper"> - <span class="tooltip-size-control"> - <span id="tooltiptextBtn" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1"> - <span class="popover-title">Upload a blueprint</span> - <span class="popover-content"> - <span>Click to open up a FORM to upload and create a new blueprint in inventory.</span> - <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong> - </span> - </span> - </span> - </span> + <h1 class="heading-page" id="blueprint-page">Blueprints</h1> + + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-hide="ecdapp.isDataLoading" style="margin-bottom: 20px;"> + <span class="tooltip" b2b-tooltip> <a href="#" + class="btn btn-alt btn-small tooltip-element" tabindex="0" + role="button" data-placement="bottom" aria-label="Help" + ng-click="ecdapp.uploadBlueprintModalPopup()" + aria-describedby="tooltiptextBtn"> Upload <span class="arrow"></span> + </a> <span class="tooltip-wrapper"> <span + class="tooltip-size-control"> <span id="tooltiptextBtn" + role="tooltip" aria-live="polite" aria-hidden="true" + class="helpertext" tabindex="-1"> <span + class="popover-title">Upload a blueprint</span> <span + class="popover-content"> <span>Click to open + up a FORM to upload and create a new blueprint in + inventory.</span> <strong class="hidden-spoken hidden-desktop">Double + tap to close help message.</strong> + </span> + </span> + </span> </span> - <div style="float:right;"> - <div class="group"> - <button tabindex="-1" class="btn btn-small" title="Reset Filters" type="button" ng-click="ecdapp.loadTable()"><i class="icon-arrows-replay-restart"></i></button> - <input tabindex="0" class="btn btn-small" type="text" placeholder="Search Blueprints" ng-model="ecdapp.searchBy"></input> - <button tabindex="1" class="btn btn-small" title="Search" type="button" ng-click="ecdapp.searchTable(ecdapp.searchBy)"><i class="ion-search"></i></button> - </div> - </div> - </div> - - <div ng-show="ecdapp.isRequestFailed"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.isRequestFailed"> - - <div - b2b-table - id="blueprints-table" - class="b2b-table-div" - table-data="ecdapp.tableData" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - - <table> - - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th id="expandTableHeading0" b2b-table-header sortable="false" key="application" ng-click="ecdapp.sortTable('application')">Application</th> - <th b2b-table-header sortable="false" key="component" ng-click="ecdapp.sortTable('component')">Component</th> - <th b2b-table-header sortable="false" key="type_name" ng-click="ecdapp.sortTable('typeName')">Name</th> - <th b2b-table-header sortable="false" key="type_version" ng-click="ecdapp.sortTable('typeVersion')">Version</th> - <th b2b-table-header sortable="false" key="created_at" ng-click="ecdapp.sortTable('created')">Created Date</th> - <th b2b-table-header sortable="false" key="deployment_ref">Deployments - <button style="margin-bottom:-5px; box-shadow:0 0 0 0 rgba(0, 0, 0, 0.15); min-width:0;" tabindex="1" class="btn btn-small" title="Refresh Deployments" type="button" ng-click="ecdapp.updateTable()"> - <i class="icon-arrows-replay-restart"></i> - </button> - <div ng-show="ecdapp.isSrvcDataLoading"> - <div class="span" style="margin-bottom:5px;"> - <i class="icon-spinner small" role="img" aria-label="Deployment Info is loading"></i> - Deployment Info is loading - </div> - </div> - </th> - <th b2b-table-header sortable="false">Actions</th> - <th b2b-table-header sortable="false" key="owner" ng-click="ecdapp.sortTable('owner')">Owner</th> - <th b2b-table-header sortable="false" key="type_id" ng-click="ecdapp.sortTable('typeId')">ID</th> - </tr> - </thead> - - <tbody b2b-table-row type="body" ng-repeat="rowData in ecdapp.tableData"> - <tr id="tr-rowData{{index}}" tabindex="0"> - <td b2b-table-body id="expandTable_t1_{{$index}}" headers="expandTableHeading0" - ng-bind="rowData.application"/> - <td b2b-table-body - ng-bind="rowData.component" /> - <td b2b-table-body - ng-bind="rowData.typeName" /> - <td b2b-table-body - ng-bind="rowData.typeVersion" /> - <td b2b-table-body - ng-bind="rowData.created | date : 'MM-dd-yyyy HH:mm:ss Z'" /> - <td b2b-table-body ng-class="{'b2b-td-noLeftBorder' : rowData.expanded}" style="padding-right:0px;"> - <span>{{rowData.deployments.totalCount}} - <i ng-if="rowData.deployments.totalCount != 0" class="pull-right" aria-label="{{rowData.expanded ? 'Collapse row ' + rowData.deployments : 'Expand row ' + rowData.deployments}}" - ng-class="{'icon-accordion-plus': !rowData.expanded, 'icon-accordion-minus' : rowData.expanded}" - ng-click="rowData.expanded=!rowData.expanded" b2b-accessibility-click="13,32" tabindex="0" role="button" aria-expanded="false" - title="click to view service information"></i> - </span> - </td> - <td b2b-table-body > - <div class="btn-group btn-actions" style="margin-bottom:0;box-shadow:none;"> - <button type="button" class="btn dropdown-toggle" data-toggle="dropdown" title="More Actions"><i class="icon-apps-marketplace"></i></button> - <ul class="dropdown-menu"> - <li> - <div ng-click="ecdapp.viewBlueprintModalPopup(rowData);"> - <i class="icon-documents-book ecd-icon-action"></i><a href="">View</a> - </div> - </li> - <li> - <div ng-click="ecdapp.exportJson(rowData);"> - <i class="icon-documents-copy ecd-icon-action"></i><a href="">Export</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy && rowData.deployments.totalCount === 0" ng-click="ecdapp.updateBlueprintModalPopup(rowData);"> - <i class="icon-misc-pen ecd-icon-action"></i><a href="">Update</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy" ng-click="ecdapp.deployBlueprintModalPopup(rowData);"> - <i class="icon-arrows-download ecd-icon-action"></i><a href="">Deploy</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy && rowData.deployments.totalCount === 0" ng-click="ecdapp.deleteBlueprintModalPopup(rowData);"> - <i class="icon-misc-trash ecd-icon-action"></i><a href="">Delete</a> - </div> - </li> - </ul> - </div><!-- .btn-group --> - </td> - <td b2b-table-body - ng-bind="rowData.owner" /> - <td b2b-table-body - ng-bind="rowData.typeId" /> - </tr> - <tr ng-show="rowData.expanded"> - <td colspan="6" class="b2b-td-noTopBorder" headers="expandTable_t1_{{$index}}"> - <p class="offscreen-text">Expanded Row details for {{rowData.deployments}}</p> - <ul> - <li class="mar-top-30" ng-repeat="srvcData in rowData.deployments.items"> - <div> <span class="font-medium">{{$index+1}}</span> </div> - <div class="b2b-leading-dots"> - <span class="font-medium">Deployment ID</span> - <!-- <span class="pull-right" ng-bind="srvcData.serviceId"><a href="ecd#/idep/{{srvcData.serviceId}}"></a></span>--> - <span class="pull-right"><a href="ecd#/idep/{{srvcData.serviceId}}">{{srvcData.serviceId}}</a></span> - </div> - <div class="b2b-leading-dots"> - <span class="font-medium">Created timestamp</span> - <span class="pull-right" ng-bind="srvcData.created | date : 'MM-dd-yyyy HH:mm:ss Z'"" /> - </div> - <div class="b2b-leading-dots"> - <span class="font-medium">Modified timestamp</span> - <span class="pull-right" ng-bind="srvcData.modified | date : 'MM-dd-yyyy HH:mm:ss Z'"" /> - </div> - </li> - <br> - </ul> - </td> - </tr> - </tbody> - </table> - </div> - - <div b2b-pagination="" total-pages="ecdapp.totalPages" - current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler" - role="navigation"> - </div> - - <div style="height: 10px;"> - <!-- space between page number and black footer --> - </div> - - </div><!-- loading --> - -</div><!-- page content --> + </span> + </div> + <div id="button-search-row" style="width: 60%; margin-left: 45px; float:right; margin-top: -30px;" + ng-hide="ecdapp.isDataLoading"> + <div> + <div class="group"> + <div class="advanced-search"> + <button tabindex="-1" + style="position: absolute; margin-left: -35px; border: none; background: none; top: 5px;" + "class="btn btn-small" title="show unfiltered view" + type="button" ng-click="ecdapp.reloadTable()"> + <i class="icon-arrows-replay-restart"></i> + </button> + <button tabindex="1" + style="position: absolute; border: none; background: none; margin-left: 5px; top: 5px;" + "class="btn btn-medium" type="button" + ng-click="ecdapp.filterBySvc()"> + <i class="ion-search"></i> + </button> + <input type="text" style="padding-left: 50px;" + class="advanced-search-input" + placeholder="Search Blueprints" + ng-model="ecdapp.searchString" + ng-keydown="[13, 32].includes($event.keyCode) && ecdapp.filterBySvc()"></input> + <button type="button" id="show-menu-filters" + class="btn dropdown-toggle" + ng-click="ecdapp.toggleMoreFilters()" + data-toggle="dropdown" title="More Filters"> + <i class="icon-controls-down"></i> + </button> + </div> + </div> + <div class="menu-filters" ng-show="ecdapp.showingMoreFilters"> + <div class="group"> + <label class="col-sm-3 control-label">Blueprints: </label> + <ui-select multiple ng-model="ecdapp.selectedBp" + theme="bootstrap" close-on-select="false" + title="Blueprint Name"> <ui-select-match + class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices + class="ui-select-choices" + repeat="bp in ecdapp.availableBp | filter:$select.search" + position='down'> {{bp}} </ui-select-choices> </ui-select> + </div> + <div class="group" ng-show="ecdapp.isInternal"> + <label class="col-sm-3 control-label">Applications: + </label> + <ui-select multiple ng-model="ecdapp.selectedApp" + theme="bootstrap" close-on-select="false" + title="Application"> <ui-select-match + class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices + class="ui-select-choices" + repeat="app in ecdapp.apps | filter:$select.search" + position='down'> {{app}} </ui-select-choices> </ui-select> + </div> + <div class="group" ng-show="ecdapp.isInternal"> + <label class="col-sm-3 control-label">Components: </label> + <ui-select multiple ng-model="ecdapp.selectedComp" + theme="bootstrap" close-on-select="false" + title="Component name"> <ui-select-match + class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices + class="ui-select-choices" + repeat="comp in ecdapp.availableComp | filter:$select.search" + position='down'> {{comp}} </ui-select-choices> </ui-select> + </div> + <div class="group" ng-hide="ecdapp.filterByUser"> + <label class="col-sm-3 control-label">Owners: </label> + <ui-select multiple ng-model="ecdapp.selectedOwner" + theme="bootstrap" close-on-select="false" + title="Blueprint owner"> <ui-select-match + class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices + class="ui-select-choices" + repeat="owner in ecdapp.bpOwners | filter:$select.search" + position='down'> {{owner}} </ui-select-choices> </ui-select> + </div> + <div class="group" style="float: right;"> + <button tabindex="-1" class="btn btn-small" + title="Reset Filters" type="button" + ng-click="ecdapp.resetFilters()"> + <i class="icon-arrows-replay-restart"></i> + </button> + <button tabindex="1" class="btn btn-small" + title="Filtered search" type="button" + ng-click="ecdapp.extendedfilterSrch()"> + <i class="ion-search"></i> + </button> + </div> + </div> + </div> + <div style="margin-left: 20px; margin-top: 10px;" title="Search filters"> + <label for="checkbox3" class="checkbox"> + <input id="checkbox3" type="checkbox" ng-model="ecdapp.filterByUser" ng-change="ecdapp.toggleUserFilt()" + class="ng-valid ng-dirty ng-valid-parse ng-touched"> + <i class="skin"></i><span>My Blueprints</span> + </label> + </div> + </div> + + <div ng-show="ecdapp.isRequestFailed"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-hide="ecdapp.isRequestFailed" > + <div b2b-table id="blueprints-table" class="b2b-table-div" + table-data="ecdapp.tableData" + current-page="ecdapp.currentPageIgnored" + next-sort="ecdapp.nextSortIgnored"> + <table> + <thead b2b-table-row type="header"> + <tr id="th-header-row"> + <th b2b-table-header sortable="false" key="type_name" + ng-click="ecdapp.sortTable('typeName')">Name</th> + <th b2b-table-header sortable="false" key="type_version" + ng-click="ecdapp.sortTable('typeVersion')">Version</th> + <th b2b-table-header sortable="false" key="created_at" + ng-click="ecdapp.sortTable('created')">Created Date</th> + <th b2b-table-header sortable="false" key="deployment_ref"> + <button style="margin-bottom: -10px;box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.15);min-width: 0;margin-left: -20px;" tabindex="1" class="btn btn-small ng-scope" title="Refresh Deployments" type="button" ng-click="ecdapp.updateTable()"> + <i class="icon-arrows-replay-restart"></i> + <span class="ng-scope">Deployments</span> + </button> + <div ng-show="ecdapp.isSrvcDataLoading" class="ng-scope ng-hide"> + <div class="span" style="margin-bottom: 5px;"> + <i class="icon-spinner small" role="img" aria-label="Deployment Info is loading"></i> + Deployment Info is loading + </div> + </div> + </th> + <th b2b-table-header sortable="false">Actions</th> + <th b2b-table-header sortable="false" key="component" + ng-click="ecdapp.sortTable('component')">Component</th> + <th b2b-table-header sortable="false" key="owner" + ng-click="ecdapp.sortTable('owner')">Owner</th> + <th b2b-table-header sortable="false" key="type_id" + ng-click="ecdapp.sortTable('typeId')">ID</th> + </tr> + </thead> + <tbody b2b-table-row type="body" + ng-repeat="rowData in ecdapp.tableData"> + <tr id="tr-rowData{{index}}" tabindex="0"> + <td b2b-table-body ng-bind="rowData.typeName" /> + <td b2b-table-body ng-bind="rowData.typeVersion" /> + <td b2b-table-body + ng-bind="rowData.created | date : 'MM-dd-yyyy HH:mm:ss Z'" /> + <td b2b-table-body ng-if="rowData.deployments == undefined"> + 0 + </td> + <td b2b-table-body ng-if="rowData.deployments" + ng-class="{'b2b-td-noLeftBorder' : rowData.expanded}" + style="padding-right: 0px;"><span>{{rowData.deployments.totalCount}} + <i ng-if="rowData.deployments && rowData.deployments.totalCount != 0" + class="pull-right" + aria-label="{{rowData.expanded ? 'Collapse row ' + rowData.deployments : 'Expand row ' + rowData.deployments}}" + ng-class="{'icon-accordion-plus': !rowData.expanded, 'icon-accordion-minus' : rowData.expanded}" + ng-click="rowData.expanded=!rowData.expanded" + b2b-accessibility-click="13,32" tabindex="0" + role="button" aria-expanded="false" + title="click to view service information"></i> + </span></td> + <td b2b-table-body> + <div class="btn-group btn-actions" + style="margin-bottom: 0; box-shadow: none;"> + <button type="button" class="btn dropdown-toggle" + data-toggle="dropdown" title="More Actions"> + <i class="icon-apps-marketplace"></i> + </button> + <ul class="dropdown-menu"> + <li> + <div + ng-click="ecdapp.viewBlueprintModalPopup(rowData);"> + <i class="icon-documents-book ecd-icon-action"></i><a + href="">View</a> + </div> + </li> + <li> + <div ng-click="ecdapp.exportJson(rowData);"> + <i class="icon-documents-copy ecd-icon-action"></i><a + href="">Export</a> + </div> + </li> + <li> + <div + ng-show="rowData.canDeploy && (rowData.deployments == undefined || rowData.deployments.totalCount === 0)" + ng-click="ecdapp.updateBlueprintModalPopup(rowData);"> + <i class="icon-misc-pen ecd-icon-action"></i><a + href="">Update</a> + </div> + </li> + <li> + <div ng-show="rowData.canDeploy" + ng-click="ecdapp.deployBlueprintModalPopup(rowData);"> + <i class="icon-arrows-download ecd-icon-action"></i><a + href="">Deploy</a> + </div> + </li> + <li> + <div + ng-show="rowData.canDeploy && (rowData.deployments == undefined || rowData.deployments.totalCount === 0)" + ng-click="ecdapp.deleteBlueprintModalPopup(rowData);"> + <i class="icon-misc-trash ecd-icon-action"></i><a + href="">Delete</a> + </div> + </li> + </ul> + </div> + <!-- .btn-group --> + </td> + <td b2b-table-body ng-bind="rowData.component" /> + <td b2b-table-body ng-bind="rowData.owner" /> + <td b2b-table-body ng-bind="rowData.typeId" /> + </tr> + <tr ng-show="rowData.expanded"> + <td colspan="6" class="b2b-td-noTopBorder" + headers="expandTable_t1_{{$index}}"> + <p class="offscreen-text">Expanded Row details for + {{rowData.deployments}}</p> + <ul> + <li class="mar-top-30" + ng-repeat="srvcData in rowData.deployments.items"> + <div> + <span class="font-medium">{{$index+1}}</span> + </div> + <div class="b2b-leading-dots" ng-show="srvcData.tenant_name.length > 0"> + <span class="font-medium">Deployment ID</span> + <span class="pull-right"> + <a href="ecd#/idep/tenant:{{srvcData.tenant_name}};serviceRef:{{srvcData.id}}"> + {{srvcData.id}} + </a> + </span> + </div> + <div class="b2b-leading-dots" ng-show="srvcData.tenant_name.length == 0"> + <span class="font-medium">Deployment ID</span> <span + class="pull-right" ng-bind="srvcData.id" /> + </div> + <div class="b2b-leading-dots" ng-show="srvcData.tenant_name.length > 0"> + <span class="font-medium">Cloudify Tenant</span> <span + class="pull-right" ng-bind="srvcData.tenant_name" /> + </div> + <div class="b2b-leading-dots"> + <span class="font-medium">Created timestamp</span> <span + class="pull-right" + ng-bind="srvcData.created_at | date : 'MM-dd-yyyy HH:mm:ss Z'" " /> + </div> + <div class="b2b-leading-dots"> + <span class="font-medium">Modified timestamp</span> + <span class="pull-right" + ng-bind="srvcData.updated_at | date : 'MM-dd-yyyy HH:mm:ss Z'" " /> + </div> + </li> + <br> + </ul> + </td> + </tr> + </tbody> + </table> + </div> + <div b2b-pagination="" total-pages="ecdapp.totalPages" + current-page="ecdapp.currentPage" + click-handler="pageChangeHandler" role="navigation"></div> + <div style="height: 10px;"> + <!-- space between page number and black footer --> + </div> + </div> + <!-- loading --> +</div> +<div style="height: 10px;"> + <!-- space between page number and black footer --> +</div> +<!-- page content --> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_popups.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_popups.html index e9bf3ea..41c3115 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_popups.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_popups.html @@ -1,657 +1,737 @@ <script type="text/ng-template" id="inventory_deployment_execute_popup.html"> - - <style> - .ecd-parameter-table - { - border: 0px; - overflow: auto; - } - .ecd-parameter-table th - { - font-size: 1.4rem; - } - </style> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="blueprintId">Deployment ID</label> - <div class="field-group"> - <!--autofocus is HTML5 attribute; doesn't work in Firefox--> - <input id="blueprintId" class="span12" type="text" data-ng-model="ecdapp.editRequest.deployment_id" autofocus/> - </div> - </div> - </div> - <div class="span12"> - <div class="form-row"> - <label for="allowCustom"> </label> - <div class="field-group"> - <label for="allowCustomParameters" class="checkbox"> - <input id="allowCustomParameters" type="checkbox" ng-model="ecdapp.editRequest.allow_custom_parameter" /> - <i class="skin"></i><span>Allow Custom Parameters</span> - </label> - </div> - </div> - </div> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="workflowName">Workflow Name</label> - <div class="field-group"> - <select b2b-dropdown id="workflowName" name="workflowName" ng-model="ecdapp.editRequest.workflow_name.value" ng-change="selectWorkflowName()"> - <option b2b-dropdown-list option-repeat="w in ecdapp.editRequest.workflow_list" value="{{w}}"> - {{w}} - </option> - </select> - </div> - </div> - </div> - <div class="span12"> - <div class="form-row"> - <label for="force"> </label> - <div class="field-group"> - <label for="force" class="checkbox"> - <input id="force" type="checkbox" ng-model="ecdapp.editRequest.force" /> - <i class="skin"></i><span>Force</span> - </label> - </div> - </div> - </div> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="parameters">*Parameters</label> - <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center"> - <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" > - Drag & drop a parameters YAML file here, or click to browse. - </span> - </div> - </div> - <div class="ecd-parameter-table"> - <table id="parameters"> - <tr id="ecd-table-header"> - <th width="40%">Name</th> - <th width="60%">Value</th> - </tr> - <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict"> - <tr id="tr-rowData"> - <td ng-bind="pkey"/> - <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td> - </tr> - </tbody> - </table> - </div> - </div> - </div> - - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.executeDeployment(ecdapp.editRequest);"> - Save - </button> - <button class="btn btn-small" type="button" - ng-click="$dismiss('cancel')"> - Cancel - </button> - </div> - </div> - +<style> +.ecd-parameter-table { + border: 0px; + overflow: auto; +} + +.ecd-parameter-table th { + font-size: 1.4rem; +} +</style> +<div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> +</div> +<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <div class="row-nowrap"> + <div class="span12"> + <div class="form-row"> + <label for="blueprintId">Deployment ID</label> + <div class="field-group"> + <!--autofocus is HTML5 attribute; doesn't work in Firefox--> + <input id="blueprintId" class="span12" type="text" + data-ng-model="ecdapp.editRequest.deployment_id" autofocus /> + </div> + </div> + </div> + <div class="span12"> + <div class="form-row"> + <label for="allowCustom"> </label> + <div class="field-group"> + <label for="allowCustomParameters" class="checkbox"> <input + id="allowCustomParameters" type="checkbox" + ng-model="ecdapp.editRequest.allow_custom_parameter" /> <i + class="skin"></i><span>Allow Custom Parameters</span> + </label> + </div> + </div> + </div> + </div> + <div class="row-nowrap"> + <div class="span12"> + <div class="form-row"> + <label for="workflowName">Workflow Name</label> + <div class="field-group"> + <select b2b-dropdown id="workflowName" name="workflowName" + ng-model="ecdapp.editRequest.workflow_name.value" + ng-change="selectWorkflowName()"> + <option b2b-dropdown-list + option-repeat="w in ecdapp.editRequest.workflow_list" + value="{{w}}">{{w}}</option> + </select> + </div> + </div> + </div> + <div class="span12"> + <div class="form-row"> + <label for="force"> </label> + <div class="field-group"> + <label for="force" class="checkbox"> <input id="force" + type="checkbox" ng-model="ecdapp.editRequest.force" /> <i + class="skin"></i><span>Force</span> + </label> + </div> + </div> + </div> + </div> + <div class="row-nowrap"> + <div class="span12"> + <div class="form-row"> + <label for="parameters">*Parameters</label> + <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" + on-drop="handleFileSelect()" align="center"> + <span b2b-file-link file-model="ecdapp.editRequest.fileModel" + on-file-select="handleFileSelect()"> Drag & drop + a parameters YAML file here, or click to browse. </span> + </div> + </div> + <div class="ecd-parameter-table"> + <table id="parameters"> + <tr id="ecd-table-header"> + <th width="40%">Name</th> + <th width="60%">Value</th> + </tr> + <tbody + ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict"> + <tr id="tr-rowData"> + <td ng-bind="pkey" /> + <td><input id="parameterValue" class="span12" + type="text" + data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" + autofocus /></td> + </tr> + </tbody> + </table> + </div> + </div> + </div> +</div> +<div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <div class="cta-button-group in"> + <button class="btn btn-alt btn-small" type="button" + ng-click="ecdapp.executeDeployment(ecdapp.editRequest);"> + Save</button> + <button class="btn btn-small" type="button" + ng-click="$dismiss('cancel')">Cancel</button> + </div> +</div> </script> - -<script type="text/ng-template" id="inventory_deployment_delete_popup.html"> - - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div ng-hide="ecdapp.errMsg"> - <div class="row-nowrap" style="margin-bottom:10px; margin-left:10px;""> - <div class="span6"> - <label for="tenant">Tenant</label> - <!--not editable--> - <input id="tenant" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/> - </div> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <div class="span12"> - <div class="form-row"> - <div class="field-group"> - <label> - Undeploy the deployment with ID '{{ecdapp.deploymentRef}}'? - </label> - </div> - </div> - </div> - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.deleteDeploymentById(deployment);"> - Undeploy - </button> - <button class="btn btn-small" type="button" - ng-click="$dismiss('cancel')"> - Cancel - </button> - </div> - </div> - +<script type="text/ng-template" + id="inventory_deployment_delete_popup.html"> +<div class="b2b-modal-header ng-scope"> + <h3 id="myModalLabel" modal-title=""> + {{ecdapp.label}} + </h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> +</div> +<div ng-hide="ecdapp.errMsg"> + <div class="row-nowrap" + style="margin-bottom: 10px; margin-left: 10px;""> + <div class="span6"> + <label for="tenant">Tenant</label> + <!--not editable--> + <input id="tenant" class="span12" type="text" disabled="disabled" + data-ng-model="ecdapp.ui_tenant" /> + </div> + </div> +</div> +<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <div class="span12"> + <div class="form-row"> + <div class="field-group"> + <label> Undeploy the deployment with ID + '{{ecdapp.deploymentRef}}'? </label> + </div> + </div> + </div> +</div> +<div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <div class="cta-button-group in"> + <button class="btn btn-alt btn-small" type="button" + ng-disabled="ecdapp.isDisabled" + ng-click="ecdapp.deleteDeploymentById(deployment);"> + Undeploy</button> + <button class="btn btn-small" type="button" + ng-click="$dismiss('cancel')">Cancel</button> + </div> +</div> </script> - -<script type="text/ng-template" id="inventory_deployment_inputs_view_popup.html"> - - <style> - .ecd-parameter-table - { - border: 1px; - overflow: auto; - } - .ecd-parameter-table th - { - font-size: 1.4rem; - } - </style> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-show="ecdapp.errMsg"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.errMsg"> - <div class="row-nowrap" style="margin-bottom:10px;"> - <div class="span6"> - <label for="tenant">Tenant</label> - <!--not editable--> - <input id="tenant" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/> - </div> - </div> - </div> - - <div ng-hide="ecdapp.errMsg"> - <div class="row-nowrap"> - <div class="span12"> - <label for="deploymentRef">Deployment Ref</label> - <!--not editable--> - <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/> - </div> - <div class="span12"> - <label for="serviceId">Service ID</label> - <!--not editable--> - <input id="serviceId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.serviceId"/> - </div> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <table id="parameters"> - <tr id="ecd-table-header"> - <th width="40%">Name</th> - <th width="60%">Value</th> - </tr> - <tbody ng-repeat="(pkey, pval) in ecdapp.deployment.inputs"> - <tr id="tr-rowData"> - <td ng-bind="pkey"/> - <td ng-bind="pval"/> - </tr> - </tbody> - </table> - </div> - </div> - </div> - </div> +<script type="text/ng-template" + id="inventory_deployment_inputs_view_popup.html"> +<style> +.ecd-parameter-table { + border: 1px; + overflow: auto; +} + +.ecd-parameter-table th { + font-size: 1.4rem; +} +</style> +<div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> +</div> +<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-hide="ecdapp.errMsg"> + <div class="row-nowrap" style="margin-bottom: 10px;"> + <div class="span6"> + <label for="tenant">Tenant</label> + <!--not editable--> + <input id="tenant" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.ui_tenant" /> + </div> + </div> + </div> + <div ng-hide="ecdapp.errMsg"> + <div class="row-nowrap"> + <div class="span12"> + <label for="deploymentRef">Deployment Ref</label> + <!--not editable--> + <input id="deploymentRef" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.deploymentRef" /> + </div> + <div class="span12"> + <label for="serviceId">Service ID</label> + <!--not editable--> + <input id="serviceId" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.serviceId" /> + </div> + </div> + <div class="row-nowrap"> + <div class="span12"> + <table id="parameters"> + <tr id="ecd-table-header"> + <th width="30%">Name</th> + <th width="70%">Value</th> + </tr> + <tbody ng-repeat="(pkey, pval) in ecdapp.deployment.parmFileDict"> + <tr id="tr-rowData"> + <td> + <div style="font-weight: bold;">{{pkey}}</div> + <div style="margin-top: 10px; font-weight: lighter;"> + {{ecdapp.deployment.descriptionDict[pkey]}}</div> + </td> + <td> <pre>{{pval}}</pre></td> + </tr> + </tbody> + </table> + </div> + </div> + </div> +</div> </script> -<script type="text/ng-template" id="inventory_deployment_update_popup.html"> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <div ng-show="ecdapp.errMsg"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <label for="deploymentRef">Deployment Ref</label> - <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/> - </div> - <div class="span12"> - <label for="tenantName">Tenant Name</label> - <!--not editable--> - <input id="tenantName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/> - </div> - </div> - - <div ng-hide="ecdapp.isDataLoading" style="margin-top:20px;"> - <div - b2b-table - id="service-type-table" - class="b2b-table-div" - table-data="ecdapp.bp" > - <table> - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header>Blueprint Name</th> - <th b2b-table-header>Blueprint Version</th> - <th b2b-table-header>Type ID</th> - <th b2b-table-header>Description</th> - <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> - </tr> - </thead> - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.bp"> - <tr id="tr-rowData"> - <td b2b-table-body - ng-bind="rowData.typeName"/> - <td b2b-table-body - ng-bind="rowData.typeVersion"/> - <td b2b-table-body - ng-bind="rowData.typeId"/> - <td b2b-table-body - ng-bind="rowData.blueprintDescription"/> - <td b2b-table-body> - <div class="form-row"> - <label for="bpCb{{index}}" class="checkbox"> - <input id="bpCb{{index}}" type="checkbox" ng-model="rowData.checked" ng-click="ecdapp.updateSelection(rowData.typeId)" /> - <i class="skin"></i> - </label> - </div> - </td> - </tr> - </tbody> - </table> - </div> - </div> - <div ng-hide="ecdapp.isDataLoading" class="row-nowrap" style="margin-top:20px;"> - <div class="span12"> - <label for="typeID">Blueprint[Service Type] ID</label> - <input id="typeID" class="span12" type="text" data-ng-model="ecdapp.typeId" title="ID of the blueprint to use for the update"/> - </div> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.getBlueprint()"> - Get Blueprint data - </button> - </div> - </div> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-hide="ecdapp.isDataLoading" class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="parameters">*Parameters</label> - <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center"> - <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" > - Drag & drop a parameters JSON file here, or click to browse. - </span> - </div> - </div> - <div class="ecd-parameter-table"> - <table id="parameters"> - <tr id="ecd-table-header"> - <th width="40%">Name</th> - <th width="60%">Value</th> - </tr> - <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict"> - <tr id="tr-rowData"> - <td ng-bind="pkey"/> - <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td> - </tr> - </tbody> - </table> - </div> - </div> - </div> - </div> - - <!-- show progress indicator --> - <div ng-show="ecdapp.deploymentInProgress"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the task completes. - </div> - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in" ng-hide="ecdapp.deploymentInProgress"> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.updateDeployment(ecdapp.editRequest)" ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg"> - Update - </button> - <button class="btn btn-alt btn-small" type="button" - ng-click="$dismiss('cancel');"> - Close - </button> - </div> - </div> - +<script type="text/ng-template" + id="inventory_deployment_update_popup.html"> +<div class="b2b-modal-header ng-scope"> + <h3 id="myModalLabel" modal-title="">{{ecdapp.label}}</h3> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> +</div> +<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-hide="ecdapp.isDataLoading" style="margin-top: -5px;"> + <div class="field-group"> + <label for="bp">Blueprint</label> <select + style="font-size: 1.2rem;" id="bp" name="appl" b2b-dropdown + class="span6" ng-model="ecdapp.typeId" + ng-change="ecdapp.getBlueprint()" required> + <option b2b-dropdown-list option-repeat="d in ecdapp.bp" + value="{{d.typeId}}">{{d.typeName}} + version#{{d.typeVersion}}</option> + </select> + </div> + </div> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-hide="ecdapp.isDataLoading" class="row-nowrap"> + <div class="span12"> + <div class="form-row"> + <label for="parameters">*Inputs</label> + <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" + on-drop="handleFileSelect()" align="center"> + <span b2b-file-link file-model="ecdapp.editRequest.fileModel" + on-file-select="handleFileSelect()"> Drag & drop + a parameters JSON file here, or click to browse. </span> + </div> + </div> + <div class="ecd-parameter-table"> + <table id="parameters"> + <tbody + ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict"> + <tr id="tr-rowData"> + <td + style="padding: 5px 0 2px 0; font-size: 1.2rem; width: 100%; border: none;" + ng-bind="pkey"> + <div style="font-weight: bold;">{{pkey}}</div> + <div style="margin-top: 8px; font-weight: lighter;">{{ecdapp.editRequest.descriptionDict[pkey]}}</div> + </td> + </tr> + <tr id="tr-rowData"> + <td + style="padding: 0 5px 5px; font-size: 1.2rem; width: 100%; border: none;"> + <input id="parameterValue" class="span12" type="text" + data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" + autofocus /> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div style="border-bottom: 1px solid black;">Actions</div> + <div style="margin-top: 10px;"> + <label for="install_flow" class="btn-switch-label" + ng-class="{'b2b-disabled-label':allDisabled}"> <input + type="button" aria-pressed="{{ecdapp.install_flow.value}}" + id="refresh_switch" b2b-switches + ng-model="ecdapp.install_flow.value" ng-disabled="allDisabled" + aria-disabled="{{allDisabled}}" + aria-label="Auto-refresh is {{ecdapp.install_flow.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}"> + <label style="margin-left: 10px;" aria-hidden="true">Run + install workflow</label> <span class="tooltip" b2b-tooltip> <a + href="#" class="icon-tooltip tooltip-element" tabindex="0" + role="button" data-placement="top" aria-label="Help" + aria-describedby="tooltiptextRadio"> <span class="arrow"></span> + </a> <span class="tooltip-wrapper"> <span + class="tooltip-size-control"> <span + id="tooltiptextRadio" role="tooltip" aria-live="polite" + aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Run install lifecycle + operations</span> <span class="popover-content"> </span> + </span> + </span> + </span> + </span> + </label> + </div> + <div style="margin-top: 10px;"> + <label for="uninstall_flow" class="btn-switch-label" + ng-class="{'b2b-disabled-label':allDisabled}"> <input + type="button" aria-pressed="{{ecdapp.uninstall_flow.value}}" + id="refresh_switch" b2b-switches + ng-model="ecdapp.uninstall_flow.value" ng-disabled="allDisabled" + aria-disabled="{{allDisabled}}" + aria-label="Auto-refresh is {{ecdapp.uninstall_flow.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}"> + <label style="margin-left: 10px;" aria-hidden="true">Run + uninstall workflow</label> <span class="tooltip" b2b-tooltip> <a + href="#" class="icon-tooltip tooltip-element" tabindex="0" + role="button" data-placement="top" aria-label="Help" + aria-describedby="tooltiptextRadio"> <span class="arrow"></span> + </a> <span class="tooltip-wrapper"> <span + class="tooltip-size-control"> <span + id="tooltiptextRadio" role="tooltip" aria-live="polite" + aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Run uninstall lifecycle + operations</span> <span class="popover-content"> </span> + </span> + </span> + </span> + </span> + </label> + </div> + <div style="margin-top: 10px;"> + <label for="install_first_flow" class="btn-switch-label" + ng-class="{'b2b-disabled-label':allDisabled}"> <input + type="button" + aria-pressed="{{ecdapp.install_first_flow_flag.value}}" + id="refresh_switch" b2b-switches + ng-model="ecdapp.install_first_flow_flag.value" + ng-disabled="allDisabled" aria-disabled="{{allDisabled}}" + aria-label="Auto-refresh is {{ecdapp.install_first_flow_flag.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}"> + <label style="margin-left: 10px;" aria-hidden="true">Run + install workflow first</label> <span class="tooltip" b2b-tooltip> + <a href="#" class="icon-tooltip tooltip-element" tabindex="0" + role="button" data-placement="top" aria-label="Help" + aria-describedby="tooltiptextRadio"> <span class="arrow"></span> + </a> <span class="tooltip-wrapper"> <span + class="tooltip-size-control"> <span + id="tooltiptextRadio" role="tooltip" aria-live="polite" + aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Run install workflow + first, then uninstall workflow. Default: first uninstall + then install workflow.</span> <span class="popover-content"> + </span> + </span> + </span> + </span> + </span> + </label> + </div> + <div style="margin-top: 10px;"> + <label for="reinstall_flow" class="btn-switch-label" + ng-class="{'b2b-disabled-label':allDisabled}"> <input + type="button" aria-pressed="{{ecdapp.reinstall_flow.value}}" + id="refresh_switch" b2b-switches + ng-model="ecdapp.reinstall_flow.value" ng-disabled="allDisabled" + aria-disabled="{{allDisabled}}" + aria-label="Auto-refresh is {{ecdapp.reinstall_flow.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}"> + <label style="margin-left: 10px;" aria-hidden="true">Run + automatic reinstall</label> <span class="tooltip" b2b-tooltip> <a + href="#" class="icon-tooltip tooltip-element" tabindex="0" + role="button" data-placement="top" aria-label="Help" + aria-describedby="tooltiptextRadio"> <span class="arrow"></span> + </a> <span class="tooltip-wrapper"> <span + class="tooltip-size-control"> <span + id="tooltiptextRadio" role="tooltip" aria-live="polite" + aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Automatically reinstall + node instances whose properties have been modified as + part of deployment update. If not set then, node + instances that were explicitly given to "Reinstall node + instances list" will be reinstalled.</span> <span + class="popover-content"> </span> + </span> + </span> + </span> + </span> + </label> + </div> + <div style="margin-top: 10px;"> + <div class="field-group"> + <div class="group"> + <label class="col-sm-3 control-label">Reinstall node + instances list </label> <span class="tooltip" b2b-tooltip> <a + href="#" class="icon-tooltip tooltip-element" tabindex="0" + role="button" data-placement="top" aria-label="Help" + aria-describedby="tooltiptextRadio"> <span class="arrow"></span> + </a> <span class="tooltip-wrapper"> <span + class="tooltip-size-control"> <span + id="tooltiptextRadio" role="tooltip" aria-live="polite" + aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Node instances to be + installed as part of the deployment update. They will + be reinstalled even if "Run automatic reinstall" is + not set</span> <span class="popover-content"> </span> + </span> + </span> + </span> + </span> + <ui-select multiple ng-model="ecdapp.selectedNodeInst" + theme="bootstrap" close-on-select="false" + title="node instance"> <ui-select-match + class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices + class="ui-select-choices" + repeat="nodeInst in ecdapp.nodeInst | filter:$select.search" + position='down'> {{nodeInst}} </ui-select-choices> </ui-select> + </div> + </div> + <div style="margin-top: 10px;"> + <label for="force" class="btn-switch-label" + ng-class="{'b2b-disabled-label':allDisabled}"> <input + type="button" aria-pressed="{{ecdapp.force_flag.value}}" + id="refresh_switch" b2b-switches + ng-model="ecdapp.force_flag.value" ng-disabled="allDisabled" + aria-disabled="{{allDisabled}}" + aria-label="Auto-refresh is {{ecdapp.force_flag.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}"> + <label style="margin-left: 10px;" aria-hidden="true">Force + update</label> <span class="tooltip" b2b-tooltip> <a href="#" + class="icon-tooltip tooltip-element" tabindex="0" + role="button" data-placement="top" aria-label="Help" + aria-describedby="tooltiptextRadio"> <span class="arrow"></span> + </a> <span class="tooltip-wrapper"> <span + class="tooltip-size-control"> <span + id="tooltiptextRadio" role="tooltip" aria-live="polite" + aria-hidden="true" class="helpertext" tabindex="-1"> + <span class="popover-title">Force running update + in case a previous update on this deployment has + failed to finish successfully</span> <span + class="popover-content"> </span> + </span> + </span> + </span> + </span> + </label> + </div> + </div> + <!-- show progress indicator --> + <div ng-show="ecdapp.deploymentInProgress"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the task completes. + </div> + </div> + <div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <div class="cta-button-group in" + ng-hide="ecdapp.deploymentInProgress"> + <button class="btn btn-alt btn-small" type="button" + ng-click="ecdapp.updateDeployment(ecdapp.editRequest)" + ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg"> + Update</button> + <button class="btn btn-alt btn-small" type="button" + ng-click="$dismiss('cancel');">Close</button> + </div> + </div> </script> <script type="text/ng-template" id="blueprint_data_view_popup.html"> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-show="ecdapp.errMsg"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <label for="typeName">Blueprint Name</label> - <!--not editable--> - <input id="typeName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.typeName"/> - </div> - </div> - <div ng-hide="ecdapp.errMsg"> - <pre>{{ecdapp.blueprint}}</pre> - </div> - - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="$dismiss('cancel');"> - Close - </button> - </div> - </div> - -</script> - -<script type="text/ng-template" id="inventory_deployment_rollback_popup.html"> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-show="ecdapp.errMsg"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.errMsg"> - <div class="row-nowrap"> - <div class="span12"> - <label for="deploymentRef">Deployment Ref</label> - <!--not editable--> - <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/> - </div> - <div class="span12"> - <label for="serviceId">Service ID</label> - <!--not editable--> - <input id="serviceId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.serviceId"/> - </div> - <div class="span12"> - <label for="tenantName">Tenant Name</label> - <!--not editable--> - <input id="tenantName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/> - </div> - </div> - - <div ng-hide="ecdapp.isDataLoading"> - <div - b2b-table - id="revisions-table" - class="b2b-table-div" - table-data="ecdapp.local_revisions" > - <table> - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header>Revision</th> - <th b2b-table-header>Updated</th> - <th b2b-table-header>Status</th> - <th b2b-table-header>Chart</th> - <th b2b-table-header>Description</th> - <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> - </tr> - </thead> - - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.local_revisions"> - <tr id="tr-rowData"> - <td b2b-table-body - ng-bind="rowData.revision"/> - <td b2b-table-body - ng-bind="rowData.updated"/> - <td b2b-table-body - ng-bind="rowData.status"/> - <td b2b-table-body - ng-bind="rowData.chart"/> - <td b2b-table-body - ng-bind="rowData.description"/> - <td ng-if="!$last" b2b-table-body> - <div class="form-row"> - <label class="checkbox"> - <input type="checkbox" ng-model="rowData.checked" ng-click="ecdapp.updateSelection(rowData.revision)" /> - <i class="skin"></i> - </label> - </div> - </td> - </tr> - </tbody> - </table> - </div> - </div> - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.rollbackWorkflow(ecdapp.revision);" ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg"> - Start Rollback - </button> - <button class="btn btn-alt btn-small" type="button" - ng-click="$dismiss('cancel');"> - Close - </button> - </div> - </div> - + <div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> + </div> + <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div class="row-nowrap"> + <div class="span12"> + <label for="typeName">Blueprint Name</label> + <!--not editable--> + <input id="typeName" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.typeName" /> + </div> + </div> + <div ng-hide="ecdapp.errMsg"> + <pre>{{ecdapp.blueprint}}</pre> + </div> + </div> + <div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <div class="cta-button-group in"> + <button class="btn btn-alt btn-small" type="button" + ng-click="$dismiss('cancel');">Close</button> + </div> + </div> </script> - -<script type="text/ng-template" id="inventory_deployment_upgrade_popup.html"> - - <style> - .ecd-parameter-table - { - border: 1px; - overflow: auto; - } - .ecd-parameter-table th - { - font-size: 1.4rem; - } - </style> - - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-show="ecdapp.errMsg"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.errMsg"> - <div class="row-nowrap"> - <div class="span12"> - <label for="deploymentRef">Deployment Ref</label> - <!--not editable--> - <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/> - </div> - <div class="span12"> - <label for="serviceId">Service ID</label> - <!--not editable--> - <input id="serviceId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.serviceId"/> - </div> - <div class="span12"> - <label for="tenantName">Tenant Name</label> - <!--not editable--> - <input id="tenantName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/> - </div> - </div> - - <div class="row-nowrap"> - <div class="span12"> - <div class="form-row"> - <label for="parameters">*Parameters</label> - <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center"> - <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" > - Drag & drop a parameters JSON file here, or click to browse. - </span> - </div> - </div> - <div class="ecd-parameter-table"> - <table id="parameters"> - <tr id="ecd-table-header"> - <th width="40%">Name</th> - <th width="60%">Value</th> - </tr> - <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceDefinitionChanges"> - <tr id="tr-rowData"> - <td ng-bind="pkey"/> - <td> - <input id="parameterValue" class="span12" type="text" - data-ng-model="ecdapp.editRequest.resourceDefinitionChanges[pkey]" autofocus/> - </td> - </tr> - </tbody> - <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceConstants"> - <tr id="tr-rowData"> - <td ng-bind="pkey"/> - <td ng-bind="pval"/> - </tr> - </tbody> - </table> - </div> - </div> - </div> - </div> - </div> - - <!-- show progress indicator --> - <div style="width: 100%;"> - <div ng-show="ecdapp.updatingDeployment" style="display: table; margin: 0 auto;" class="span"> - <i class="icon-spinner small" role="img" aria-label="Update Deployment in Progress..."></i> - Update Deployment in Progress... - </div> - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope" ng-show="!ecdapp.updatingDeployment"> - <div class="cta-button-group in"> - <!--<div ng-show="!ecdapp.isDataLoading">--> - <button class="btn btn-alt btn-small" type="button" - ng-click="ecdapp.upgradeWorkflow(ecdapp.editRequest.resourceDefinitionChanges);" ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg"> - Start Upgrade - </button> - <!--</div>--> - <button class="btn btn-small" type="button" - ng-click="$dismiss('cancel')"> - Cancel - </button> - </div> - </div> +<script type="text/ng-template" + id="inventory_deployment_rollback_popup.html"> + <div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> + </div> + <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-hide="ecdapp.errMsg"> + <div class="row-nowrap"> + <div class="span12"> + <label for="deploymentRef">Deployment Ref</label> + <!--not editable--> + <input id="deploymentRef" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.deploymentRef" /> + </div> + <div class="span12"> + <label for="serviceId">Service ID</label> + <!--not editable--> + <input id="serviceId" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.serviceId" /> + </div> + <div class="span12"> + <label for="tenantName">Tenant Name</label> + <!--not editable--> + <input id="tenantName" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.ui_tenant" /> + </div> + </div> + <div ng-hide="ecdapp.isDataLoading"> + <div b2b-table id="revisions-table" class="b2b-table-div" + table-data="ecdapp.local_revisions"> + <table> + <thead b2b-table-row type="header"> + <tr id="th-header-row"> + <th b2b-table-header>Revision</th> + <th b2b-table-header>Updated</th> + <th b2b-table-header>Status</th> + <th b2b-table-header>Chart</th> + <th b2b-table-header>Description</th> + <th b2b-table-header sortable="false"><i + class="icon-controls-gear ecd-icon-display"></i></th> + </tr> + </thead> + <tbody b2b-table-row type="body" + row-repeat="rowData in ecdapp.local_revisions"> + <tr id="tr-rowData"> + <td b2b-table-body ng-bind="rowData.revision" /> + <td b2b-table-body ng-bind="rowData.updated" /> + <td b2b-table-body ng-bind="rowData.status" /> + <td b2b-table-body ng-bind="rowData.chart" /> + <td b2b-table-body ng-bind="rowData.description" /> + <td ng-if="!$last" b2b-table-body> + <div class="form-row"> + <label class="checkbox"> <input + type="checkbox" ng-model="rowData.checked" + ng-click="ecdapp.updateSelection(rowData.revision)" /> + <i class="skin"></i> + </label> + </div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <div class="cta-button-group in"> + <button class="btn btn-alt btn-small" type="button" + ng-click="ecdapp.rollbackWorkflow(ecdapp.revision);" + ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg"> + Start Rollback</button> + <button class="btn btn-alt btn-small" type="button" + ng-click="$dismiss('cancel');">Close</button> + </div> + </div> </script> +<script type="text/ng-template" + id="inventory_deployment_upgrade_popup.html"> + <style> +.ecd-parameter-table { + border: 1px; + overflow: auto; +} + +.ecd-parameter-table th { + font-size: 1.4rem; +} +</style> + <div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> + </div> + <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-hide="ecdapp.errMsg"> + <div class="row-nowrap"> + <div class="span12"> + <label for="deploymentRef">Deployment Ref</label> + <!--not editable--> + <input id="deploymentRef" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.deploymentRef" /> + </div> + <div class="span12"> + <label for="tenantName">Tenant Name</label> + <!--not editable--> + <input id="tenantName" class="span12" type="text" + disabled="disabled" data-ng-model="ecdapp.ui_tenant" /> + </div> + </div> + <div class="row-nowrap"> + <div class="span12"> + <div class="form-row"> + <label for="parameters">*Parameters</label> + <div b2b-file-drop + file-model="ecdapp.editRequest.fileModel" + on-drop="handleFileSelect()" align="center"> + <span b2b-file-link + file-model="ecdapp.editRequest.fileModel" + on-file-select="handleFileSelect()"> Drag + & drop a parameters JSON file here, or click to + browse. </span> + </div> + </div> + <div class="ecd-parameter-table"> + <table id="parameters"> + <tr id="ecd-table-header"> + <th width="40%">Name</th> + <th width="60%">Value</th> + </tr> + <tbody + ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceDefinitionChanges"> + <tr id="tr-rowData"> + <td ng-bind="pkey" /> + <td><input id="parameterValue" class="span12" + type="text" + data-ng-model="ecdapp.editRequest.resourceDefinitionChanges[pkey]" + autofocus /></td> + </tr> + </tbody> + <tbody + ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceConstants"> + <tr id="tr-rowData"> + <td ng-bind="pkey" /> + <td ng-bind="pval" /> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </div> + </div> + <!-- show progress indicator --> + <div style="width: 100%;"> + <div ng-show="ecdapp.updatingDeployment" + style="display: table; margin: 0 auto;" class="span"> + <i class="icon-spinner small" role="img" + aria-label="Update Deployment in Progress..."></i> Update + Deployment in Progress... + </div> + </div> + <div class="b2b-modal-footer ng-scope ng-isolate-scope" + ng-show="!ecdapp.updatingDeployment"> + <div class="cta-button-group in"> + <!--<div ng-show="!ecdapp.isDataLoading">--> + <button class="btn btn-alt btn-small" type="button" + ng-click="ecdapp.upgradeWorkflow(ecdapp.editRequest.resourceDefinitionChanges);" + ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg"> + Start Upgrade</button> + <!--</div>--> + <button class="btn btn-small" type="button" + ng-click="$dismiss('cancel')">Cancel</button> + </div> + </div> +</script>
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_table.html deleted file mode 100644 index 66ab9b5..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_table.html +++ /dev/null @@ -1,148 +0,0 @@ -<div id="page-content"> - - <h1 class="heading-page" id="deployments-page">Deployments</h1> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - - <div ng-hide="ecdapp.isDataLoading"> - <div id="button-search-row"> - <div style="float:right;"> - <div class="group"> - <button tabindex="-1" class="btn btn-small" title="Reset Filters" type="button" ng-click="ecdapp.loadTable()"><i class="icon-arrows-replay-restart"></i></button> - <input tabindex="0" class="btn btn-small" type="text" placeholder="Search Deployments" ng-model="ecdapp.searchBy"></input> - <button tabindex="1" class="btn btn-small" type="button" ng-click="ecdapp.searchTable(ecdapp.searchBy)"><i class="ion-search"></i></button> - </div> - </div> - </div> - - <div ng-show="ecdapp.isRequestFailed"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - - <div ng-hide="ecdapp.isRequestFailed"> - <div - b2b-table - id="deployments-table" - class="b2b-table-div" - table-data="ecdapp.tableData" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - <table> - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header sortable="false" key="serviceId" ng-click="ecdapp.sortTable('serviceId')">Service ID/Deployment Ref.</th> - <th b2b-table-header sortable="false" key="created" ng-click="ecdapp.sortTable('created')">Created</th> - <th b2b-table-header sortable="false" key="updated" ng-click="ecdapp.sortTable('modified')">Modified</th> - <th b2b-table-header sortable="false" key="tenant" style="background-color:#dbefef;">Tenant - <button style="margin-bottom:-5px; box-shadow:0 0 0 0 rgba(0, 0, 0, 0.15); min-width:0;" tabindex="1" class="btn btn-small" title="Refresh Tenant and Status" type="button" ng-click="ecdapp.updateTable()"> - <i class="icon-arrows-replay-restart"></i> - </button> - <div ng-show="ecdapp.isSrvcDataLoading"> - <div class="span" style="margin-bottom:5px;"> - <i class="icon-spinner small" role="img" aria-label="Deployment Info is loading"></i> - Tenant and Status Info loading - </div> - </div> - </th> - <th b2b-table-header sortable="false" key="status" style="background-color:#dbefef;">Install Status</th> - <th b2b-table-header sortable="false" style="background-color:#dbefef;">Actions</th> - </tr> - </thead> - - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData"> - <tr id="tr-rowData"> - <td b2b-table-body - ng-bind="rowData.serviceId" - ng-class="{'td-error' : rowData.statusInfo === undefined}"/> - <td b2b-table-body - ng-bind="rowData.created | date : 'MM-dd-yyyy HH:mm:ss Z'" - ng-class="{'td-error' : rowData.statusInfo === undefined}"/> - <td b2b-table-body - ng-bind="rowData.modified | date : 'MM-dd-yyyy HH:mm:ss Z'" - ng-class="{'td-error' : rowData.statusInfo === undefined}"/> - <td b2b-table-body - ng-bind="rowData.statusInfo.tenant_name" - ng-class="{'td-error' : rowData.statusInfo === undefined}"/> - <td b2b-table-body - ng-class="{'td-error' : rowData.statusInfo === undefined}"> - <img ng-src="{{rowData.statusInfo.statusImg}}" title="{{rowData.statusInfo.status}}" /> - </span> - </td> - <td b2b-table-body ng-class="{'td-error' : rowData.statusInfo === undefined}"> - <div class="btn-group btn-actions" style="margin-bottom:0;box-shadow:none;"> - <button type="button" class="btn dropdown-toggle" data-toggle="dropdown" title="More Actions"><i class="icon-apps-marketplace"></i></button> - <ul class="dropdown-menu"> - <li> - <div ng-click="ecdapp.viewBlueprintDataModal(rowData);"> - <i class="icon-documents-book ecd-icon-action"></i><a href="">View blueprint</a> - </div> - </li> - <li> - <div ng-click="ecdapp.viewDeploymentInputsModalPopup(rowData);"> - <i class="icoDocuments-report ecd-icon-action"></i><a href="">View Inputs</a> - </div> - </li> - <li> - <div ng-click="ecdapp.viewDeploymentExecutionsModalPopup(rowData);"> - <i class="icon-overview ecd-icon-action"></i><a href="">View executions</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.updateDeploymentModalPopup(rowData);"> - <i class="icon-misc-pen ecd-icon-action"></i><a href="">Update deployment</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy" ng-click="ecdapp.deleteDeploymentModalPopup(rowData);"> - <i class="icon-misc-trash ecd-icon-action"></i><a href="">Undeploy</a> - </div> - </li> - <li> - <div ng-show="rowData.statusInfo.is_helm && rowData.statusInfo.helm_status && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.checkHelmStatus(rowData);"> - <i class="icoDocuments-report ecd-icon-action"></i><a href="">Helm Status</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy && rowData.statusInfo.is_helm && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.upgradeDeploymentModalPopup(rowData);"> - <i class="icon-controls-down ecd-icon-action"></i><a href="#">Helm upgrade deployment</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy && rowData.statusInfo.is_helm && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.rollbackDeploymentModalPopup(rowData);"> - <i class="icon-controls-up"></i><a href="#">Helm rollback deployment</a> - </div> - </li> - <li> - <div ng-show="rowData.canDeploy && rowData.statusInfo === undefined" ng-click="ecdapp.deleteServiceModalPopup(rowData);"> - <i class="icon-misc-trash ecd-icon-action"></i><a href="">Delete Service</a> - </div> - </li> - </ul> - </div><!-- .btn-group --> - </td> - </tr> - </tbody> - </table> - </div> - - <div b2b-pagination="" total-pages="ecdapp.totalPages" - current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler" - role="navigation"> - </div> - - </div> - </div> - - <div style="height: 10px;"> - <!-- space between page number and black footer --> - </div> - -</div><!-- loading --> - -</div><!-- page content --> diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_execution_popups.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_execution_popups.html index 4b870dc..6277207 100644 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_execution_popups.html +++ b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_execution_popups.html @@ -1,255 +1,271 @@ <script type="text/ng-template" id="inventory_execution_view_popup.html"> - <div class="b2b-modal-header ng-scope"> - <h2 id="myModalLabel" style="margin-left: 200px;" modal-title="">{{ecdapp.label}}</h2> - <div class="corner-button in"> - <button type="button" class="close" aria-label="Close" - ng-click="$dismiss('cancel')"></button> - </div> - <div style="position: absolute;"> - <label for="show-menu" class="show-menu" title="click to view more info">☰</label> - <input type="checkbox" id="show-menu" /> - <div class="menu" ng-hide="ecdapp.errMsg"> - <!--<div class="row-nowrap" style="margin-bottom:10px;"> --> - <div class="span12" style="margin-bottom:10px;"> - <label for="deploymentRef">Deployment Ref</label> - <!--not editable--> - <input id="deploymentRef" class="span6" type="text" data-ng-model="ecdapp.deplRef"/> - </div> - <div class="span12" style="margin-bottom:10px;"> - <label for="tenant">Tenant</label> - <!--not editable--> - <input id="tenant" class="span6" type="text" data-ng-model="ecdapp.ui_tenant"/> - </div> - <!-- <button ng-click="ecdapp.toggleStatusDefinitions()" class="btn btn-alt btn-small">Click to view status definitions</button> --> - <div> - <div b2b-table id="status-table" class="b2b-table-div"> - <table id="status-definition-table"> - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header key="status">Status</th> - <th b2b-table-header key="definition">Definition</th> - </tr> - </thead> - <tbody b2b-table-row type="body"> - <tr> - <td>waiting to start</td> - <td>The execution is waiting for a worker to start it</td> - </tr> - <tr> - <td>in progress</td> - <td>The execution is currently running.</td> - </tr> - <tr> - <td>cancel in progress</td> - <td>The execution is currently being cancelled.</td> - </tr> - <tr> - <td>force-cancelling in progress</td> - <td>The execution is currently being force-cancelled.</td> - </tr> - <tr> - <td>cancelled</td> - <td>The execution has been cancelled.</td> - </tr> - <tr> - <td>successful</td> - <td>The execution has terminated successfully.</td> - </tr> - <tr> - <td>failed</td> - <td>The execution has failed. Click on the button in the error column to view the error details.</td> - </tr> - </tbody> - </table> - </div> - </div> - </div> - </div> - </div> - - <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" - role="region" aria-label="Modal body content"> - - <!--<h1 class="heading-page" id="executions-page">Executions</h1> --> - - <!-- show progress indicator --> - <div ng-show="ecdapp.isDataLoading"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - </div> - <div ng-show="ecdapp.isCancelOn"> - <div class="span" style="margin-bottom:20px;"> - <i class="icon-spinner small" role="img" aria-label="Cancel in progress"></i> - Cancel in progress - </div> - </div> - <div ng-show="ecdapp.errMsg"> - <span class="ecd-error-message">{{ecdapp.errMsg}}</span> - </div> - <div ng-show="ecdapp.evtErrMsg"> - <span class="ecd-error-message">{{ecdapp.evtErrMsg}}</span> - </div> - - <div class="form-row" style="margin-top:0px;"> - <div style="float: left; width: 200px; margin-left: 30px;" title="switch to enable/disable screen refresh"> - <label for="refresh_switch" class="btn-switch-label" ng-class="{'b2b-disabled-label':allDisabled}"> - <span aria-hidden="true">Auto-refresh</span> - <input type="button" aria-pressed="{{ecdapp.refresh_switch.value}}" id="refresh_switch" b2b-switches ng-model="ecdapp.refresh_switch.value" ng-disabled="allDisabled" aria-disabled="{{allDisabled}}" aria-label="Auto-refresh is {{ecdapp.refresh_switch.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}"> - </label> - </div> - <div style="float: right;" title="Checkbox to view latest execution workflow only"> - <label for="checkbox1" class="checkbox"> - <input id="checkbox1" type="checkbox" ng-model="ecdapp.isLastExecution"><i class="skin"></i><span>Last execution</span> - </label> - </div> +<div class="b2b-modal-header ng-scope"> + <h2 id="myModalLabel" modal-title=""> + Deployment <span style="font-weight: bolder; background: aqua;">{{ecdapp.deplRef}}</span> + Executions + </h2> + <div class="corner-button in"> + <button type="button" class="close" aria-label="Close" + ng-click="$dismiss('cancel')"></button> + </div> + <div style="position: absolute; right: 50px; top: 40px;"> + <label for="show-menu" class="show-menu" + title="click to view more info">☰</label> <input + type="checkbox" id="show-menu" /> + <div class="menu" ng-hide="ecdapp.errMsg"> + <div class="span12" style="margin-bottom: 10px;"> + <label for="tenant">Tenant</label> + <!--not editable--> + <input id="tenant" class="span6" type="text" + data-ng-model="ecdapp.ui_tenant" /> + </div> + <div> + <div b2b-table id="status-table" class="b2b-table-div"> + <table id="status-definition-table"> + <thead b2b-table-row type="header"> + <tr id="th-header-row"> + <th b2b-table-header key="status">Status</th> + <th b2b-table-header key="definition">Definition</th> + </tr> + </thead> + <tbody b2b-table-row type="body"> + <tr> + <td>waiting to start</td> + <td>The execution is waiting for a worker to start + it</td> + </tr> + <tr> + <td>in progress</td> + <td>The execution is currently running.</td> + </tr> + <tr> + <td>cancel in progress</td> + <td>The execution is currently being cancelled.</td> + </tr> + <tr> + <td>force-cancelling in progress</td> + <td>The execution is currently being + force-cancelled.</td> + </tr> + <tr> + <td>cancelled</td> + <td>The execution has been cancelled.</td> + </tr> + <tr> + <td>successful</td> + <td>The execution has terminated successfully.</td> + </tr> + <tr> + <td>failed</td> + <td>The execution has failed. Click on the button + in the error column to view the error details.</td> + </tr> + </tbody> + </table> + </div> + </div> </div> - - <div ng-hide="ecdapp.errMsg"> - <div - b2b-table - id="executions-table" - class="b2b-table-div" - table-data="ecdapp.tableData" - search-string="ecdapp.searchString" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - - <table> - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header key="created_at">Created Date</th> - <th b2b-table-header key="workflow_id">Workflow ID</th> - <th b2b-table-header key="id">ID</th> - <th b2b-table-header key="status">Status</th> - <th b2b-table-header sortable="false"><i class="icon-settings ecd-icon-display"></i></th> - </tr> - </thead> - - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData"> - <tr id="tr-rowData"> - <td b2b-table-body - ng-bind="rowData.created_at"/> - <td b2b-table-body - ng-bind="rowData.workflow_id"/> - <td b2b-table-body - ng-bind="rowData.id"/> - <td b2b-table-body ng-if="rowData.status == 'pending'"> - waiting to start - </td> - <td b2b-table-body ng-if="rowData.status == 'started'"> - <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);"> - <a href="" title="View execution logs" class="tooltip">in progress</a> - </div> - </td> - <td b2b-table-body ng-if="rowData.status == 'cancelling'"> - <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);"> - <a href="" title="View execution logs" class="tooltip">cancel in progress</a> - </div> - </td> - <td b2b-table-body ng-if="rowData.status == 'force_cancelling'"> - <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);"> - <a href="" title="View execution logs" class="tooltip">force-cancelling in progress</a> - </div> - </td> - <td b2b-table-body ng-if="rowData.status == 'cancelled'"> - <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);"> - <a href="" title="View execution logs" class="tooltip">cancelled</a> - </div> - </td> - <td b2b-table-body ng-if="rowData.status == 'terminated'"> - <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);"> - <a href="" title="View execution logs" class="tooltip">successful</a> - </div> - </td> - <td b2b-table-body ng-if="rowData.status == 'failed'"> - <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);"> - <a href="" title="View execution logs" class="tooltip">failed</a> - </div> - </td> - <td b2b-table-body ng-if="rowData.status == 'failed'"> - <div ng-show="rowData.error" ng-click="ecdapp.viewErrorModalPopup(rowData);"> - <a href="" title="View error details" class="icon-people-preview ecd-icon-action"></a> - </div> - </td> - <td b2b-table-body ng-if="rowData.status == 'started'"> - <div ng-click="ecdapp.cancelExecutionModalPopup(rowData, ecdapp.ui_tenant);"> - <a href="" title="Cancel execution" class="ion-stop ecd-icon-action"></a> - </div> - </td> - </tr> - </tbody> - </table> - </div> - <!-- <div b2b-pagination="" total-pages="ecdapp.totalPages" - current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler" - role="navigation"> - </div> --> - </div> - <div ng-show="ecdapp.isEventLogQuery"> - <div style="float: left;"> - <h3>Events/Logs </h3> - <h4>execution id: {{ecdapp.executionId}} </h4> - </div> - <div style="float: right;" title="Checkbox to Include log type events"> - <label for="checkbox2" class="checkbox"> - <input id="checkbox2" type="checkbox" ng-model="ecdapp.isLogType"><i class="skin"></i><span>Include Logs</span> - </label> - </div> - - <div - b2b-table - id="logs-table" - class="b2b-table-div" - table-data="ecdapp.logTableData" - current-page="ecdapp.currentPageIgnored" - next-sort="ecdapp.nextSortIgnored"> - <table> - <thead b2b-table-row type="header"> - <tr id="th-header-row"> - <th b2b-table-header key="reported_timestamp">Reported Timestamp</th> - <th b2b-table-header key="timestamp">Type</th> - <th b2b-table-header key="event_type">Event Type</th> - <th b2b-table-header key="message">Message</th> - <th b2b-table-header key="node_name">Node name</th> - <th b2b-table-header key="node_instance_id">Node Instance</th> - <th b2b-table-header key="error_causes">Error Causes</th> - </tr> - </thead> - <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.logTableData"> - <tr id="tr-rowData" ng-class="{ 'red-background' : rowData.message.toLowerCase().contains("error") }"> - <td b2b-table-body - ng-bind="rowData.reported_timestamp"/> - <td b2b-table-body - ng-bind="rowData.type"/> - <td b2b-table-body - ng-bind="rowData.event_type"/> - <td b2b-table-body - ng-bind="rowData.message"/> - <td b2b-table-body - ng-bind="rowData.node_name"/> - <td b2b-table-body - ng-bind="rowData.node_instance_id"/> - <td b2b-table-body - ng-bind="rowData.error_causes[0].traceback"/> - </tr> - </tbody> - </table> - </div> - <div b2b-pagination="" total-pages="ecdapp.totalLogPages" - current-page="ecdapp.currentLogPageNum" click-handler="pageChangeHandler" - role="navigation"> - </div> - </div> - - <div class="b2b-modal-footer ng-scope ng-isolate-scope"> - <div class="cta-button-group in"> - <button class="btn btn-alt btn-small" type="button" - ng-click="$dismiss('cancel');"> - Close - </button> - </div> - </div> - + </div> +</div> +<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0" + role="region" aria-label="Modal body content"> + <!--<h1 class="heading-page" id="executions-page">Executions</h1> --> + <!-- show progress indicator --> + <div ng-show="ecdapp.isDataLoading"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Please wait while the content loads"></i> Please + wait while the content loads. + </div> + </div> + <div ng-show="ecdapp.isCancelOn"> + <div class="span" style="margin-bottom: 20px;"> + <i class="icon-spinner small" role="img" + aria-label="Cancel in progress"></i> Cancel in progress + </div> + </div> + <div ng-show="ecdapp.errMsg"> + <span class="ecd-error-message">{{ecdapp.errMsg}}</span> + </div> + <div ng-show="ecdapp.evtErrMsg"> + <span class="ecd-error-message">{{ecdapp.evtErrMsg}}</span> + </div> + <div class="form-row" style="margin-top: 0px;"> + <div style="float: left; width: 200px; margin-left: 30px;" + title="switch to enable/disable screen refresh"> + <label for="refresh_switch" class="btn-switch-label" + ng-class="{'b2b-disabled-label':allDisabled}"> <span + aria-hidden="true">Auto-refresh</span> <input type="button" + aria-pressed="{{ecdapp.refresh_switch.value}}" + id="refresh_switch" b2b-switches + ng-model="ecdapp.refresh_switch.value" ng-disabled="allDisabled" + aria-disabled="{{allDisabled}}" + aria-label="Auto-refresh is {{ecdapp.refresh_switch.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}"> + </label> + </div> + <div style="float: right;" + title="Checkbox to view latest execution workflow only"> + <label for="checkbox1" class="checkbox"> <input + id="checkbox1" type="checkbox" ng-model="ecdapp.isLastExecution"><i + class="skin"></i><span>Last execution</span> + </label> + </div> + </div> + <div ng-hide="ecdapp.errMsg"> + <div b2b-table id="executions-table" class="b2b-table-div" + table-data="ecdapp.tableData" search-string="ecdapp.searchString" + current-page="ecdapp.currentPageIgnored" + next-sort="ecdapp.nextSortIgnored"> + <table> + <thead b2b-table-row type="header"> + <tr id="th-header-row"> + <th b2b-table-header key="index">#</th> + <th b2b-table-header key="created_at">Created Date</th> + <th b2b-table-header key="workflow_id">Workflow ID</th> + <th b2b-table-header key="id">ID</th> + <th b2b-table-header key="status">Status</th> + <th b2b-table-header sortable="false">Actions<i + class="icon-controls-gear ecd-icon-display"></i></th> + </tr> + </thead> + <tbody b2b-table-row type="body" + ng-repeat="rowData in ecdapp.tableData" + ng-class="{'selected':$index == ecdapp.selectedRow}"> + <!--ng-click="ecdapp.setClickedRow($index)" --> + <tr id="tr-rowData"> + <td b2b-table-body>{{$index+1}}</td> + <td b2b-table-body ng-bind="rowData.created_at" /> + <td b2b-table-body ng-bind="rowData.workflow_id" /> + <td b2b-table-body ng-bind="rowData.id" /> + <td b2b-table-body ng-if="rowData.status == 'pending'"> + waiting to start</td> + <td b2b-table-body ng-if="rowData.status == 'started'"> + <div + ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);"> + <a href="" title="View execution logs" class="tooltip">in + progress</a> + </div> + </td> + <td b2b-table-body ng-if="rowData.status == 'cancelling'"> + <div + ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);"> + <a href="" title="View execution logs" class="tooltip">cancel + in progress</a> + </div> + </td> + <td b2b-table-body + ng-if="rowData.status == 'force_cancelling'"> + <div + ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);"> + <a href="" title="View execution logs" class="tooltip">force-cancelling + in progress</a> + </div> + </td> + <td b2b-table-body ng-if="rowData.status == 'cancelled'"> + <div + ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);"> + <a href="" title="View execution logs" class="tooltip">cancelled</a> + </div> + </td> + <td b2b-table-body ng-if="rowData.status == 'terminated'"> + <div + ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);"> + <a href="" title="View execution logs" class="tooltip">successful</a> + </div> + </td> + <td b2b-table-body ng-if="rowData.status == 'failed'"> + <div + ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);"> + <a href="" title="View execution logs" class="tooltip">failed</a> + </div> + </td> + <td b2b-table-body ng-if="rowData.status == 'failed'"> + <div ng-show="rowData.error" + ng-click="ecdapp.viewErrorModalPopup(rowData);"> + <a href="" title="View error details" + class="icon-people-preview ecd-icon-action"></a> + </div> + </td> + <td b2b-table-body ng-if="rowData.status == 'started'"> + <div + ng-click="ecdapp.cancelExecutionModalPopup(rowData, ecdapp.ui_tenant);"> + <a href="" title="Cancel execution" + class="icon-controls-stop ecd-icon-action"></a> + </div> + </td> + </tr> + </tbody> + </table> + </div> + <div b2b-pagination="" total-pages="ecdapp.totalPages" + current-page="ecdapp.currentPageNum" + click-handler="pageChangeHandler" role="navigation"></div> + </div> + <div ng-show="ecdapp.isEventLogQuery"> + <div style="float: left;"> + <h3>Events/Logs</h3> + <h4>execution id: {{ecdapp.execId}}</h4> + </div> + <div style="float: right;" + title="Checkbox to Include log type events"> + <label for="checkbox2" class="checkbox"> <input + id="checkbox2" type="checkbox" ng-model="ecdapp.isLogType"><i + class="skin"></i><span>Include Logs</span> + </label> + </div> + <div b2b-table id="logs-table" class="b2b-table-div" + table-data="ecdapp.logTableData" + current-page="ecdapp.currentPageIgnored" + next-sort="ecdapp.nextSortIgnored"> + <table> + <thead b2b-table-row type="header"> + <tr id="th-header-row"> + <th b2b-table-header key="reported_timestamp">Reported + Timestamp</th> + <th b2b-table-header key="timestamp">Type</th> + <th b2b-table-header key="event_type">Event Type</th> + <th b2b-table-header key="message">Message</th> + <th b2b-table-header key="node_name">Node name</th> + <th b2b-table-header key="node_instance_id">Node + Instance</th> + <th b2b-table-header key="error_causes">Error Causes</th> + </tr> + </thead> + <tbody b2b-table-row type="body" + row-repeat="rowData in ecdapp.logTableData"> + <tr id="tr-rowData" ng-style="{'background-color':rowData.event_type === 'task_failed' + || rowData.event_type === 'workflow_failed' ? '#fbbbbb' : '#ffffff'}"> + <td b2b-table-body ng-bind="rowData.reported_timestamp" /> + <td b2b-table-body ng-bind="rowData.type" /> + <td b2b-table-body ng-bind="rowData.event_type" /> + <td b2b-table-body> + <div class="my-tooltip"> + {{rowData.message | limitTo: 1000}} + <div class="wrapper"> + <div class="clip-btn-div"> + <button style="border-radius: 5px;margin-top: -20px;" + ng-click="ecdapp.copyStringToClipboard(rowData.message)">Copy Message</button> + </div> + <span class="my-tooltiptext">{{rowData.message}}</span> + </div> + </div> + </td> + <td b2b-table-body ng-bind="rowData.node_name" /> + <td b2b-table-body ng-bind="rowData.node_instance_id" /> + <td b2b-table-body + ng-bind="rowData.error_causes[0].traceback" /> + </tr> + </tbody> + </table> + </div> + <div b2b-pagination="" total-pages="ecdapp.totalLogPages" + current-page="ecdapp.currentLogPageNum" + click-handler="pageChangeHandlerEvent" role="navigation"></div> + </div> + <div class="b2b-modal-footer ng-scope ng-isolate-scope"> + <div class="cta-button-group in"> + <button class="btn btn-alt btn-small" type="button" + ng-click="$dismiss('cancel');">Close</button> + </div> + </div> </script>
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/dbcl_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/dbcl_view.html deleted file mode 100644 index da9fb74..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/dbcl_view.html +++ /dev/null @@ -1,6 +0,0 @@ -<div id="page-content" ng-controller="tabsController"> - <h1> DMaap Bus Controller</h1> - <iframe scrolling="yes" frameborder="0" style="width:100%; height: 800px;" - ng-src="{{opsMenu[5].url}}"> - </iframe> -</div>
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs-view-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs-view-controller.js deleted file mode 100644 index f37a4f0..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs-view-controller.js +++ /dev/null @@ -1,271 +0,0 @@ -appDS2.controller('tabsController', function ($rootScope, $scope, $interval, b2bDOMHelper, $timeout, $route) { - 'use strict'; - $scope.ecdapp = {}; - $scope.ecdapp.opsItem = $route.current.$$route.item; - $scope.ecdapp.activeTabsId = $scope.ecdapp.opsItem ; - $scope.ecdapp.activeTabUrl = ''; - $scope.ecdapp.isInit = false; - $scope.ecdapp.cfy = {}; - $scope.ecdapp.cfy.url = ''; //$rootScope.opsMenu[0].url; - $scope.ecdapp.cfy.site = ''; - $scope.ecdapp.cnsl = {}; - $scope.ecdapp.cnsl.url = ''; //$rootScope.opsMenu[2].url; - $scope.ecdapp.k8 = {}; - $scope.ecdapp.k8.site = ''; - $scope.ecdapp.k8.url = ''; //$rootScope.opsMenu[3].url; - $scope.ecdapp.k8.tenant = ''; - $scope.ecdapp.prom = {}; - $scope.ecdapp.prom.tenant = ''; - $scope.ecdapp.prom.site = ''; - $scope.ecdapp.prom.url = ''; //$rootScope.opsMenu[4].url; - $scope.ecdapp.grf = {}; - $scope.ecdapp.grf.site = ''; - $scope.ecdapp.grf.tenant = ''; - $scope.ecdapp.grf.url = ''; //$rootScope.opsMenu[1].url; - $scope.ecdapp.isFrameLoaded = true; - $scope.ecdapp.cfySite = ''; - $scope.ecdapp.cnslSite = ''; - $scope.ecdapp.appCluster = ''; - $scope.ecdapp.k8.cluster = ''; - $scope.ecdapp.grf.cluster = ''; - $scope.ecdapp.prom.cluster = ''; - - var key = $scope.ecdapp.opsItem; - - // if it's not already part of our keys array - if($rootScope.menuKeys.indexOf(key) === -1) { - // add it to our keys array - $rootScope.menuKeys.push(key); - for (var itemTab = 0; itemTab < $rootScope.opsMenu.length; itemTab++) { - if ($rootScope.opsMenu[itemTab].id === key) { - $rootScope.gTabs.push($rootScope.opsMenu[itemTab]); - //$scope.ecdapp.activeTabUrl = $rootScope.opsMenu[itemTab].url; - break; - } - } - } - $scope.ecdapp.gTabs = $rootScope.gTabs; - /* - angular.forEach($rootScope.opsMenu, function(item) { - if - // we check to see whether our object exists - var key = $scope.ecdapp.opsItem; - // if it's not already part of our keys array - if($rootScope.menuKeys.indexOf(key) === -1) { - // add it to our keys array - $rootScope.menuKeys.push(key); - // push this item to our final output array - $rootScope.gTabs.push(item); - $scope.ecdapp.activeTabUrl = item.url; - } else { - if (item.id === key) { - $scope.ecdapp.activeTabUrl = item.url; - } - } - }); - - - for (var menuTab = 0; menuTab < $scope.ecdapp.gTabs.length; menuTab++) { - if ($scope.ecdapp.gTabs[menuTab].id === key) { - $scope.ecdapp.activeTabUrl = $scope.ecdapp.gTabs[menuTab].url; - break; - } - } - */ - $scope.ecdapp.isInit = true; - $rootScope.activeTabsId = $scope.ecdapp.opsItem; - - $rootScope.$watch('activeTabsId', function (newVal, oldVal) { - if(newVal !== oldVal) { - var selectedTab; - for (selectedTab = 0; selectedTab < $rootScope.opsMenu.length; selectedTab++) { - if ($rootScope.opsMenu[selectedTab].id === newVal) { - //$scope.ecdapp.activeTabUrl = $rootScope.opsMenu[selectedTab].url; - break; - } - } - var selectedTabPanelElement = document.getElementById($rootScope.opsMenu[selectedTab].tabPanelId); - - var elem = null; - if (selectedTabPanelElement) { - elem = b2bDOMHelper.firstTabableElement(selectedTabPanelElement); - } - - if (elem) { - $timeout(function () { - elem.focus(); - }, 100); - } - } - }); - - - $scope.ecdapp.selectAppTenant = function(site) { - if(site != "Select Site") { - for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) { - if ($rootScope.site_tenant_map[indx].site === site) { - $scope.ecdapp.appTenants = $rootScope.site_tenant_map[indx].tenant; - break; - } - } - } - } - - $scope.ecdapp.selectCluster = function(tenant) { - if(tenant != "Select Tenant") { - for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) { - if ($rootScope.tenant_cluster_map[indx].tenant === tenant) { - $scope.ecdapp.appCluster = $rootScope.tenant_cluster_map[indx].cluster; - } - } - } - } - - var stopPolling; - //var doIframePolling; - $scope.ecdapp.appFrameReload = function(cluster, app) { - if(cluster != "Select K8s cluster") { - $scope.ecdapp.isFrameLoaded = false; - for (var indx = 0; indx < $rootScope.tenant_cluster_apps_map.length; indx++) { - if ($rootScope.tenant_cluster_apps_map[indx].cluster === cluster) { - if (app === 'prom') { - $scope.ecdapp.prom.url = $rootScope.tenant_cluster_apps_map[indx].prom; - } else if (app === 'grf') { - $scope.ecdapp.grf.url = $rootScope.tenant_cluster_apps_map[indx].grf; - } else { - $scope.ecdapp.k8.url = $rootScope.tenant_cluster_apps_map[indx].k8; - } - break; - } - } - stopPolling = $timeout(function () { - $timeout.cancel(stopPolling); - stopPolling = undefined; - $scope.ecdapp.isFrameLoaded = true; - },30000); - } - } - - $scope.ecdapp.cfyCnslFrameReload = function(site, app) { - if(site != "Select Site") { - $scope.ecdapp.isFrameLoaded = false; - for (var indx = 0; indx < $rootScope.site_cfy_cnsl_map.length; indx++) { - if ($rootScope.site_cfy_cnsl_map[indx].site === site) { - if (app === 'cfy') { - $scope.ecdapp.cfy.url = $rootScope.site_cfy_cnsl_map[indx].cfy; - } else { - $scope.ecdapp.cnsl.url = $rootScope.site_cfy_cnsl_map[indx].cnsl; - } - break; - } - } - stopPolling = $timeout(function () { - $timeout.cancel(stopPolling); - stopPolling = undefined; - $scope.ecdapp.isFrameLoaded = true; - },30000); - } - } - document.querySelector("iframe").addEventListener("load", function() { - $scope.ecdapp.isFrameLoaded = true; - $scope.$apply(); - }); - $scope.$on("$destroy",function() { - $timeout.cancel(stopPolling); - //$interval.cancel(doIframePolling); - }); - - /* - * $scope.ecdapp.selectK8Tenant = function(site) { - if(site != "Select Site") { - for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) { - if ($rootScope.site_tenant_map[indx].site === site) { - $scope.ecdapp.k8Tenants = $rootScope.site_tenant_map[indx].tenant; - break; - } - } - } - } - - $scope.ecdapp.selectK8App = function(t) { - if(t != "Select Tenant for K8s components") { - for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) { - if ($rootScope.tenant_cluster_map[indx].tenant === t) { - $scope.ecdapp.k8.url = $rootScope.tenant_cluster_map[indx].k8s; - break; - } - } - } - } - - $scope.ecdapp.selectGrfTenant = function(site) { - if(site != "Select Site") { - for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) { - if ($rootScope.site_tenant_map[indx].site === site) { - $scope.ecdapp.grfTenants = $rootScope.site_tenant_map[indx].tenant; - break; - } - } - } - } - - $scope.ecdapp.selectGrfApp = function(t) { - if(t != "Select Tenant for Grafana") { - for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) { - if ($rootScope.tenant_cluster_map[indx].tenant === t) { - $scope.ecdapp.grf.url = $rootScope.tenant_cluster_map[indx].grf; - break; - } - } - } - } - - $scope.ecdapp.selectPromTenant = function(site) { - if(site != "Select Site") { - for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) { - if ($rootScope.site_tenant_map[indx].site === site) { - $scope.ecdapp.promTenants = $rootScope.site_tenant_map[indx].tenant; - break; - } - } - } - } - - $scope.ecdapp.selectPromApp = function(t) { - if(t != "Select Tenant for Prometheus") { - for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) { - if ($rootScope.tenant_cluster_map[indx].tenant === t) { - $scope.ecdapp.prom.url = $rootScope.tenant_cluster_map[indx].prom; - break; - } - } - } - } - - doIframePolling = $interval(function () { - if(document.querySelector("iframe") && - document.querySelector("iframe").contentDocument.head && - document.querySelector("iframe").contentDocument.head.innerHTML != '') - { - $interval.cancel(doIframePolling); - doIframePolling = undefined; - $timeout.cancel(stopPolling); - stopPolling = undefined; - $scope.ecdapp.isCfyLoadDone = true; - } - },400); - - stopPolling = $timeout(function () { - //$interval.cancel(doIframePolling); - //doIframePolling = undefined; - $timeout.cancel(stopPolling); - stopPolling = undefined; - $scope.ecdapp.isCfyLoadDone = true; - },30000); - } - } - - */ - - -});
\ No newline at end of file diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs_view.html deleted file mode 100644 index aa5b1f8..0000000 --- a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs_view.html +++ /dev/null @@ -1,131 +0,0 @@ -<div id="page-content" ng-controller="tabsController"> - <div ng-show="ecdapp.isInit"> - <b2b-tabset tab-id-selected="activeTabsId"> - <b2b-tab ng-repeat="tab in ecdapp.gTabs" tab-item="tab" - id="{{tab.uniqueId}}" aria-controls="{{tab.tabPanelId}}" - ng-disabled="tab.disabled"> - {{tab.title}} - </b2b-tab> - </b2b-tabset> - </div> - - <div class="tab-content"> - <div id="threetab1x" role="tabpanel" aria-labelledby="uniqueTab1x" aria-hidden="{{'cfy'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'cfy'===activeTabsId}"> - <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;"> - <div class="span3 form-row"> - <label for="cfy-site-url">Site</label> - <select id="cfy-site-url" name="cfy-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.cfySite" ng-change="ecdapp.cfyCnslFrameReload(ecdapp.cfySite, 'cfy')" required> - <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option> - </select> - </div> - </div> - <div ng-hide="ecdapp.isFrameLoaded" class="span"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - <iframe id="cfy_frame" ng-show="ecdapp.isFrameLoaded" aria-expanded="true" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.cfy.url}}"> - </iframe> - </div> - <div id="threetab2x" role="tabpanel" aria-labelledby="uniqueTab2x" aria-hidden="{{'grf'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'grf'===activeTabsId}"> - <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;"> - <div class="span3 form-row"> - <label for="grf-site-url">Site</label> - <select id="grf-site-url" name="grf-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.grf.site" ng-change="ecdapp.selectAppTenant(ecdapp.grf.site)" required> - <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option> - </select> - </div> - <div class="span4 form-row"> - <label for="grf-ten-url">Tenant</label> - <select id="grf-ten-url" name="grf-ten-url" b2b-dropdown placeholder-text="Select Tenant" data-ng-model="ecdapp.grf.tenant" ng-change="ecdapp.selectCluster(ecdapp.grf.tenant)" required> - <option b2b-dropdown-list option-repeat="t in ecdapp.appTenants" value="{{t}}">{{t}}</option> - </select> - </div> - <div class="span3 form-row"> - <label for="grf-cluster-url">Cluster</label> - <select id="grf-cluster-url" name="grf-cluster-url" b2b-dropdown placeholder-text="Select K8s cluster" data-ng-model="ecdapp.grf.cluster" ng-change="ecdapp.appFrameReload(ecdapp.grf.cluster, 'grf')" required> - <option b2b-dropdown-list option-repeat="c in ecdapp.appCluster" value="{{c}}">{{c}}</option> - </select> - </div> - </div> - <div ng-hide="ecdapp.isFrameLoaded" class="span"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.grf.url}}"> - </iframe> - </div> - <div id="threetab3x" role="tabpanel" aria-labelledby="uniqueTab3x" aria-hidden="{{'cnsl'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'cnsl'===activeTabsId}"> - <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;"> - <div class="span3 form-row"> - <label for="cnsl-site-url">Site</label> - <select id="cnsl-site-url" name="cnsl-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.cnslSite" ng-change="ecdapp.cfyCnslFrameReload(ecdapp.cnslSite, 'cnsl')" required> - <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option> - </select> - </div> - </div> - <div ng-hide="ecdapp.isFrameLoaded" class="span"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.cnsl.url}}"> - </iframe> - </div> - <div id="threetab4x" role="tabpanel" aria-labelledby="uniqueTab4x" aria-hidden="{{'k8s'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'k8s'===activeTabsId}"> - <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;"> - <div class="span3 form-row"> - <label for="k8s-site-url">Site</label> - <select id="k8s-site-url" name="k8s-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.k8.site" ng-change="ecdapp.selectAppTenant(ecdapp.k8.site)" required> - <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option> - </select> - </div> - <div class="span6 form-row"> - <label for="k8s-ten-url">Tenant</label> - <select id="k8s-ten-url" name="k8s-ten-url" b2b-dropdown placeholder-text="Select Tenant" data-ng-model="ecdapp.k8.tenant" ng-change="ecdapp.selectCluster(ecdapp.k8.tenant)" required> - <option b2b-dropdown-list option-repeat="t in ecdapp.appTenants" value="{{t}}">{{t}}</option> - </select> - </div> - <div class="span3 form-row"> - <label for="k8s-cluster-url">Cluster</label> - <select id="k8s-cluster-url" name="k8s-cluster-url" b2b-dropdown placeholder-text="Select K8s cluster" data-ng-model="ecdapp.k8.cluster" ng-change="ecdapp.appFrameReload(ecdapp.k8.cluster, 'k8')" required> - <option b2b-dropdown-list option-repeat="c in ecdapp.appCluster" value="{{c}}">{{c}}</option> - </select> - </div> - </div> - <div ng-hide="ecdapp.isFrameLoaded" class="span"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.k8.url}}"> - </iframe> - </div> - <div id="threetab5x" role="tabpanel" aria-labelledby="uniqueTab5x" aria-hidden="{{'prom'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'prom'===activeTabsId}"> - <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;"> - <div class="span3 form-row"> - <label for="prom-site-url">Site</label> - <select id="prom-site-url" name="prom-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.prom.site" ng-change="ecdapp.selectAppTenant(ecdapp.prom.site)" required> - <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option> - </select> - </div> - <div class="span6 form-row"> - <label for="prom-ten-url">Tenant</label> - <select id="prom-ten-url" name="prom-ten-url" b2b-dropdown placeholder-text="Select Tenant" data-ng-model="ecdapp.prom.tenant" ng-change="ecdapp.selectCluster(ecdapp.prom.tenant)" required> - <option b2b-dropdown-list option-repeat="t in ecdapp.appTenants" value="{{t}}">{{t}}</option> - </select> - </div> - <div class="span3 form-row"> - <label for="prom-cluster-url">Cluster</label> - <select id="prom-cluster-url" name="prom-cluster-url" b2b-dropdown placeholder-text="Select K8s cluster" data-ng-model="ecdapp.prom.cluster" ng-change="ecdapp.appFrameReload(ecdapp.prom.cluster, 'prom')" required> - <option b2b-dropdown-list option-repeat="c in ecdapp.appCluster" value="{{c}}">{{c}}</option> - </select> - </div> - </div> - <div ng-hide="ecdapp.isFrameLoaded" class="span"> - <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i> - Please wait while the content loads. - </div> - <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.prom.url}}"> - </iframe> - </div> - </div> - -</div>
\ No newline at end of file @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <!-- Add oparent parent --> - + <parent> <groupId>org.onap.oparent</groupId> <artifactId>oparent</artifactId> @@ -14,7 +14,7 @@ <!-- Maven parent project for convenience of building and cleaning --> <groupId>org.onap.ccsdk.dashboard</groupId> <artifactId>ccsdk-app-parent</artifactId> - <version>1.3.2-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>pom</packaging> <name>ccsdk-dashboard</name> @@ -38,5 +38,17 @@ <url>${onap.nexus.url}/content/repositories/snapshots</url> </snapshotRepository> </distributionManagement> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>versions-maven-plugin</artifactId> + <version>2.5</version> + <configuration> + <generateBackupPoms>false</generateBackupPoms> + </configuration> + </plugin> + </plugins> + </build> </project> diff --git a/version.properties b/version.properties index 0969948..668657e 100644 --- a/version.properties +++ b/version.properties @@ -3,8 +3,8 @@ # because they are used in Jenkins, whose plug-in doesn't support major=1 -minor=3 -patch=2 +minor=4 +patch=0 base_version=${major}.${minor}.${patch} |