package org.cloudfoundry.community.servicebroker.controller;
import javax.validation.Valid;
import org.cloudfoundry.community.servicebroker.exception.*;
import org.cloudfoundry.community.servicebroker.model.*;
import org.cloudfoundry.community.servicebroker.service.*;
import org.slf4j.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
* See: http://docs.cloudfoundry.com/docs/running/architecture/services/writing-service.html
*
* @author sgreenberg@gopivotal.com
*/
@Controller
public class ServiceInstanceController extends BaseController {
public static final String BASE_PATH = "/v2/service_instances";
private static final Logger logger = LoggerFactory.getLogger(ServiceInstanceController.class);
private ServiceInstanceService service;
private CatalogService catalogService;
@Autowired
public ServiceInstanceController(ServiceInstanceService service, CatalogService catalogService) {
this.service = service;
this.catalogService = catalogService;
}
@RequestMapping(value = BASE_PATH + "/{instanceId}", method = RequestMethod.PUT)
public ResponseEntity<ServiceInstance> createServiceInstance(
@PathVariable("instanceId") String serviceInstanceId,
@RequestParam(value="accepts_incomplete", required=false) boolean acceptsIncomplete,
@Valid @RequestBody CreateServiceInstanceRequest request) throws
ServiceDefinitionDoesNotExistException,
ServiceInstanceExistsException,
ServiceBrokerException, ServiceBrokerAsyncRequiredException {
logger.debug("PUT: " + BASE_PATH + "/{instanceId}?accepts_incomplete=" + acceptsIncomplete
+ ", createServiceInstance(), serviceInstanceId = " + serviceInstanceId);
ServiceDefinition svc = catalogService.getServiceDefinition(request.getServiceDefinitionId());
if (svc == null) {
throw new ServiceDefinitionDoesNotExistException(request.getServiceDefinitionId());
}
ServiceInstance instance = service.createServiceInstance(
request.withServiceDefinition(svc).and().withServiceInstanceId(serviceInstanceId)
.and().withAcceptsIncomplete(acceptsIncomplete));
logger.debug("ServiceInstance Created: " + instance.getServiceInstanceId());
return new ResponseEntity<>(
instance, instance.isAsync() ? HttpStatus.ACCEPTED : HttpStatus.CREATED);
}
@RequestMapping(value = BASE_PATH + "/{instanceId}/last_operation", method = RequestMethod.GET)
public ResponseEntity<?> getServiceInstanceLastOperation(
@PathVariable("instanceId") String instanceId) {
logger.debug("GET: " + BASE_PATH + "/{instanceId}/last_operation"
+ ", getServiceInstance(), serviceInstanceId = " + instanceId);
ServiceInstance instance = service.getServiceInstance(instanceId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if (null == instance) {
return new ResponseEntity<>("{}", headers, HttpStatus.GONE);
}
ServiceInstanceLastOperation lastOperation = instance.getServiceInstanceLastOperation();
logger.debug("ServiceInstance: " + instance.getServiceInstanceId() + "is in " + lastOperation.getState() + " state. Details : " +lastOperation.getDescription());
return new ResponseEntity<>(lastOperation, headers, HttpStatus.OK);
}
@RequestMapping(value = BASE_PATH + "/{instanceId}", method = RequestMethod.DELETE)
public ResponseEntity<?> deleteServiceInstance(
@PathVariable("instanceId") String instanceId,
@RequestParam("service_id") String serviceId,
@RequestParam("plan_id") String planId,
@RequestParam(value="accepts_incomplete", required=false) boolean acceptsIncomplete)
throws ServiceBrokerException, ServiceBrokerAsyncRequiredException {
logger.debug( "DELETE: " + BASE_PATH + "/{instanceId}?accepts_incomplete=" + acceptsIncomplete
+ ", deleteServiceInstanceBinding(), serviceInstanceId = " + instanceId
+ ", serviceId = " + serviceId
+ ", planId = " + planId);
ServiceInstance instance = service.deleteServiceInstance(
new DeleteServiceInstanceRequest(instanceId, serviceId, planId, acceptsIncomplete));
if (instance == null) {
return new ResponseEntity<>("{}", HttpStatus.GONE);
}
logger.debug("ServiceInstance Deleted: " + instance.getServiceInstanceId());
return new ResponseEntity<>(instance,
instance.isAsync() ? HttpStatus.ACCEPTED : HttpStatus.OK);
}
@RequestMapping(value = BASE_PATH + "/{instanceId}", method = RequestMethod.PATCH)
public ResponseEntity<String> updateServiceInstance(
@PathVariable("instanceId") String instanceId,
@RequestParam(value="accepts_incomplete", required=false) boolean acceptsIncomplete,
@Valid @RequestBody UpdateServiceInstanceRequest request) throws
ServiceInstanceUpdateNotSupportedException,
ServiceInstanceDoesNotExistException,
ServiceBrokerException, ServiceBrokerAsyncRequiredException {
logger.debug("UPDATE: " + BASE_PATH + "/{instanceId}?accepts_incomplete=" + acceptsIncomplete
+ ", updateServiceInstanceBinding(), serviceInstanceId = "
+ instanceId + ", instanceId = " + instanceId + ", planId = "
+ request.getPlanId());
ServiceInstance instance = service.updateServiceInstance(
request.withInstanceId(instanceId).withAcceptsIncomplete(acceptsIncomplete));
logger.debug("ServiceInstance updated: " + instance.getServiceInstanceId());
HttpStatus status = instance.isAsync() ? HttpStatus.ACCEPTED : HttpStatus.OK;
return new ResponseEntity<>("{}", status);
}
@ExceptionHandler(ServiceDefinitionDoesNotExistException.class)
@ResponseBody
public ResponseEntity<ErrorMessage> handleException(ServiceDefinitionDoesNotExistException ex) {
return getErrorResponse(ex.getMessage(), HttpStatus.UNPROCESSABLE_ENTITY);
}
@ExceptionHandler(ServiceInstanceExistsException.class)
@ResponseBody
public ResponseEntity<ErrorMessage> handleException(ServiceInstanceExistsException ex) {
return getErrorResponse(ex.getMessage(), HttpStatus.CONFLICT);
}
@ExceptionHandler(ServiceInstanceUpdateNotSupportedException.class)
@ResponseBody
public ResponseEntity<ErrorMessage> handleException(ServiceInstanceUpdateNotSupportedException ex) {
return getErrorResponse(ex.getMessage(), HttpStatus.UNPROCESSABLE_ENTITY);
}
}