diff options
Diffstat (limited to 'ccsdk-app-common/src/main')
41 files changed, 5131 insertions, 0 deletions
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 new file mode 100644 index 0000000..1962c4f --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CloudifyController.java @@ -0,0 +1,637 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest; +import org.onap.ccsdk.dashboard.exception.DashboardControllerException; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprint; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintUpload; +import org.onap.ccsdk.dashboard.model.CloudifyDeployment; +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentRequest; +import org.onap.ccsdk.dashboard.model.CloudifyExecution; +import org.onap.ccsdk.dashboard.model.CloudifyExecutionList; +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.rest.IControllerRestClient; +import org.openecomp.portalsdk.core.domain.User; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.portalsdk.core.web.support.UserUtils; +import org.slf4j.MDC; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +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.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.client.HttpStatusCodeException; + +/** + * Controller for Cloudify features: blueprints, deployments, executions. + * Methods serve Ajax requests made by Angular scripts on pages that show + * content. + */ +@Controller +@RequestMapping("/") +public class CloudifyController extends DashboardRestrictedBaseController { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CloudifyController.class); + + /** + * Enum for selecting an item type. + */ + public enum CloudifyDataItem { + BLUEPRINT, DEPLOYMENT, EXECUTION; + } + + private static final String BLUEPRINTS_PATH = "blueprints"; + private static final String VIEW_BLUEPRINTS_PATH = "viewblueprints"; + private static final String DEPLOYMENTS_PATH = "deployments"; + private static final String EXECUTIONS_PATH = "executions"; + + /** + * Supports sorting blueprints by ID + */ + private static Comparator<CloudifyBlueprint> blueprintComparator = Comparator.comparing(o -> o.id); + + /** + * Supports sorting deployments by ID + */ + private static Comparator<CloudifyDeployment> deploymentComparator = Comparator.comparing(o -> o.id); + + /** + * Supports sorting executions by ID + */ + private static Comparator<CloudifyExecution> executionComparator = Comparator.comparing(o -> o.id); + + /** + * 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 DashboardControllerException + * On any error; e.g., Network failure. + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private String getItemListForPage(long userId, CloudifyDataItem option, int pageNum, int pageSize) + throws DashboardControllerException, JsonProcessingException { + IControllerRestClient restClient = getControllerRestClient(userId); + List itemList; + switch (option) { + case BLUEPRINT: + itemList = restClient.getBlueprints().items; + itemList.sort(blueprintComparator); + break; + case DEPLOYMENT: + itemList = restClient.getDeployments().items; + itemList.sort(deploymentComparator); + break; + default: + throw new DashboardControllerException( + "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); + return objectMapper.writeValueAsString(model); + } + + /** + * 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, CloudifyDataItem option) { + String outboundJson = null; + try { + User appUser = UserUtils.getUserSession(request); + if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0) { + throw new DashboardControllerException("getItemListForPageWrapper: Failed to get application user"); + } + int pageNum = getRequestPageNumber(request); + int pageSize = getRequestPageSize(request); + outboundJson = getItemListForPage(appUser.getId(), option, pageNum, pageSize); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception", ex); + RestResponseError result; + 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() + "\"}"; + } + } + return outboundJson; + } + + /** + * Serves one page of blueprints + * + * @param request + * HttpServletRequest + * @return List of CloudifyBlueprint objects + */ + @RequestMapping(value = {BLUEPRINTS_PATH}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getBlueprintsByPage(HttpServletRequest request) { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + String json = getItemListForPageWrapper(request, CloudifyDataItem.BLUEPRINT); + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return json; + } + + /** + * 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) { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + String json = getItemListForPageWrapper(request, CloudifyDataItem.DEPLOYMENT); + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return json; + } + + /** + * Gets the specified blueprint metadata. + * + * @param id + * Blueprint ID + * @param request + * HttpServletRequest + * @return Blueprint as JSON; or error. + * @throws JsonProcessingException + * on serialization error + * + */ + @RequestMapping(value = {BLUEPRINTS_PATH + "/{id}"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getBlueprintById(@PathVariable("id") String id, HttpServletRequest request) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.getBlueprint(id); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("getBlueprintById failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Gets the specified blueprint content for viewing. + * + * @param id + * Blueprint ID + * @param request + * HttpServletRequest + * @return Blueprint as YAML; or error. + * @throws JsonProcessingException + * on serialization error + * + */ + @RequestMapping(value = { + VIEW_BLUEPRINTS_PATH + "/{id}"}, method = RequestMethod.GET, produces = "application/yaml") + @ResponseBody + public String viewBlueprintContentById(@PathVariable("id") String id, HttpServletRequest request) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.viewBlueprint(id); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("getBlueprintContentById failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Processes request to upload a blueprint from a remote server. + * + * @param request + * HttpServletRequest + * @param blueprint + * Cloudify blueprint + * @return Blueprint as uploaded; or error. + * @throws JsonProcessingException + * on serialization error + */ + @RequestMapping(value = {BLUEPRINTS_PATH}, method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String uploadBlueprint(HttpServletRequest request, @RequestBody CloudifyBlueprintUpload blueprint) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.uploadBlueprint(blueprint); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("uploadBlueprint failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Deletes the specified blueprint. + * + * @param id + * Blueprint ID + * @param request + * HttpServletRequest + * @param response + * HttpServletResponse + * @return No content on success; error on failure. + * @throws JsonProcessingException + * On serialization failure + */ + @RequestMapping(value = {BLUEPRINTS_PATH + "/{id}"}, method = RequestMethod.DELETE, produces = "application/json") + @ResponseBody + public String deleteBlueprint(@PathVariable("id") String id, HttpServletRequest request, + HttpServletResponse response) throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + int code = restClient.deleteBlueprint(id); + response.setStatus(code); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("deleteBlueprint failed on ID " + id, t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + if (result == null) { + return null; + } else { + return objectMapper.writeValueAsString(result); + } + } + + /** + * Gets the specified deployment. + * + * @param id + * Deployment ID + * @param request + * HttpServletRequest + * @return Deployment for the specified ID; error on failure. + * @throws JsonProcessingException + * On serialization failure + * + */ + @RequestMapping(value = {DEPLOYMENTS_PATH + "/{id}"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getDeploymentById(@PathVariable("id") String id, HttpServletRequest request) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.getDeployment(id); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("getDeploymentById failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Processes request to create a deployment based on a blueprint. + * + * @param request + * HttpServletRequest + * @param deployment + * Deployment to upload + * @return Body of deployment; error on failure + * @throws JsonProcessingException + * On serialization failure + */ + @RequestMapping(value = {DEPLOYMENTS_PATH}, method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String createDeployment(HttpServletRequest request, @RequestBody CloudifyDeploymentRequest deployment) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.createDeployment(deployment); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("createDeployment failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Deletes the specified deployment. + * + * @param id + * Deployment ID + * @param ignoreLiveNodes + * Boolean indicator whether to force a delete in case of live + * nodes + * @param request + * HttpServletRequest + * @param response + * HttpServletResponse + * @return Passes through HTTP status code from remote endpoint; no body on + * success + * @throws JsonProcessingException + * on serialization failure + */ + @RequestMapping(value = { + DEPLOYMENTS_PATH + "/{id}"}, method = RequestMethod.DELETE, produces = "application/json") + @ResponseBody + public String deleteDeployment(@PathVariable("id") String id, + @RequestParam(value = "ignore_live_nodes", required = false) Boolean ignoreLiveNodes, + HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + int code = restClient.deleteDeployment(id, ignoreLiveNodes == null ? false : ignoreLiveNodes); + response.setStatus(code); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("deleteDeployment failed on ID " + id, t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + if (result == null) { + return null; + } else { + return objectMapper.writeValueAsString(result); + } + } + + /** + * Gets and serves one page of executions: + * <OL> + * <LI>Gets all deployments; OR uses the specified deployment ID if the + * query parameter is present + * <LI>Gets executions for each deployment ID + * <LI>Sorts by execution ID + * <LI>Reduces the list to the page size (if needed) + * <LI>If the optional request parameter "status" is present, reduces the + * list to the executions with that status. + * </OL> + * + * @param request + * HttpServletRequest + * @param deployment_id + * Optional request parameter; if found, only executions for that + * deployment ID are returned. + * @param status + * Optional request parameter; if found, only executions with + * that status are returned. + * @return List of CloudifyExecution objects + * @throws JsonProcessingException + * on serialization failure + */ + @SuppressWarnings("unchecked") + @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 = "status", required = false) String status) throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + List<CloudifyExecution> itemList = new ArrayList<>(); + IControllerRestClient restClient = getControllerRestClient(request); + List<String> depIds = new ArrayList<>(); + if (deployment_id == null) { + CloudifyDeploymentList depList = restClient.getDeployments(); + for (CloudifyDeployment cd : depList.items) { + depIds.add(cd.id); + } + } else { + depIds.add(deployment_id); + } + for (String depId : depIds) { + CloudifyExecutionList exeList = restClient.getExecutions(depId); + itemList.addAll(exeList.items); + } + // Filter down to specified status as needed + if (status != null) { + itemList.removeIf(ce -> !status.equals(ce.status)); + } + itemList.sort(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) { + result = new RestResponseError("getExecutionsByPage failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + 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 JsonProcessingException + * on serialization failure + */ + @RequestMapping(value = {EXECUTIONS_PATH + "/{id}"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getExecutionByIdAndDeploymentId(@PathVariable("id") String execution_id, + @RequestParam("deployment_id") String deployment_id, HttpServletRequest request) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.getExecutions(deployment_id); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Processes request to create an execution based on a deployment. + * + * @param request + * HttpServletRequest + * @param execution + * Execution model + * @return Information about the execution + * @throws JsonProcessingException + * on serialization failure + */ + @RequestMapping(value = {EXECUTIONS_PATH}, method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String startExecution(HttpServletRequest request, @RequestBody CloudifyExecutionRequest execution) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.startExecution(execution); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("startExecution failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * 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 through HTTP status code from remote endpoint; no body on success + * @throws JsonProcessingException + * on serialization failure + */ + @RequestMapping(value = {EXECUTIONS_PATH + "/{id}"}, method = RequestMethod.DELETE, produces = "application/json") + @ResponseBody + public String cancelExecution(@PathVariable("id") String id, + @RequestParam(value = "deployment_id") String deploymentId, @RequestParam(value = "action") String action, + HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + int code = restClient.cancelExecution(id, deploymentId, action); + response.setStatus(code); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("cancelExecution failed on ID " + id, t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + if (result == null) { + return null; + } else { + return objectMapper.writeValueAsString(result); + } + } +} 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 new file mode 100644 index 0000000..9f22456 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ConsulController.java @@ -0,0 +1,445 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.net.URI; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import javax.servlet.http.HttpServletRequest; + +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.RestResponsePage; +import org.onap.ccsdk.dashboard.rest.IControllerRestClient; +import org.onap.ccsdk.dashboard.exception.DashboardControllerException; +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.RestResponseSuccess; +import org.openecomp.portalsdk.core.domain.User; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.portalsdk.core.web.support.UserUtils; +import org.slf4j.MDC; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +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.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.client.HttpStatusCodeException; + +/** + * Controller for Consul features: health checks of services, nodes, data + * centers. Methods serve Ajax requests made by Angular scripts on pages that + * show content. + */ +@Controller +@RequestMapping("/healthservices") +public class ConsulController extends DashboardRestrictedBaseController { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ConsulController.class); + + /** + * Enum for selecting an item type. + */ + public enum ConsulDataItem { + SERVICE_INFO, SERVICE_HEALTH, NODES, DATACENTERS; + } + + private static final String NODES_PATH = "/nodes"; + private static final String SERVICES_PATH = "/services"; + + /** + * Supports sorting results by node name + */ + private static Comparator<ConsulNodeInfo> nodeHealthComparator = Comparator.comparing(o -> o.node); + + /** + * Supports sorting results by service name + */ + private static Comparator<ConsulServiceHealth> serviceHealthComparator = Comparator.comparing(o -> o.serviceName); + + /** + * Supports sorting results by service name + */ + private static Comparator<ConsulServiceInfo> serviceInfoComparator = Comparator.comparing(o -> o.name); + + /** + * Gets one page of objects and supporting information via the REST client. On + * success, returns a page of objects as String. + * + * @param option + * Specifies which item 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 DashboardControllerException, + * JsonProcessingException On any error; e.g., Network failure. + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + private String getItemListForPage(long userId, ConsulDataItem option, int pageNum, int pageSize) + throws DashboardControllerException, JsonProcessingException { + IControllerRestClient restClient = getControllerRestClient(userId); + List itemList; + switch (option) { + case NODES: + itemList = restClient.getNodes(); + itemList.sort(nodeHealthComparator); + break; + case DATACENTERS: + itemList = restClient.getDatacenters(); + break; + default: + throw new DashboardControllerException( + "getItemListForPage failed: unimplemented case: " + option.name()); + } + + // Shrink if needed + if (itemList.size() > pageSize) { + itemList = getPageOfList(pageNum, pageSize, itemList); + } + int pageCount = (int) Math.ceil((double) itemList.size() / pageSize); + RestResponsePage<List> model = new RestResponsePage<>(itemList.size(), pageCount, itemList); + return objectMapper.writeValueAsString(model); + } + + /** + * 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, ConsulDataItem option) { + String outboundJson; + try { + User appUser = UserUtils.getUserSession(request); + if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0) { + throw new DashboardControllerException("getItemListForPageWrapper: Failed to get application user"); + } + int pageNum = getRequestPageNumber(request); + int pageSize = getRequestPageSize(request); + outboundJson = getItemListForPage(appUser.getId(), option, pageNum, pageSize); + } catch (Exception ex) { + // Remote service failed; build descriptive error message + logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception", ex); + RestResponseError 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() + "\"}"; + } + } + return outboundJson; + } + + /** + * Serves all service details. + * + * @param request + * HttpServletRequest + * @return List of ConsulServiceInfo objects, as JSON + * @throws JsonProcessingException + * if serialization fails + */ + @RequestMapping(value = {SERVICES_PATH}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getServices(HttpServletRequest request) throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + Object result; + try { + IControllerRestClient restClient = getControllerRestClient(request); + List<ConsulServiceInfo> itemList = restClient.getServices(); + itemList.sort(serviceInfoComparator); + result = itemList; + } catch (Exception t) { + result = new RestResponseError("getServices failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Serves service health details - not paginated. + * + * @param request + * HttpServletRequest + * @param serviceId + * Service ID + * @return List of ConsulServiceHealth objects as JSON + * @throws JsonProcessingException + * if serialization fails + */ + @RequestMapping(value = { + SERVICES_PATH + "/{serviceId}"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getServiceHealthDetails(HttpServletRequest request, @PathVariable String serviceId) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + Object result; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.getServiceHealth(serviceId); + } catch (Exception t) { + result = new RestResponseError("getServiceHealthDetails failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Serves service health historical data - not paginated. + * + * @param request + * HttpServletRequest + * @param serviceName + * Service name as path parameter + * @param start + * Earliest date-time as an ISO 8061 value, such as + * 2007-12-03T10:15:30+01:00 + * @param end + * Latest date-time as an ISO 8061 value, such as + * 2007-12-03T10:15:30+01:00 + * @return List of ConsulServiceHealth objects as JSON + * @throws JsonProcessingException + * if serialization fails + */ + @RequestMapping(value = {"/svchist/{serviceName}"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getServiceHealthHistory(HttpServletRequest request, // + @PathVariable String serviceName, // + @RequestParam String start, // + @RequestParam String end) throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + Object result = null; + try { + Instant startDateTime = Instant.parse(start); + Instant endDateTime = Instant.parse(end); + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.getServiceHealthHistory(serviceName, startDateTime, endDateTime); + } catch (HttpStatusCodeException e) { + // Rare, but can happen + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + // Work around the hack to report no-match. + result = new RestResponseError("getServiceHealthHistory failed: " + t.getMessage()); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Serves one page of service health information by getting all service names, + * then iterating over them to get the health of each service. + * + * ECOMP-C does NOT provide an API to get the health of all services in one + * request. + * + * @param request + * HttpServletRequest + * @return List of ConsulServiceHealth objects, as JSON + * @throws JsonProcessingException + * on serialization exception + */ + @SuppressWarnings("unchecked") + @RequestMapping(value = {"/serviceshealth"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getServicesHealth(HttpServletRequest request) throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + List<ConsulServiceHealth> itemList = new ArrayList<>(); + IControllerRestClient restClient = getControllerRestClient(request); + List<ConsulServiceInfo> svcInfoList = restClient.getServices(); + for (ConsulServiceInfo csi : svcInfoList) { + List<ConsulServiceHealth> csh = restClient.getServiceHealth(csi.name); + itemList.addAll(csh); + } + itemList.sort(serviceHealthComparator); + // 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) { + result = new RestResponseError("getServicesHealth failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Serves one page of node information. + * + * @param request + * HttpServletRequest + * @return List of ConsulNodeInfo objects, as JSON + */ + @RequestMapping(value = {NODES_PATH}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getNodesInfo(HttpServletRequest request) { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + String json = getItemListForPageWrapper(request, ConsulDataItem.NODES); + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return json; + } + + /** + * Serves node services health details - not paginated. + * + * @param request + * HttpServletRequest + * @param nodeName + * Node name + * @return List of ConsulServiceHealth objects as JSON + * @throws JsonProcessingException + * if serialization fails + */ + @RequestMapping(value = {NODES_PATH + "/{nodeName}"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getNodeServicesHealth(HttpServletRequest request, @PathVariable String nodeName) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + Object result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + result = restClient.getNodeServicesHealth(nodeName); + } catch (Exception t) { + result = new RestResponseError("getNodeServicesHealth failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } + + /** + * Serves one page of data centers health. + * + * @param request + * HttpServletRequest + * @return List of ConsulHealthStatus objects + */ + @RequestMapping(value = {"/datacenters"}, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getDatacentersHealth(HttpServletRequest request) { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + String json = getItemListForPageWrapper(request, ConsulDataItem.DATACENTERS); + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + 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 JsonProcessingException + * on serialization error + */ + @RequestMapping(value = {"/register"}, method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String registerService(HttpServletRequest request, @RequestBody ConsulHealthServiceRegistration registration) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + URI uri = restClient.registerService(registration); + result = new RestResponseSuccess(uri.toString()); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("registerService failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + 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 JsonProcessingException + * on serialization error + */ + @RequestMapping(value = { + "/deregister" + "/{serviceName}"}, method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String deregisterService(HttpServletRequest request, @PathVariable String serviceName) + throws JsonProcessingException { + MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(new Date())); + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + ECTransportModel result = null; + try { + IControllerRestClient restClient = getControllerRestClient(request); + int code = restClient.deregisterService(serviceName); + result = new RestResponseSuccess("Deregistration yielded code " + Integer.toString(code)); + } catch (HttpStatusCodeException e) { + result = new RestResponseError(e.getResponseBodyAsString()); + } catch (Exception t) { + result = new RestResponseError("deregisterService failed", t); + } + MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(new Date())); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + return objectMapper.writeValueAsString(result); + } +} 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 new file mode 100644 index 0000000..618e84d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardHomeController.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.controller; + +import java.util.ArrayList; + +import javax.servlet.http.HttpServletRequest; + +import org.onap.ccsdk.dashboard.domain.ControllerEndpoint; +import org.onap.ccsdk.dashboard.exception.DashboardControllerException; +import org.onap.ccsdk.dashboard.model.ControllerEndpointCredentials; +import org.onap.ccsdk.dashboard.model.ControllerEndpointTransport; +import org.onap.ccsdk.dashboard.model.RestResponseError; +import org.onap.ccsdk.dashboard.model.RestResponseSuccess; +import org.onap.ccsdk.dashboard.service.ControllerEndpointService; +import org.openecomp.portalsdk.core.domain.User; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.web.support.UserUtils; +import org.springframework.beans.factory.annotation.Autowired; +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; +import org.springframework.web.servlet.ModelAndView; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * This controller maps requests for the application's landing page, which is an + * Angular single-page application. + */ +@Controller +@RequestMapping("/") +public class DashboardHomeController extends DashboardRestrictedBaseController { + + /** + * This path is embedded in the database, so it's nontrivial to change. + */ + public static final String APP_CONTEXT_PATH = "/ecd"; + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DashboardHomeController.class); + + @Autowired + private ControllerEndpointService controllerEndpointService; + + /** + * For general use in these methods + */ + private final ObjectMapper mapper; + + private static final String CONTROLLERS_PATH = "controllers"; + + /** + * Spring autowires fields AFTER the constructor is called. + */ + public DashboardHomeController() { + mapper = new ObjectMapper(); + // Do not serialize null values + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + /** + * @return View name key, which is resolved to a file using an Apache tiles + * "definitions.xml" file. + */ + @RequestMapping(value = { APP_CONTEXT_PATH }, method = RequestMethod.GET) + public ModelAndView dbcDefaultController() { + // a model is only useful for JSP; this app is angular. + return new ModelAndView("oom_home_tdkey"); + } + + /** + * Gets the available controller endpoints. + * + * @param request + * HttpServletRequest + * @return List of ControllerEndpointTransport objects, or an error on failure + */ + @RequestMapping(value = { CONTROLLERS_PATH }, method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getControllers(HttpServletRequest request) { + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + String outboundJson = null; + // Static data + ControllerEndpointCredentials[] configured = getControllerEndpoints(); + try { + User appUser = UserUtils.getUserSession(request); + if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0) + throw new DashboardControllerException("getControllers: Failed to get application user"); + ControllerEndpointCredentials selectedInDb = getOrSetControllerEndpointSelection(appUser.getId()); + // Built result from properties + ArrayList<ControllerEndpointTransport> list = new ArrayList<>(); + for (ControllerEndpointCredentials ctrl : configured) { + // Check if this is the selected endpoint in DB + boolean selected = (selectedInDb != null && selectedInDb.getUrl() != null + && selectedInDb.getUrl().equals(ctrl.getUrl())); + // Result has no privileged information + ControllerEndpointTransport transport = new ControllerEndpointTransport(selected, ctrl.getName(), + ctrl.getUrl()); + list.add(transport); + } + outboundJson = mapper.writeValueAsString(list); + } catch (Exception ex) { + RestResponseError response = new RestResponseError("Failed to get controller endpoint list", ex); + outboundJson = response.toJson(); + } + 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 DashboardControllerException, + * if application user is not found + * @throws JsonProcessingException + * If serialization fails + */ + @RequestMapping(value = { CONTROLLERS_PATH }, method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String setControllerSelection(HttpServletRequest request, @RequestBody ControllerEndpointTransport endpoint) + throws DashboardControllerException, JsonProcessingException { + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + String outboundJson = null; + User appUser = UserUtils.getUserSession(request); + if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0) + throw new DashboardControllerException("setControllerSelection: Failed to get application user"); + ControllerEndpoint dbEntry = new ControllerEndpoint(appUser.getId(), endpoint.getName(), endpoint.getUrl()); + controllerEndpointService.updateControllerEndpointSelection(dbEntry); + RestResponseSuccess success = new RestResponseSuccess("Updated selection to " + endpoint.getName()); + outboundJson = mapper.writeValueAsString(success); + return outboundJson; + } +} 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 new file mode 100644 index 0000000..6f80d22 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardRestrictedBaseController.java @@ -0,0 +1,275 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.controller; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.onap.ccsdk.dashboard.exception.DashboardControllerException; +import org.onap.ccsdk.dashboard.rest.ControllerRestClientMockImpl; +import org.onap.ccsdk.dashboard.service.ControllerEndpointService; +import org.onap.ccsdk.dashboard.domain.ControllerEndpoint; +import org.onap.ccsdk.dashboard.rest.IControllerRestClient; +import org.onap.ccsdk.dashboard.util.DashboardProperties; +import org.onap.ccsdk.dashboard.model.ControllerEndpointCredentials; +import org.onap.ccsdk.dashboard.rest.ControllerRestClientImpl; +import org.openecomp.portalsdk.core.controller.RestrictedBaseController; +import org.openecomp.portalsdk.core.domain.User; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.web.support.UserUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * This base class provides utility methods to child controllers. + */ +public class DashboardRestrictedBaseController extends RestrictedBaseController { + + /** + * Logger that conforms with ECOMP guidelines + */ + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DashboardRestrictedBaseController.class); + + /** + * 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 = "pageNum"; + + /** + * Query parameter for desired items per page + */ + protected static final String PAGE_SIZE_QUERY_PARAM = "viewPerPage"; + + /** + * For general use in these methods and subclasses + */ + protected final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * Application properties - NOT available to constructor. + */ + @Autowired + private DashboardProperties appProperties; + + /** + * For getting selected controller + */ + @Autowired + private ControllerEndpointService controllerEndpointService; + + /** + * Hello Spring, here's your no-arg constructor. + */ + public DashboardRestrictedBaseController() { + // Do not serialize null values + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + /** + * 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 = 50; + 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); + } + + /** + * Gets all configured controllers from properties. + * + * @return Array of ControllerEndpointRestricted objects + * @throws IllegalStateException + * if a required property is not found + */ + protected ControllerEndpointCredentials[] getControllerEndpoints() { + final String[] controllerKeys = appProperties.getCsvListProperty(DashboardProperties.CONTROLLER_KEY_LIST); + ControllerEndpointCredentials[] controllers = new ControllerEndpointCredentials[controllerKeys.length]; + for (int i = 0; i < controllerKeys.length; ++i) { + String key = controllerKeys[i]; + final String name = appProperties.getControllerProperty(key, DashboardProperties.CONTROLLER_SUBKEY_NAME); + final String url = appProperties.getControllerProperty(key, DashboardProperties.CONTROLLER_SUBKEY_URL); + final String user = appProperties.getControllerProperty(key, + DashboardProperties.CONTROLLER_SUBKEY_USERNAME); + final String pass = appProperties.getControllerProperty(key, + DashboardProperties.CONTROLLER_SUBKEY_PASSWORD); + final boolean encr = Boolean.parseBoolean ( + appProperties.getControllerProperty(key, DashboardProperties.CONTROLLER_SUBKEY_ENCRYPTED)); + logger.debug(EELFLoggerDelegate.debugLogger, "getConfiguredControllers: key {} yields url {}", key, url); + controllers[i] = new ControllerEndpointCredentials(false, name, url, user, pass, encr); + } + return controllers; + } + + /** + * Gets the controller endpoint for the specified user ID. Chooses the first + * one from properties if the user has not selected one previously. + * + * @param userId + * Database User ID + * @return ControllerEndpointCredentials for the specified user + */ + protected ControllerEndpointCredentials getOrSetControllerEndpointSelection(long userId) { + // Always need the complete list from properties + ControllerEndpointCredentials[] configured = getControllerEndpoints(); + // See if the database has an entry for this user + ControllerEndpoint dbEntry = controllerEndpointService.getControllerEndpointSelection(userId); + // If no row found DAO returns an object with null entries. + if (dbEntry == null || dbEntry.getName() == null) { + // Arbitrarily choose the first one + ControllerEndpointCredentials first = configured[0]; + dbEntry = new ControllerEndpoint(userId, first.getName(), first.getUrl()); + controllerEndpointService.updateControllerEndpointSelection(dbEntry); + } + // Fetch complete details for the selected item + ControllerEndpointCredentials selected = null; + for (ControllerEndpointCredentials cec : configured) { + if (dbEntry.getUrl().equals(cec.getUrl())) { + selected = cec; + break; + } + } + // Defend against a stale database entry. + if (selected == null) { + selected = configured[0]; + dbEntry = new ControllerEndpoint(userId, selected.getName(), selected.getUrl()); + controllerEndpointService.updateControllerEndpointSelection(dbEntry); + } + return selected; + } + + /** + * Convenience method that gets the user ID from the session and fetches the + * REST client. Factors code out of subclass methods. + * + * @param request + * HttpServletRequest + * @return REST client appropriate for the user + * @throws DashboardControllerException + */ + protected IControllerRestClient getControllerRestClient(HttpServletRequest request) throws DashboardControllerException { + User appUser = UserUtils.getUserSession(request); + if (appUser == null || appUser.getLoginId() == null || appUser.getLoginId().length() == 0) + throw new DashboardControllerException("getControllerRestClient: Failed to get application user"); + return getControllerRestClient(appUser.getId()); + } + + /** + * Gets a REST client; either a mock client (returns canned data), or a real + * client with appropriate credentials from properties. + * + * @return REST client. + * @throws DashboardControllerException on any failure; e.g., if the password cannot be decrypted. + */ + protected IControllerRestClient getControllerRestClient(long userId) throws DashboardControllerException { + IControllerRestClient result = null; + // Be robust to missing development-only property + boolean mock = false; + if (appProperties.containsProperty(DashboardProperties.CONTROLLER_MOCK_DATA)) + mock = appProperties.getBooleanProperty(DashboardProperties.CONTROLLER_MOCK_DATA); + if (mock) { + result = new ControllerRestClientMockImpl(); + } else { + try { + ControllerEndpointCredentials details = getOrSetControllerEndpointSelection(userId); + final String clearText = details.getEncryptedPassword() ? details.decryptPassword() : details.getPassword(); + result = new ControllerRestClientImpl(details.getUrl(), details.getUsername(), clearText); + } + catch (Exception ex) { + logger.error("getControllerRestClient failed", ex); + throw new DashboardControllerException(ex); + } + } + return result; + } + +} 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 new file mode 100644 index 0000000..953adff --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ECDSingleSignOnController.java @@ -0,0 +1,290 @@ +/*- + * ================================================================================ + * ECOMP Portal SDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ================================================================================ + */ + +package org.onap.ccsdk.dashboard.controller; + +import java.io.UnsupportedEncodingException; + +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.onap.ccsdk.dashboard.exception.DashboardControllerException; +import org.openecomp.portalsdk.core.auth.LoginStrategy; +import org.openecomp.portalsdk.core.command.LoginBean; +import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController; +import org.openecomp.portalsdk.core.domain.User; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.menu.MenuProperties; +import org.openecomp.portalsdk.core.onboarding.exception.PortalAPIException; +import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler; +import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants; +import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties; +import org.openecomp.portalsdk.core.service.LoginService; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.portalsdk.core.web.support.AppUtils; +import org.openecomp.portalsdk.core.web.support.UserUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.util.WebUtils; + +@Controller +@RequestMapping("/") +/** + * Replicated from + * org.openecomp.portalapp.controller.core.SingleSignOnController to modify the + * behavior of sending user's browser on a detour of Portal app to get the + * EPService cookie. + */ +public class ECDSingleSignOnController extends UnRestrictedBaseController { + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ECDSingleSignOnController.class); + private static final String REDIRECT = "redirect:"; + + @Autowired + private LoginService loginService; + + @Autowired + private LoginStrategy loginStrategy; + + private String viewName; + private String welcomeView; + + /** + * Handles requests directed to the single sign-on page by the session timeout + * interceptor. + * + * @param request + * HttpServletRequest + * @param response + * HttpServletResponse + * @return Redirect to an appropriate address + * @throws DashboardControllerException + * User not found + * @throws PortalAPIException + * User ID can't be fetched + * @throws UnsupportedEncodingException + * Encoding fails + */ + @RequestMapping(value = { "/single_signon.htm" }, method = RequestMethod.GET) + public ModelAndView singleSignOnLogin(HttpServletRequest request, HttpServletResponse response) + throws DashboardControllerException, PortalAPIException, UnsupportedEncodingException { + + Map<String, String> model = new HashMap<>(); + HashMap<String, String> additionalParamsMap = new HashMap<>(); + LoginBean commandBean = new LoginBean(); + + // SessionTimeoutInterceptor sets these parameters + String forwardURL = URLDecoder.decode(request.getParameter("forwardURL"), "UTF-8"); + String redirectToPortal = request.getParameter("redirectToPortal"); + + if (isLoginCookieExist(request) && redirectToPortal == null) { + HttpSession session = null; + session = AppUtils.getSession(request); + User user = UserUtils.getUserSession(request); + if (session == null || user == null) { + + final String authMech = SystemProperties.getProperty(SystemProperties.AUTHENTICATION_MECHANISM); + String userId = loginStrategy.getUserId(request); + commandBean.setUserid(userId); + try { + commandBean = getLoginService().findUser(commandBean, + (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), + additionalParamsMap); + } catch (Exception ex) { + logger.error("singleSignOnLogin failed", ex); + throw new DashboardControllerException(ex); + } + if (commandBean.getUser() == null) { + String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) + ? commandBean.getLoginErrorMessage() + : SystemProperties.MESSAGE_KEY_LOGIN_ERROR_USER_NOT_FOUND; + model.put(LoginStrategy.ERROR_MESSAGE_KEY, SystemProperties.getProperty(loginErrorMessage)); + final String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL) + + "?noUserError=Yes"; + logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: user is null, redirect URL is {}", + redirectUrl); + return new ModelAndView(REDIRECT + redirectUrl); + } else { + // store the user's information in the session + String loginMethod; + if (null == authMech || "".equals(authMech) || "BOTH".equals(authMech)) { + loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP); + } else if ("CSP".equals(authMech)) { + loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP); + } else { + loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_WEB_JUNCTION); + } + UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(), + commandBean.getBusinessDirectMenu(), loginMethod); + initateSessionMgtHandler(request); + logger.debug(EELFLoggerDelegate.debugLogger, + "singleSignOnLogin: create new user session for expired user {}; user {} exists in the system", + userId, commandBean.getUser().getOrgUserId()); + return new ModelAndView(REDIRECT + forwardURL); + } + } // user is null or session is null + else { + // both user and session are non-null. + logger.info(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: redirecting to the forwardURL {}", + forwardURL); + return new ModelAndView(REDIRECT + forwardURL); + } + } else { + /* + * Login cookie not found, or redirect-to-portal parameter was found. + */ + if (isPortalAvailable()) { + /* + * Redirect the user to the portal with a suitable return URL. The forwardURL + * parameter that arrives as a parameter is a partial (not absolute) request + * path for a page in the application. The challenge here is to compute the + * correct absolute path for the original request so the portal can redirect the + * user back to the right place. If the application sits behind WebJunction, or + * if separate FE-BE hosts are used, then the URL yielded by the request has a + * host name that is not reachable by the user. + */ + String returnToAppUrl = null; + if (SystemProperties.containsProperty(SystemProperties.APP_BASE_URL)) { + // New feature as of 1610, release 3.3.3: + // application can publish a base URL in system.properties + String appUrl = SystemProperties.getProperty(SystemProperties.APP_BASE_URL); + returnToAppUrl = appUrl + (appUrl.endsWith("/") ? "" : "/") + forwardURL; + logger.debug(EELFLoggerDelegate.debugLogger, + "singleSignOnLogin: using app base URL {} and redirectURL {}", appUrl, returnToAppUrl); + } else { + /** + * Be backward compatible with applications that don't need this feature. This + * is the controller for the single_signon.htm page, so the replace should + * always find the specified token. + */ + returnToAppUrl = request.getRequestURL().toString() + .replace("single_signon.htm", forwardURL); + logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: computed redirectURL {}", + returnToAppUrl); + } + final String encodedReturnToAppUrl = URLEncoder.encode(returnToAppUrl, "UTF-8"); + // Also send the application's UEB key so Portal can block URL + // reflection attacks. + final String uebAppKey = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY); + final String url = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL); + final String portalUrl = url.substring(0, url.lastIndexOf('/')) + "/process_csp"; + final String redirectUrl = portalUrl + "?uebAppKey=" + uebAppKey + "&redirectUrl=" + + encodedReturnToAppUrl; + logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: portal-bound redirect URL is {}", + redirectUrl); + return new ModelAndView(REDIRECT + redirectUrl); + } // portal is available + + else { + /* + * Portal is not available. Redirect user to the login page, ignoring the + * forwardURL parameter. + */ + 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. + * + * @return True if the portal answers, otherwise false. + */ + private boolean isPortalAvailable() { + HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); + final int oneSecond = 1000; + httpRequestFactory.setConnectionRequestTimeout(oneSecond); + httpRequestFactory.setConnectTimeout(oneSecond); + httpRequestFactory.setReadTimeout(oneSecond); + RestTemplate restTemplate = new RestTemplate(httpRequestFactory); + boolean avail = true; + try { + final String portalUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REST_URL); + String s = restTemplate.getForObject(portalUrl, String.class); + logger.trace("isPortalAvailable got response {}", s); + } catch (RestClientException ex) { + logger.debug("isPortalAvailable failed", ex); + avail = false; + } + return avail; + } + + protected void initateSessionMgtHandler(HttpServletRequest request) { + String portalJSessionId = getPortalJSessionId(request); + String jSessionId = getJessionId(request); + PortalTimeoutHandler.sessionCreated(portalJSessionId, jSessionId, AppUtils.getSession(request)); + } + + public boolean isLoginCookieExist(HttpServletRequest request) { + Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE); + return (ep != null); + } + + public String getPortalJSessionId(HttpServletRequest request) { + Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE); + return ep.getValue(); + } + + public String getJessionId(HttpServletRequest request) { + return request.getSession().getId(); + } + + @Override + public String getViewName() { + return viewName; + } + + @Override + public void setViewName(String viewName) { + this.viewName = viewName; + } + + public String getWelcomeView() { + return welcomeView; + } + + public void setWelcomeView(String welcomeView) { + this.welcomeView = welcomeView; + } + + public LoginService getLoginService() { + return loginService; + } + + public void setLoginService(LoginService loginService) { + this.loginService = loginService; + } + +} 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 new file mode 100644 index 0000000..3393236 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/HealthCheckController.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.controller; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.onap.ccsdk.dashboard.model.HealthStatus; +import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController; +import org.openecomp.portalsdk.core.domain.App; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.service.DataAccessService; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +/** + * This controller responds to probes for application health, returning a JSON + * body to indicate current status. + */ +@RestController +@Configuration +@EnableAspectJAutoProxy +@RequestMapping("/") +public class HealthCheckController extends UnRestrictedBaseController { + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(HealthCheckController.class); + + private static final String HEALTH_CHECK_PATH = "/healthCheck"; + + @Autowired + private DataAccessService dataAccessService; + + /** + * Checks application health by making a trivial query to (what??). + * + * @param request + * HttpServletRequest + * @return 200 if database access succeeds, 500 if it fails. + */ + @RequestMapping(value = { HEALTH_CHECK_PATH }, method = RequestMethod.GET, produces = "application/json") + public HealthStatus healthCheck(HttpServletRequest request) { + logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, DashboardRestrictedBaseController.APP_NAME); + logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI()); + HealthStatus healthStatus = null; + try { + logger.debug(EELFLoggerDelegate.debugLogger, "Performing health check"); + @SuppressWarnings("unchecked") + // Get the single app. + List<App> list = dataAccessService.getList(App.class, null); + if (!list.isEmpty()) + healthStatus = new HealthStatus(200, SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME) + " health check succeeded"); + else + healthStatus = new HealthStatus(500, SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME) + " health check failed to run db query"); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "Failed to perform health check", ex); + healthStatus = new HealthStatus(500, "health check failed: " + ex.toString()); + } + return healthStatus; + } + +} 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 new file mode 100644 index 0000000..1e74611 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/ControllerEndpoint.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.domain; + +import org.openecomp.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; + + public ControllerEndpoint() { + } + + public ControllerEndpoint(long userId, String name, String url) { + this.userId = userId; + this.name = name; + this.url = url; + } + + 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; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/exception/DashboardControllerException.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/exception/DashboardControllerException.java new file mode 100644 index 0000000..f288741 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/exception/DashboardControllerException.java @@ -0,0 +1,26 @@ +package org.onap.ccsdk.dashboard.exception; + +/** + * A little something to placate the Sonar code-analysis tool. + */ +public class DashboardControllerException extends Exception { + + private static final long serialVersionUID = -1373841666122351816L; + + public DashboardControllerException() { + super(); + } + + public DashboardControllerException(String message) { + super(message); + } + + public DashboardControllerException(String message, Throwable cause) { + super(message, cause); + } + + public DashboardControllerException(Throwable cause) { + super(cause); + } + +} 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/CloudifyBlueprint.java new file mode 100644 index 0000000..f66a072 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprint.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +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 as generic collections. + */ +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; + + @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/CloudifyBlueprintContent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintContent.java new file mode 100644 index 0000000..6b95eaa --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintContent.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Trivial wrapper for Blueprint YAML content. + */ +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; + + @JsonCreator + public CloudifyBlueprintContent(@JsonProperty("id") String id, + @JsonProperty("content") String content) { + this.id = id; + this.content = content; + } + +} 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/CloudifyBlueprintList.java new file mode 100644 index 0000000..a9a98a1 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintList.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import java.util.List; + +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; + + @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; + + @JsonCreator + 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){ + 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/CloudifyBlueprintUpload.java new file mode 100644 index 0000000..70e093b --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintUpload.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +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 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; + + @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; + } + +} 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 new file mode 100644 index 0000000..126fe9c --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployment.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +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 Inputs 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; + + @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") Inputs 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) { + 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; + } + + 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/CloudifyDeploymentList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentList.java new file mode 100644 index 0000000..51b6169 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentList.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CloudifyDeploymentList extends ECTransportModel { + + public final List<CloudifyDeployment> items; + public final Metadata metadata; + + @JsonCreator + 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; + + @JsonCreator + 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){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } + +} 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 new file mode 100644 index 0000000..32c7199 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentRequest.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +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/CloudifyExecution.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java new file mode 100644 index 0000000..071ef57 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +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 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("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) { + + 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; + } + +} 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/CloudifyExecutionList.java new file mode 100644 index 0000000..5909c62 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionList.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import java.util.List; + +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; + + @JsonCreator + 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; + + @JsonCreator + 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){ + this.total = total; + this.offset = offset; + this.size = size; + } + } + } + +} 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 new file mode 100644 index 0000000..d787fec --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionRequest.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +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 Execution: + * + * <pre> + * { + "deployment_id" : "deployment-id", + "workflow_name" : "workflow-name", + "allow_custom_parameter" : "true|false", + "force" : "true|false", + "parameters": + { + + } + } + * </pre> + */ +public final class CloudifyExecutionRequest 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; + + @JsonCreator + public CloudifyExecutionRequest(@JsonProperty("deployment_id") String deployment_id, + @JsonProperty("workflow_name") String workflow_name, + @JsonProperty("allow_custom_parameter") Boolean allowCustomParameter, @JsonProperty("force") Boolean force, + @JsonProperty("parameters") Map<String, Object> parameters) { + this.deployment_id = deployment_id; + this.workflow_name = workflow_name; + this.allow_custom_parameter = allowCustomParameter; + this.force = force; + this.parameters = parameters; + } + +} 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/ConsulDatacenter.java new file mode 100644 index 0000000..7b610b5 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulDatacenter.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Model for message returned by Consul about monitored datacenters. + * + * <pre> + "dcname" + </pre> + */ +public final class ConsulDatacenter extends ECTransportModel { + + public final String name; + + @JsonCreator + public ConsulDatacenter( + @JsonProperty("ID") String name) { + this.name = name; + } + +} 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/ConsulHealthServiceRegistration.java new file mode 100644 index 0000000..f899a8d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulHealthServiceRegistration.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Model for message POST-ed to controller to (de)register a node or service + * with the Consul health service. The ID is optional; the name is required. + * + * <pre> +{ + "services": [ + { + "id": "<service_id>", + "name": "<service_name>", + "address": "<service_address>", + "port": "<service_port>", + "tags": [ + ], + "checks": [ + { + "endpoint": "<http url for status>", + "interval": "<frequency to check health> e.g., 10s|10m", + "description": "<human readable description of the check", + "name":"<name of the check> + }, + { + "endpoint": "<http url for status>", + "interval": "<frequency to check health> e.g. 10s|10m", + "description": "<human readable description of the check", + "name":"<name of the check> + }, + ] + } + ] +}* + * </pre> + */ +public final class ConsulHealthServiceRegistration extends ECTransportModel { + + public final List<ConsulServiceRegistration> services; + + @JsonCreator + public ConsulHealthServiceRegistration(@JsonProperty("services") List<ConsulServiceRegistration> services) { + this.services = services; + } + + public static final class ConsulServiceRegistration { + + public final String id; + public final String name; + public final String address; + public final String port; + public final List<String> tags; + public final List<EndpointCheck> checks; + + @JsonCreator + public ConsulServiceRegistration(@JsonProperty("id") String id, // + @JsonProperty("name") String name, // + @JsonProperty("address") String address, // + @JsonProperty("port") String port, // + @JsonProperty("tags") List<String> tags,// + @JsonProperty("checks") List<EndpointCheck> checks) { + this.id = id; + this.name = name; + this.address = address; + this.port = port; + this.tags = tags; + this.checks = checks; + } + + } + + public static final class EndpointCheck { + + public final String endpoint; + public final String interval; + public final String description; + public final String name; + + @JsonCreator + public EndpointCheck(@JsonProperty("endpoint") String endpoint, // + @JsonProperty("interval") String interval, // + @JsonProperty("description") String description, // + @JsonProperty("name") String name) { + this.endpoint = endpoint; + this.interval = interval; + this.description = description; + this.name = name; + } + } + +} 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/ConsulNodeInfo.java new file mode 100644 index 0000000..b3ba4ae --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulNodeInfo.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +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 returned by Consul about a node registered for health monitoring. + * + * <pre> + { + "ID":"a2788806-6e2e-423e-8ee7-6cad6f3d3de6", + "Node":"cjlvmcnsl00", + "Address":"10.170.8.13", + "TaggedAddresses":{"lan":"10.170.8.13","wan":"10.170.8.13"}, + "Meta":{}, + "CreateIndex":6, + "ModifyIndex":179808 + } + </pre> + */ +public final class ConsulNodeInfo extends ECTransportModel { + + public final String id; + public final String node; + public final String address; + public final Map<String,Object> taggedAddresses; + public final Map<String,Object> meta; + public final int createIndex; + public final int modifyIndex; + + @JsonCreator + public ConsulNodeInfo( + @JsonProperty("ID") String id, + @JsonProperty("Node") String node, + @JsonProperty("Address") String address, + @JsonProperty("TaggedAddresses") Map<String,Object> taggedAddresses, + @JsonProperty("Meta") Map<String,Object> meta, + @JsonProperty("CreateIndex") int createIndex, + @JsonProperty("ModifyIndex") int modifyIndex) { + this.id = id; + this.node = node; + this.address = address; + this.taggedAddresses = taggedAddresses; + this.meta = meta; + this.createIndex = createIndex; + this.modifyIndex = modifyIndex; + } + +} 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/ConsulServiceHealth.java new file mode 100644 index 0000000..b609b78 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealth.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Model for message returned by Consul about health of a service. + * + * <pre> + { + "Node": "cjlvmcnsl00", + "CheckID": "service:pgaas1_Service_ID", + "Name": "Service 'pgaasServer1' check", + "Status": "passing", + "Notes": "This is a pgaas1_Service_ID health check", + "Output": "HTTP GET http:\/\/1.2.3.4:8000\/healthcheck\/status: 200 OK ..", + "ServiceID": "pgaas1_Service_ID", + "ServiceName": "pgaasServer1", + "CreateIndex": 190199, + "ModifyIndex": 199395 + } </pre> + * + */ +public final class ConsulServiceHealth extends ECTransportModel { + + public final String node; + public final String checkID; + public final String name; + public final String status; + public final String notes; + public final String output; + public final String serviceID; + public final String serviceName; + public final int createIndex; + public final int modifyIndex; + + @JsonCreator + public ConsulServiceHealth( + @JsonProperty("Node") String node, + @JsonProperty("CheckID") String checkID, + @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) { + this.node = node; + this.checkID = checkID; + this.name = name; + this.status = status; + this.notes = notes; + this.output = output; + this.serviceID = serviceID; + this.serviceName = serviceName; + this.createIndex = createIndex; + this.modifyIndex = modifyIndex; + } + +} 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/ConsulServiceHealthHistory.java new file mode 100644 index 0000000..f80b506 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealthHistory.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Model for message returned by Consul about health of a service observed at + * some point in time. + * + * <pre> + { + "Status": "critical", + "Output": "\"Get http://1.2.3.4:8080: dial tcp 2.3.4.5:8080: getsockopt: connection refused\"", + "Date": "2017-06-01 15:31:58.00-0000" + } + * </pre> + * + */ +public final class ConsulServiceHealthHistory extends ECTransportModel { + + public final String status; + public final String output; + public final String date; + + @JsonCreator + public ConsulServiceHealthHistory(@JsonProperty("Status") String status, @JsonProperty("Output") String output, + @JsonProperty("Date") String date) { + this.status = status; + this.output = output; + this.date = date; + } + +} 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/ConsulServiceInfo.java new file mode 100644 index 0000000..edeb029 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceInfo.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Dashboard-specific model for message about a service registered for health + * monitoring. This is NOT a model of message returned by Controller. + * + * The controller API answers a message with a map of String (name) to List of + * String (IP addresses). + * + * <pre> + { + "pgaasServer1":["1.2.3.4"] + } + * </pre> + */ +public final class ConsulServiceInfo extends ECTransportModel { + + public final String name; + public final List<String> addresses; + + @JsonCreator + public ConsulServiceInfo(@JsonProperty("name") String name, @JsonProperty("addresses") List<String> addresses) { + this.name = name; + this.addresses = addresses; + } + +} 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 new file mode 100644 index 0000000..02c892f --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointCredentials.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import org.onap.ccsdk.dashboard.exception.DashboardControllerException; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.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 { + + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ControllerEndpointCredentials.class); + + public String username; + public String password; + public boolean isEncryptedPass; + + public ControllerEndpointCredentials(boolean selected, String name, String url, String username, String password, + boolean isEncryptedPass) { + super(selected, name, url); + 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()); + } + + /** + * Accepts clear text and stores an encrypted value; as a side effect, sets the + * encrypted flag to true. + * + * @param plainText + * Clear-text password + * @throws DashboardControllerException + * If encryption fails + */ + public void encryptPassword(final String plainText) throws DashboardControllerException { + try { + this.password = CipherUtil.encrypt(plainText); + this.isEncryptedPass = true; + } catch (Exception ex) { + logger.error("encryptPassword failed", ex); + throw new DashboardControllerException(ex); + } + } + + /** + * Client should call this method if {@link #getEncryptedPassword()} returns + * true. + * + * @return Clear-text password. + * @throws DashboardControllerException + * If decryption fails + */ + public String decryptPassword() throws DashboardControllerException { + try { + return CipherUtil.decrypt(password); + } catch (Exception ex) { + logger.error("decryptPassword failed", ex); + throw new DashboardControllerException(ex); + } + } +}
\ 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 new file mode 100644 index 0000000..0a2f529 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointTransport.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +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; + + public ControllerEndpointTransport() {} + + public ControllerEndpointTransport(boolean selected, String name, String url) { + this.selected = selected; + this.name = name; + this.url = url; + } + + 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; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ECTransportModel.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ECTransportModel.java new file mode 100644 index 0000000..3e0baa1 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ECTransportModel.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +/** + * Base class for POJOs that transport data in the ECOMP Controller webapp. + */ +public abstract class ECTransportModel { + + protected final ObjectMapper mapper = new ObjectMapper(); + + public ECTransportModel() { + // Do not serialize null values + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + // toString should yield pretty version + mapper.configure(SerializationFeature.INDENT_OUTPUT, true); + // tolerate empty strings where object is expected + mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); + } + + /** + * Convenience method that serializes content as JSON and catches any + * exception so this method can be easily used in a catch clause. + * + * @return A REST error response object as well-formed JSON + */ + public String toString() { + String json = null; + try { + json = mapper.writeValueAsString(this); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + json = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + return json; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/HealthStatus.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/HealthStatus.java new file mode 100644 index 0000000..93d072f --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/HealthStatus.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +/** + * Model for JSON response with health-check results. + */ +public class HealthStatus { + // Either 200 or 500 + public int statusCode; + // Additional detail in case of error, empty in case of success. + public String message; + + public HealthStatus(int code, String msg) { + this.statusCode = code; + this.message = msg; + } + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int code) { + this.statusCode = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String msg) { + this.message = msg; + } +}
\ No newline at end of file diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponseError.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponseError.java new file mode 100644 index 0000000..64e0d71 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponseError.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Trivial model for carrying error responses. + */ +public class RestResponseError extends ECTransportModel { + + private String error; + + public RestResponseError() { + } + + /** + * Convenience constructor + * + * @param message + * Message body + */ + public RestResponseError(final String message) { + this.error = message; + } + + /** + * Convenience constructor that limits the size of the throwable message. + * + * @param message + * Message body + * @param t + * Throwable used to construct body + */ + public RestResponseError(final String message, final Throwable t) { + final int enough = 512; + String exString = t.toString(); + String exceptionMsg = exString.length() > enough ? exString.substring(0, enough) : exString; + this.error = message + ": " + exceptionMsg; + } + + public String getError() { + return error; + } + + public void setError(String message) { + this.error = message; + } + + /** + * Convenience method that serializes content as JSON and catches any + * exception so this can be easily used in a catch clause. + * + * @return A REST error response object as well-formed JSON + */ + public String toJson() { + String json = null; + try { + ObjectMapper mapper = new ObjectMapper(); + json = mapper.writeValueAsString(this); + } catch (JsonProcessingException jpe) { + // Should never, ever happen + json = "{ \"error\" : \"" + jpe.toString() + "\"}"; + } + return json; + } + + @Override + public String toString() { + return "RestErrorResponse[message=" + error + "]"; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponsePage.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponsePage.java new file mode 100644 index 0000000..0902fb0 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponsePage.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +/** + * Model for a response with count of items available, count of pages required + * to display all items, and one page worth of data items. + * + * @param <T> + * Model class for item + */ +public class RestResponsePage<T> extends ECTransportModel { + + private int totalItems; + private int totalPages; + private T items; + + public RestResponsePage() { + } + + public RestResponsePage(final int totalItems, final int totalPages, final T items) { + this.totalItems = totalItems; + this.totalPages = totalPages; + this.items = items; + } + + public int getTotalItems() { + return totalItems; + } + + public void setTotalItems(int items) { + this.totalItems = items; + } + + public int getTotalPages() { + return totalPages; + } + + public void setTotalPages(int pages) { + this.totalPages = pages; + } + + public T getItems() { + return items; + } + + public void setItems(final T data) { + this.items = data; + } + + @Override + public String toString() { + return "RestResponsePage[totalItems=" + totalItems + ", totalPages=" + totalPages + ", items=" + items + "]"; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponseSuccess.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponseSuccess.java new file mode 100644 index 0000000..145c1cd --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/RestResponseSuccess.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.model; + +/** + * Trivial model for carrying a message indicating success. + */ +public class RestResponseSuccess extends ECTransportModel { + + private String message; + + public RestResponseSuccess() { + } + + /** + * Convenience constructor + * + * @param message + * Message body + */ + public RestResponseSuccess(final String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "RestResponseSuccess[message=" + message + "]"; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ControllerRestClientImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ControllerRestClientImpl.java new file mode 100644 index 0000000..bb79c9f --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ControllerRestClientImpl.java @@ -0,0 +1,412 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.rest; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +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.onap.ccsdk.dashboard.model.CloudifyBlueprintContent; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintUpload; +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentRequest; +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.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.ConsulServiceHealthHistory; +import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Provides methods for accessing the ECOMP Controller API via REST. Most + * methods are just simple proxies. Only the methods that fetch one page of data + * have to do any real work. + * + * Implemented using Spring RestTemplate. Supports basic HTTP authentication. + * + */ +public class ControllerRestClientImpl implements IControllerRestClient { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ControllerRestClientImpl.class); + private static final String DEPLOYMENT_ID = "deployment_id"; + + private final String baseUrl; + private final RestTemplate restTemplate; + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * Builds a restTemplate. If username and password are supplied, uses basic + * HTTP authentication. + * + * @param webapiUrl + * URL of the web endpoint + * @param user + * user name; ignored if null + * @param pass + * password + */ + public ControllerRestClientImpl(String webapiUrl, String user, String pass) { + if (webapiUrl == null) + throw new IllegalArgumentException("Null URL not permitted"); + + URL url = null; + try { + url = new URL(webapiUrl); + baseUrl = url.toExternalForm(); + } catch (MalformedURLException ex) { + throw new RuntimeException("Failed to parse URL", ex); + } + final HttpHost httpHost = new HttpHost(url.getHost(), url.getPort()); + + // 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); + + // Put the factory in the template + this.restTemplate = new RestTemplate(); + restTemplate.setRequestFactory(requestFactory); + } + + /** + * Builds URL ensuring appropriate separators. The base comes from + * properties file so could have many problems. + * + * @param base + * @param suffix + * @param queryParams + * key-value pairs; i.e. must have an even number of entries. + * Ignored if null. + * @return + */ + private String buildUrl(final String[] path, final String[] queryParams) { + StringBuilder sb = new StringBuilder(path[0]); + for (int p = 1; p < path.length; ++p) { + if (!path[p - 1].endsWith("/") && !path[p].startsWith("/")) + sb.append('/'); + sb.append(path[p]); + } + if (queryParams != null && queryParams.length > 0) { + sb.append('?'); + int i = 0; + while (i < queryParams.length) { + if (i > 0) + sb.append('&'); + sb.append(queryParams[i]); + sb.append('='); + sb.append(queryParams[i + 1]); + i += 2; + } + } + return sb.toString(); + } + + @Override + public CloudifyBlueprintList getBlueprints() { + String url = buildUrl(new String[] { baseUrl, blueprintsPath }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getBlueprints: url {}", url); + ResponseEntity<CloudifyBlueprintList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyBlueprintList>() { + }); + return response.getBody(); + } + + @Override + public CloudifyBlueprintList getBlueprint(final String id) { + String url = buildUrl(new String[] { baseUrl, blueprintsPath }, new String[] { "id", id }); + logger.debug(EELFLoggerDelegate.debugLogger, "getBlueprint: url {}", url); + ResponseEntity<CloudifyBlueprintList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyBlueprintList>() { + }); + return response.getBody(); + } + + @Override + public CloudifyBlueprintContent viewBlueprint(final String id) { + String url = buildUrl(new String[] { baseUrl, viewBlueprintsPath }, new String[] { "id", id }); + logger.debug(EELFLoggerDelegate.debugLogger, "viewBlueprint: url {}", url); + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, String.class); + String yaml = response.getBody(); + return new CloudifyBlueprintContent(id, yaml); + } + + @Override + public CloudifyBlueprintList uploadBlueprint(CloudifyBlueprintUpload blueprint) { + String url = buildUrl(new String[] { baseUrl, blueprintsPath }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "uploadBlueprint: url {}", url); + return restTemplate.postForObject(url, blueprint, CloudifyBlueprintList.class); + } + + @Override + public int deleteBlueprint(final String id) { + String url = buildUrl(new String[] { baseUrl, blueprintsPath, id }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "deleteBlueprint: url {}", url); + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.DELETE, null, + new ParameterizedTypeReference<String>() { + }); + return response.getStatusCode().value(); + } + + @Override + public CloudifyDeploymentList getDeployments() { + String url = buildUrl(new String[] { baseUrl, deploymentsPath }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getDeployments: url {}", url); + ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyDeploymentList>() { + }); + return response.getBody(); + } + + @Override + public CloudifyDeploymentList getDeployment(final String id) { + String url = buildUrl(new String[] { baseUrl, deploymentsPath }, new String[] { "id", id }); + logger.debug(EELFLoggerDelegate.debugLogger, "getDeployment: url {}", url); + ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyDeploymentList>() { + }); + return response.getBody(); + } + + @Override + public CloudifyDeploymentList createDeployment(CloudifyDeploymentRequest deployment) { + String url = buildUrl(new String[] { baseUrl, deploymentsPath }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "createDeployment: url {}", url); + return restTemplate.postForObject(url, deployment, CloudifyDeploymentList.class); + } + + @Override + public int deleteDeployment(final String id, boolean ignoreLiveNodes) { + String url = buildUrl(new String[] { baseUrl, deploymentsPath, id }, + new String[] { "ignore_live_nodes", Boolean.toString(ignoreLiveNodes) }); + logger.debug(EELFLoggerDelegate.debugLogger, "deleteDeployment: url {}", url); + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.DELETE, null, + new ParameterizedTypeReference<String>() { + }); + return response.getStatusCode().value(); + } + + @Override + public CloudifyExecutionList getExecutions(final String deploymentId) { + String url = buildUrl(new String[]{baseUrl, executionsPath}, new String[]{DEPLOYMENT_ID, deploymentId}); + logger.debug(EELFLoggerDelegate.debugLogger, "getExecutions: url {}", url); + ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyExecutionList>() { + }); + return response.getBody(); + } + + @Override + public CloudifyExecutionList getExecution(String executionId, String deploymentId) { + String url = buildUrl(new String[] { baseUrl, executionsPath, executionId }, + new String[]{DEPLOYMENT_ID, deploymentId}); + logger.debug(EELFLoggerDelegate.debugLogger, "getExecution: url {}", url); + ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<CloudifyExecutionList>() { + }); + return response.getBody(); + } + + @Override + public CloudifyExecution startExecution(CloudifyExecutionRequest execution) { + String url = buildUrl(new String[] { baseUrl, executionsPath }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "startExecution: url {}", url); + return restTemplate.postForObject(url, execution, CloudifyExecution.class); + } + + @Override + public int cancelExecution(final String executionId, final String deploymentId, final String action) { + String url = buildUrl(new String[] { baseUrl, executionsPath, executionId }, + new String[]{DEPLOYMENT_ID, deploymentId, "action", action}); + logger.debug(EELFLoggerDelegate.debugLogger, "deleteExecution: url {}", url); + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.DELETE, null, + new ParameterizedTypeReference<String>() { + }); + return response.getStatusCode().value(); + } + + @Override + public URI registerService(ConsulHealthServiceRegistration registration) { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "register" }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "registerService: url {}", url); + return restTemplate.postForLocation(url, registration); + } + + @Override + public int deregisterService(String serviceName) { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "deregister" , serviceName}, null); + logger.debug(EELFLoggerDelegate.debugLogger, "deregisterService: url {}", url); + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, null, + new ParameterizedTypeReference<String>() { + }); + return response.getStatusCode().value(); + } + + /** + * Translates the awkward map of String-to-List of IP into a list of + * ConsulServiceInfo objects + */ + @SuppressWarnings("unchecked") + @Override + public List<ConsulServiceInfo> getServices() { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "services" }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getServicesHealth: url {}", url); + ResponseEntity<Map<String, Object>> response = restTemplate.exchange(url, HttpMethod.GET, null, + 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; + if (entry.getValue() instanceof List<?>) + addrs = (List<String>) entry.getValue(); + else + addrs = new ArrayList<>(); + list.add(new ConsulServiceInfo(entry.getKey(), addrs)); + } + return list; + } + + @Override + public List<ConsulServiceHealth> getServiceHealth(String serviceName) { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "services", serviceName }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealth: url {}", url); + ResponseEntity<List<ConsulServiceHealth>> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<List<ConsulServiceHealth>>() { + }); + return response.getBody(); + } + + @Override + public List<ConsulServiceHealthHistory> getServiceHealthHistory(String serviceName, Instant start, + Instant end) { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "svchist", serviceName }, + new String[] { "start", start.toString(), "end", end.toString() }); + logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealthHistory: url {}", url); + // Hack around an odd interface that returns non-JSON on error: + // "No health Data found for the selected dates or service" + ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<String>() { }); + if (response.getBody().startsWith("No health")) + throw new RuntimeException(response.getBody()); + List<ConsulServiceHealthHistory> result = null; + try { + TypeReference<List<ConsulServiceHealthHistory>> typeRef = new TypeReference<List<ConsulServiceHealthHistory>>() { }; + result = objectMapper.readValue(response.getBody(), typeRef); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "getServiceHealthHistory failed to parse response body", ex); + } + return result; + } + + @Override + public List<ConsulNodeInfo> getNodes() { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "nodes" }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getNodesHealth: url {}", url); + ResponseEntity<List<ConsulNodeInfo>> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<List<ConsulNodeInfo>>() { + }); + return response.getBody(); + } + + @Override + public List<ConsulServiceHealth> getNodeServicesHealth(String nodeId) { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "nodes", nodeId }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getNodeServicesHealth: url {}", url); + ResponseEntity<List<ConsulServiceHealth>> response = restTemplate.exchange(url, HttpMethod.GET, null, + new ParameterizedTypeReference<List<ConsulServiceHealth>>() { + }); + return response.getBody(); + } + + @Override + public List<ConsulDatacenter> getDatacenters() { + String url = buildUrl(new String[] { baseUrl, healthServicesPath, "datacenters" }, null); + logger.debug(EELFLoggerDelegate.debugLogger, "getDatacentersHealth: url {}", url); + ResponseEntity<List<String>> response = restTemplate.exchange(url, HttpMethod.GET, null, + 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; + } + + /** + * Simple test + * + * @param args + * blueprint ID + * @throws IllegalArgumentException + * On bad arguments + */ + public static void main(String[] args) throws IllegalArgumentException { + if (args.length != 1) + throw new IllegalArgumentException("Single argument expected: blueprint-id"); + ControllerRestClientImpl client = new ControllerRestClientImpl("http://localhost:8081/controller", "dbus_user", + "dbus_pass"); + final String id = args[0]; + logger.info("Requesting blueprint for " + id); + CloudifyBlueprintList list = client.getBlueprint(id); + if (list == null) + logger.error("Received null"); + else + for (int i = 0; i < list.items.size(); ++i) { + logger.info("Blueprint " + Integer.toString(i)); + logger.info(list.items.get(i).toString()); + } + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ControllerRestClientMockImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ControllerRestClientMockImpl.java new file mode 100644 index 0000000..2523538 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ControllerRestClientMockImpl.java @@ -0,0 +1,311 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.rest; + +import java.io.InputStream; +import java.net.URI; +import java.time.Instant; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import org.onap.ccsdk.dashboard.exception.DashboardControllerException; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintContent; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintUpload; +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentRequest; +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.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.ConsulServiceHealthHistory; +import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; +import org.onap.ccsdk.dashboard.model.ECTransportModel; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Provides mock implementations that return contents of files on the classpath. + */ +public class ControllerRestClientMockImpl implements IControllerRestClient { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ControllerRestClientMockImpl.class); + + /** + * For mock outputs + */ + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * No-arg constructor + */ + public ControllerRestClientMockImpl() { + } + + private String getMockDataContent(final String path) { + String result = null; + try { + InputStream is = getClass().getResourceAsStream(path); + if (is == null) + throw new DashboardControllerException("Failed to find resource at path " + path); + Scanner scanner = new Scanner(is, "UTF-8"); + result = scanner.useDelimiter("\\A").next(); + scanner.close(); + is.close(); + } catch (Exception ex) { + logger.error("getMockDataContent failed", ex); + throw new RuntimeException(ex); + } + return result; + } + + /** + * Creates an input stream using the specified path and requests the mapper + * create an object of the specified type. + * + * @param modelClass + * Model class + * @param path + * Path to classpath resource + * @return Instance of modelClass + */ + private ECTransportModel getMockData(final Class<? extends ECTransportModel> modelClass, final String path) { + ECTransportModel result; + String json = getMockDataContent(path); + try { + result = objectMapper.readValue(json, modelClass); + } catch (Exception ex) { + logger.error("getMockData failed", ex); + throw new RuntimeException(ex); + } + return result; + } + + @Override + public CloudifyBlueprintList getBlueprints() { + return (CloudifyBlueprintList) getMockData(CloudifyBlueprintList.class, "/blueprintList.json"); + } + + @Override + public CloudifyBlueprintList getBlueprint(final String id) { + return (CloudifyBlueprintList) getMockData(CloudifyBlueprintList.class, "/blueprintByID.json"); + } + + @Override + public CloudifyBlueprintContent viewBlueprint(final String id) { + String yaml = getMockDataContent("/blueprintContent.yaml"); + return new CloudifyBlueprintContent(id, yaml); + } + + @Override + public CloudifyBlueprintList uploadBlueprint(CloudifyBlueprintUpload blueprint) { + logger.debug(EELFLoggerDelegate.debugLogger, "uploadBlueprint: {}", blueprint.toString()); + return new CloudifyBlueprintList(null, null); + } + + @Override + public int deleteBlueprint(final String id) { + logger.debug(EELFLoggerDelegate.debugLogger, "deleteBlueprint: {}", id); + return 204; + } + + @Override + public CloudifyDeploymentList getDeployments() { + return (CloudifyDeploymentList) getMockData(CloudifyDeploymentList.class, "/deploymentList.json"); + } + + @Override + public CloudifyDeploymentList getDeployment(final String id) { + return (CloudifyDeploymentList) getMockData(CloudifyDeploymentList.class, "/deploymentByID.json"); + } + + public CloudifyDeploymentList createDeployment(CloudifyDeploymentRequest deployment) { + logger.debug(EELFLoggerDelegate.debugLogger, "createDeployment: {}", deployment.toString()); + return new CloudifyDeploymentList(null, null); + } + + @Override + public int deleteDeployment(final String id, boolean ignoreLiveNodes) { + logger.debug(EELFLoggerDelegate.debugLogger, "deleteDeployment: id {}, ignoreLiveNodes", id, ignoreLiveNodes); + return 204; + } + + @Override + public CloudifyExecutionList getExecutions(final String deploymentId) { + return (CloudifyExecutionList) getMockData(CloudifyExecutionList.class, "/listExecutionForDeploymentID.json"); + } + + @Override + public CloudifyExecutionList getExecution(String executionId, String deploymentId) { + return (CloudifyExecutionList) getMockData(CloudifyExecutionList.class, "/listExecutionForDeploymentID.json"); + } + + @Override + public CloudifyExecution startExecution(CloudifyExecutionRequest execution) { + logger.debug(EELFLoggerDelegate.debugLogger, "startExecution: {}", execution.toString()); + return new CloudifyExecution(null, null, null, null, null, null, null, null, null); + } + + @Override + public int cancelExecution(String executionId, String deploymentId, String action) { + logger.debug(EELFLoggerDelegate.debugLogger, "deleteExecution: executionId {}, deploymentId {}, action {}", + executionId, deploymentId, action); + return 204; + } + + @Override + public URI registerService(ConsulHealthServiceRegistration registration) { + logger.debug(EELFLoggerDelegate.debugLogger, "registerService: {}", registration); + return null; + } + + @Override + public int deregisterService(String serviceName) { + logger.debug(EELFLoggerDelegate.debugLogger, "deregisterService: {}", serviceName); + return 200; + } + + @Override + public List<ConsulServiceHealth> getServiceHealth(String serviceName) { + logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealth: serviceName={}", serviceName); + String json = getMockDataContent("/serviceHealth.json"); + TypeReference<List<ConsulServiceHealth>> typeRef = new TypeReference<List<ConsulServiceHealth>>() { + }; + List<ConsulServiceHealth> result = null; + try { + result = objectMapper.readValue(json, typeRef); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "getServiceHealth failed", ex); + } + return result; + } + + @Override + public List<ConsulServiceHealthHistory> getServiceHealthHistory(String serviceName, Instant start, Instant end) { + logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealthHistory: serviceName={}", serviceName); + String json = getMockDataContent("/serviceHealthHistory.json"); + TypeReference<List<ConsulServiceHealthHistory>> typeRef = new TypeReference<List<ConsulServiceHealthHistory>>() { + }; + List<ConsulServiceHealthHistory> result = null; + try { + result = objectMapper.readValue(json, typeRef); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "getServiceHealthHistory failed", ex); + } + return result; + } + + @Override + public List<ConsulServiceHealth> getNodeServicesHealth(String nodeId) { + logger.debug(EELFLoggerDelegate.debugLogger, "getNodeServicesHealth: nodeId={}", nodeId); + String json = getMockDataContent("/nodeServicesHealth.json"); + TypeReference<List<ConsulServiceHealth>> typeRef = new TypeReference<List<ConsulServiceHealth>>() { + }; + List<ConsulServiceHealth> result = null; + try { + result = objectMapper.readValue(json, typeRef); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "getNodeServicesHealth failed", ex); + } + return result; + } + + @Override + public List<ConsulServiceInfo> getServices() { + logger.debug(EELFLoggerDelegate.debugLogger, "getServices"); + String json = getMockDataContent("/services.json"); + TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() { + }; + HashMap<String, Object> map = null; + try { + map = objectMapper.readValue(json, typeRef); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "getNode failed", ex); + } + ArrayList<ConsulServiceInfo> result = new ArrayList<>(); + if (map != null) { + for (Map.Entry<String, Object> entry : map.entrySet()) { + final String service = entry.getKey(); + @SuppressWarnings("unchecked") final List<String> addrs = (List<String>) entry.getValue(); + result.add(new ConsulServiceInfo(service, addrs)); + } + } + return result; + } + + @Override + public List<ConsulNodeInfo> getNodes() { + logger.debug(EELFLoggerDelegate.debugLogger, "getNodes"); + String json = getMockDataContent("/nodesHealth.json"); + TypeReference<List<ConsulNodeInfo>> typeRef = new TypeReference<List<ConsulNodeInfo>>() { + }; + List<ConsulNodeInfo> result = null; + try { + result = objectMapper.readValue(json, typeRef); + } catch (Exception ex) { + logger.error(EELFLoggerDelegate.errorLogger, "getNode failed", ex); + + } + return result; + } + + @Override + public List<ConsulDatacenter> getDatacenters() { + logger.debug(EELFLoggerDelegate.debugLogger, "getDatacentersHealth"); + return null; + } + + /** + * Simple test + * + * @param args + * blueprint ID + * @throws DashboardControllerException + * On any failure + */ + public static void main(String[] args) throws DashboardControllerException { + logger.info("Testing paths and parsing mock data"); + ControllerRestClientMockImpl client = new ControllerRestClientMockImpl(); + CloudifyBlueprintList list1 = client.getBlueprints(); + CloudifyBlueprintList list2 = client.getBlueprint("mock"); + CloudifyDeploymentList list3 = client.getDeployments(); + CloudifyDeploymentList list4 = client.getDeployment("mock"); + CloudifyExecutionList list5 = client.getExecutions("mock"); + List<ConsulServiceInfo> list6 = client.getServices(); + List<ConsulNodeInfo> list7 = client.getNodes(); + List<ConsulServiceHealth> list8 = client.getServiceHealth("mock"); + List<ConsulServiceHealthHistory> list9 = client.getServiceHealthHistory("mock", Instant.now(), Instant.now()); + if (list1 == null || list2 == null || list3 == null || list4 == null || list5 == null || list6 == null + || list7 == null || list8 == null || list9 == null) + throw new DashboardControllerException("Failed"); + logger.info("Pass."); + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/HttpComponentsClientHttpRequestFactoryBasicAuth.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/HttpComponentsClientHttpRequestFactoryBasicAuth.java new file mode 100644 index 0000000..77ccda0 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/HttpComponentsClientHttpRequestFactoryBasicAuth.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.rest; + +import java.net.URI; + +import org.apache.http.HttpHost; +import org.apache.http.client.AuthCache; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; + +/** + * Utility class to enable Basic HTTP Authentication with Spring REST templates. + * + * From: + * http://www.baeldung.com/2012/04/16/how-to-use-resttemplate-with-basic-authentication-in-spring-3-1/ + */ +public class HttpComponentsClientHttpRequestFactoryBasicAuth extends HttpComponentsClientHttpRequestFactory { + + private HttpHost host; + + /** + * @param host + * HttpHost + */ + public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) { + super(); + this.host = host; + } + + @Override + protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { + return createHttpContext(); + } + + private HttpContext createHttpContext() { + // Create AuthCache instance + AuthCache authCache = new BasicAuthCache(); + // Generate BASIC scheme object and add it to the local auth cache + BasicScheme basicAuth = new BasicScheme(); + authCache.put(host, basicAuth); + + // Add AuthCache to the execution context + BasicHttpContext localcontext = new BasicHttpContext(); + localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache); + return localcontext; + } +} diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/IControllerRestClient.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/IControllerRestClient.java new file mode 100644 index 0000000..5e060e9 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/IControllerRestClient.java @@ -0,0 +1,247 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.rest; + +import java.net.URI; +import java.time.Instant; +import java.util.List; + +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintContent; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList; +import org.onap.ccsdk.dashboard.model.CloudifyBlueprintUpload; +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList; +import org.onap.ccsdk.dashboard.model.CloudifyDeploymentRequest; +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.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.ConsulServiceHealthHistory; +import org.onap.ccsdk.dashboard.model.ConsulServiceInfo; + +/** + * Defines the interface of the Controller REST client. + */ +public interface IControllerRestClient { + + String blueprintsPath = "blueprints"; + String viewBlueprintsPath = "viewblueprints"; + String deploymentsPath = "deployments"; + String executionsPath = "executions"; + String healthServicesPath = "healthservices"; + + /** + * Gets the list of Cloudify blueprints. + * + * @return CloudifyBlueprintList + */ + CloudifyBlueprintList getBlueprints(); + + /** + * Gets the Cloudify blueprint metadata for the specified ID + * + * @param id + * Blueprint ID + * @return CloudifyBlueprintList of size 1; null if not found + */ + CloudifyBlueprintList getBlueprint(String id); + + /** + * Gets the Cloudify blueprint content for the specified ID + * + * @param id + * Blueprint ID + * @return Blueprint content + */ + CloudifyBlueprintContent viewBlueprint(String id); + + /** + * Uploads a Cloudify blueprint. + * + * @param blueprint + * Cloudify Blueprint to upload + * @return CloudifyBlueprintList of size 1; null if not found + */ + CloudifyBlueprintList uploadBlueprint(CloudifyBlueprintUpload blueprint); + + /** + * Deletes the Cloudify blueprint with the specified id. + * + * @param id + * Blueprint ID + * @return Status code; e.g., 200, 202, 204. + */ + int deleteBlueprint(String id); + + /** + * Gets the list of Cloudify deployments. + * + * @return CloudifyDeploymentList + */ + CloudifyDeploymentList getDeployments(); + + /** + * Gets the Cloudify deployment for the specified ID + * + * @param id + * Deployment ID + * @return CloudifyDeploymentList of size 1; null if not found. + */ + CloudifyDeploymentList getDeployment(String id); + + /** + * Creates a Cloudify deployment. + * + * @param deployment + * Deployment details + * @return CloudifyDeploymentList of size 1 + */ + CloudifyDeploymentList createDeployment(CloudifyDeploymentRequest deployment); + + /** + * Deletes the Cloudify deployment with the specified id. + * + * @param id + * Deployment ID + * @param ignoreLiveNodes + * Boolean indicator whether to delete even if live nodes exist + * @return Status code; e.g., 200, 202, 204. + */ + int deleteDeployment(String id, boolean ignoreLiveNodes); + + /** + * Gets the Cloudify executions for the specified deployment ID + * + * @param deploymentId + * Deployment ID + * @return CloudifyExecutionList + */ + CloudifyExecutionList getExecutions(String deploymentId); + + /** + * Gets the Cloudify execution for the specified execution ID and deployment + * ID + * + * @param executionId + * Execution ID + * @param deploymentId + * Deployment ID + * @return CloudifyExecutionList of size 1 + */ + CloudifyExecutionList getExecution(String executionId, String deploymentId); + + /** + * Starts a Cloudify execution. + * + * @param execution + * Execution details + * @return CloudifyExecution + */ + CloudifyExecution startExecution(CloudifyExecutionRequest execution); + + /** + * Deletes the Cloudify execution with the specified ids. + * + * @param executionId + * execution ID + * @param deploymentId + * Deployment ID + * @param action + * either "cancel" or "force-cancel" + * @return Status code; e.g., 200, 202, 204. + */ + int cancelExecution(String executionId, String deploymentId, String action); + + /** + * Registers a service with Consul for health check. + * + * @param registration + * Details about the service to be registered. + * @return Result of registering a service + */ + URI registerService(ConsulHealthServiceRegistration registration); + + /** + * Deregister a service with Consul for health check. + * + * @param serviceName + * Name of the service to be deregister. + * @return Response code + */ + int deregisterService(String serviceName); + + /** + * Gets all the services that are monitored by Consul. + * + * @return List of ConsulServiceHealth + */ + List<ConsulServiceInfo> getServices(); + + /** + * Gets the status for the specified service on all nodes. + * + * @param serviceName + * Service name + * @return List of ConsulServiceHealth + */ + List<ConsulServiceHealth> getServiceHealth(String serviceName); + + /** + * Gets the status for the specified service on all nodes for the specified + * time window. + * + * @param serviceName + * Service name + * @param start + * Start (earliest point) of the time window + * @param end + * End (latest point) of the time window + * @return List of ConsulServiceHealth + */ + List<ConsulServiceHealthHistory> getServiceHealthHistory(String serviceName, Instant start, Instant end); + + /** + * Gets all the nodes that are monitored by Consul. + * + * @return List of ConsulNodeHealth + */ + List<ConsulNodeInfo> getNodes(); + + /** + * Gets the status for all registered services running on the specified + * node. + * + * @param nodeId + * Node ID + * @return List of ConsulServiceHealth + */ + List<ConsulServiceHealth> getNodeServicesHealth(String nodeId); + + /** + * Gets all the data centers that are monitored by Consul. + * + * @return List of ConsulDatacenter objects + */ + List<ConsulDatacenter> getDatacenters(); +} 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 new file mode 100644 index 0000000..621de95 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointService.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.service; + +import org.onap.ccsdk.dashboard.domain.ControllerEndpoint; + +/** + * 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); + +} 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 new file mode 100644 index 0000000..b1c64b5 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointServiceImpl.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.service; + +import org.onap.ccsdk.dashboard.domain.ControllerEndpoint; +import org.openecomp.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; + } + + @Override + public ControllerEndpoint getControllerEndpointSelection(long userId) { + return (ControllerEndpoint) getDataAccessService() + .getDomainObject(ControllerEndpoint.class, userId, null); + } + + @Override + public void updateControllerEndpointSelection(ControllerEndpoint endpoint) { + getDataAccessService().saveDomainObject(endpoint, null); + } + + @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 new file mode 100644 index 0000000..717be11 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/util/DashboardProperties.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.ccsdk.dashboard.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; + +/** + * Publishes a list of constants and methods to access the properties that are + * read by Spring from the specified configuration file(s). + * + * Should be used like this (and never in a constructor): + * + * <pre> + * @Autowired + * DashboardProperties properties; + * </pre> + */ +@Configuration +@PropertySource(value = { "${container.classpath:}/WEB-INF/conf/dashboard.properties" }) +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 + */ + public static final String CONTROLLER_KEY_LIST = "controller.key.list"; + /** + * Subkey for property with Controller name (description) + */ + public static final String CONTROLLER_SUBKEY_NAME = "name"; + /** + * Subkey for property with Controller URL + */ + public static final String CONTROLLER_SUBKEY_URL = "url"; + /** + * Subkey for property with Controller user name for authentication + */ + public static final String CONTROLLER_SUBKEY_USERNAME = "username"; + /** + * Subkey for property with Controller password + */ + public static final String CONTROLLER_SUBKEY_PASSWORD = "password"; + /** + * Subkey for property with Controller password encryption status + */ + public static final String CONTROLLER_SUBKEY_ENCRYPTED = "is_encrypted"; + + private Environment environment; + + /** + * No-arg constructor + */ + public DashboardProperties() { + } + + protected Environment getEnvironment() { + return environment; + } + + /** + * @param environment + * Environment + */ + @Autowired + public void setEnvironment(final Environment environment) { + this.environment = environment; + } + + /** + * @param key + * Property key + * @return True or false + */ + public boolean containsProperty(final String key) { + return environment.containsProperty(key); + } + + /** + * @param key + * Property key + * @return String value; throws unchecked exception if key is not found + */ + public String getProperty(final String key) { + return environment.getRequiredProperty(key); + } + + /** + * @param key + * Property key + * @return True or False; null if key is not found + */ + public Boolean getBooleanProperty(final String key) { + final String value = getProperty(key); + return Boolean.parseBoolean(value); + } + + /** + * Gets the values for a comma-separated list property value as a String + * array. + * + * @param key + * Property key + * @return Array of values with leading and trailing whitespace removed; + * null if key is not found. + */ + public String[] getCsvListProperty(final String key) { + String listVal = getProperty(key); + if (listVal == null) + return null; + String[] vals = listVal.split("\\s*,\\s*"); + return vals; + } + + /** + * 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 String getControllerProperty(final String controllerKey, final String propKey) { + final String key = controllerKey + '.' + propKey; + return getProperty(key); + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/fusionapp/model/Result.java b/ccsdk-app-common/src/main/java/org/onap/fusionapp/model/Result.java new file mode 100644 index 0000000..1f6328d --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/fusionapp/model/Result.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.fusionapp.model; + +/** + * Trivial model of a String + */ +public class Result { + private String result; + + /** + * @param result + * String + */ + public Result(String result) { + this.result = result; + } + + /** + * @return String + */ + public String getResult() { + return result; + } + + /** + * @param result + * String + */ + public void setResult(String result) { + this.result = result; + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/fusionapp/service/AdminAuthExtension.java b/ccsdk-app-common/src/main/java/org/onap/fusionapp/service/AdminAuthExtension.java new file mode 100644 index 0000000..8a64ab5 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/fusionapp/service/AdminAuthExtension.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.fusionapp.service; + +import org.openecomp.portalsdk.core.domain.User; + +//@Service("adminAuthExtension") +//@Transactional +/** + * Extension supporting action on authorization of user + */ +public class AdminAuthExtension { + + /** + * @param user + * User who was authenticated + */ + public void saveUserExtension(User user) { + // app's developer implement their own logic here, like updating app's + // related tables + } + +} diff --git a/ccsdk-app-common/src/main/java/org/onap/fusionapp/util/CustomLoggingFilter.java b/ccsdk-app-common/src/main/java/org/onap/fusionapp/util/CustomLoggingFilter.java new file mode 100644 index 0000000..1f08b88 --- /dev/null +++ b/ccsdk-app-common/src/main/java/org/onap/fusionapp/util/CustomLoggingFilter.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * =============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. + *******************************************************************************/ +package org.onap.fusionapp.util; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.FilterReply; + +/** + * Custom Filter class bind with logback.xml configuration file to strip out + * certain log messages coming out of special packages or classes. + * + */ +public class CustomLoggingFilter extends Filter<ILoggingEvent> { + + /** + * Custom Filter is added to strip out the continuous U-EB logging messages + * But make sure we log the ERROR and WARNING Level messages. + * + * @param event + * Logging event + */ + @Override + public FilterReply decide(ILoggingEvent event) { + try { + if ((event.getLevel() != Level.ERROR || event.getLevel() != Level.WARN) + && ("UEBConsumerThread".equalsIgnoreCase(event.getThreadName())) + && (event.getLoggerName().contains("com.att.nsa") + || event.getLoggerName().contains("org.apache.http"))) { + return FilterReply.DENY; + } else { + return FilterReply.NEUTRAL; + } + } catch (Exception e) { + return FilterReply.NEUTRAL; + } + } +} |