/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package controllers.api;
import static com.emc.vipr.client.core.util.ResourceUtils.uri;
import static render.RenderApiModel.renderApi;
import static util.BourneUtil.getCatalogClient;
import static util.Json.renderPrettyJson;
import static util.api.ApiMapperUtils.newCategoryInfo;
import static util.api.ApiMapperUtils.newOrderInfo;
import static util.api.ApiMapperUtils.newServiceInfo;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import play.data.validation.Validation;
import play.i18n.Messages;
import util.CatalogCategoryUtils;
import util.CatalogServiceUtils;
import util.ServiceDescriptorUtils;
import com.emc.storageos.model.DataObjectRestRep;
import com.emc.vipr.model.catalog.CatalogCategoryRestRep;
import com.emc.vipr.model.catalog.CatalogServiceFieldRestRep;
import com.emc.vipr.model.catalog.CatalogServiceRestRep;
import com.emc.vipr.model.catalog.OrderCreateParam;
import com.emc.vipr.model.catalog.OrderRestRep;
import com.emc.vipr.model.catalog.ServiceDescriptorRestRep;
import com.emc.vipr.model.catalog.ServiceFieldRestRep;
import com.emc.vipr.model.catalog.ValidationError;
import com.google.common.collect.Lists;
import controllers.catalog.OrderExecution;
/**
* Catalog API. API for access services and performing orders.
*
* Note: setSelectedVdc() is used before most of the service. This is a utility to set the VDC based on the VDC name
* passed in. The API does not have the same interaction as the portal where the user can choose the active VDC in the
* corner. Instead, the VDC is passed in on each request. Set this into the session so the code is consistent
* regardless of where the VDC comes from.
*
* @author Chris Dail
*/
public class CatalogApi extends OrderExecution {
public static void serviceDescriptor(String serviceId) {
CatalogServiceRestRep service = CatalogServiceUtils.getCatalogService(uri(serviceId));
ServiceDescriptorRestRep descriptor = service.getServiceDescriptor();
// Remove any locked fields so user does not see things they cannot change
for (CatalogServiceFieldRestRep catalogServiceField : service.getCatalogServiceFields()) {
if (catalogServiceField.getOverride()) {
ServiceFieldRestRep serviceField = ServiceDescriptorUtils.getField(descriptor, catalogServiceField.getName());
descriptor.getItems().remove(serviceField);
}
}
renderPrettyJson(descriptor);
}
public static void invoke(String serviceId) {
runCatalogService(serviceId);
}
public static void invokeByPath(String sp1, String sp2, String sp3, String sp4, String sp5) {
CatalogCategoryRestRep catalog = CatalogCategoryUtils.getRootCategory();
DataObjectRestRep results = findCategoryOrService(catalog, sp1, sp2, sp3, sp4, sp5);
if (results != null && results instanceof CatalogServiceRestRep) {
CatalogServiceRestRep catalogService = (CatalogServiceRestRep) results;
runCatalogService(catalogService.getId().toString());
}
else {
notFound();
}
}
public static void browseCatalog(String sp1, String sp2, String sp3, String sp4, String sp5) {
CatalogCategoryRestRep catalogCategory = CatalogCategoryUtils.getRootCategory();
DataObjectRestRep result = findCategoryOrService(catalogCategory, sp1, sp2, sp3, sp4, sp5);
if (result instanceof CatalogCategoryRestRep) {
renderApi(newCategoryInfo((CatalogCategoryRestRep) result));
}
else if (result instanceof CatalogServiceRestRep) {
renderApi(newServiceInfo((CatalogServiceRestRep) result));
}
}
public static void category(String categoryId) {
CatalogCategoryRestRep category = CatalogCategoryUtils.getCatalogCategory(uri(categoryId));
renderApi(newCategoryInfo(category));
}
public static void service(String serviceId) {
CatalogServiceRestRep service = CatalogServiceUtils.getCatalogService(uri(serviceId));
renderApi(newServiceInfo(service));
}
/**
* Recursively traverse a list of sub-paths to find the category or service.
*/
private static DataObjectRestRep findCategoryOrService(CatalogCategoryRestRep root, String... subPaths) {
if (subPaths == null) {
return root;
}
DataObjectRestRep result = root;
for (String path : subPaths) {
if (StringUtils.isBlank(path)) {
continue;
}
if (result instanceof CatalogCategoryRestRep) {
result = getCategoryOrService((CatalogCategoryRestRep) result, path);
if (result == null) {
notFound(Messages.get("CatalogApi.subpathNotFound", path));
}
}
}
return result;
}
private static DataObjectRestRep getCategoryOrService(CatalogCategoryRestRep category, String subPath) {
if (category != null) {
List<CatalogServiceRestRep> catalogServices = CatalogServiceUtils.getCatalogServices(category);
for (CatalogServiceRestRep catalogService : catalogServices) {
if (StringUtils.equalsIgnoreCase(subPath, catalogService.getName())) {
return catalogService;
}
}
List<CatalogCategoryRestRep> subCatalogCategories = CatalogCategoryUtils.getCatalogCategories(category);
for (CatalogCategoryRestRep subCatalogCategory : subCatalogCategories) {
if (StringUtils.equalsIgnoreCase(subPath, subCatalogCategory.getName())) {
return subCatalogCategory;
}
}
}
return null;
}
private static void runCatalogService(String serviceId) {
params.checkAndParse();
OrderCreateParam order = createAndValidateOrder(serviceId);
OrderRestRep submittedOrder = getCatalogClient().orders().submit(order);
renderApi(newOrderInfo(submittedOrder));
}
private static OrderCreateParam createAndValidateOrder(String serviceId) {
CatalogServiceRestRep service = CatalogServiceUtils.getCatalogService(uri(serviceId));
ServiceDescriptorRestRep descriptor = service.getServiceDescriptor();
// Filter out actual Service Parameters
Map<String, String> parameters = parseParameters(service, descriptor);
if (Validation.hasErrors()) {
response.status = HttpStatus.SC_BAD_REQUEST;
renderApi(getValidationErrors());
}
// Create request and perform selection
OrderCreateParam order = createOrder(service, descriptor, parameters);
return order;
}
private static List<ValidationError> getValidationErrors() {
List<ValidationError> errors = Lists.newArrayList();
for (play.data.validation.Error error : Validation.errors()) {
errors.add(new ValidationError(error.getKey(), error.message()));
}
return errors;
}
}