package alien4cloud.rest.orchestrator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Authorization;
import java.util.List;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.validation.Valid;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import alien4cloud.audit.annotation.Audit;
import alien4cloud.model.orchestrators.locations.Location;
import alien4cloud.orchestrators.locations.services.ILocationResourceService;
import alien4cloud.orchestrators.locations.services.LocationService;
import alien4cloud.rest.model.RestResponse;
import alien4cloud.rest.model.RestResponseBuilder;
import alien4cloud.rest.orchestrator.model.CreateLocationRequest;
import alien4cloud.rest.orchestrator.model.LocationDTO;
import alien4cloud.rest.orchestrator.model.UpdateLocationRequest;
import alien4cloud.security.AuthorizationUtil;
import alien4cloud.security.model.DeployerRole;
import alien4cloud.utils.ReflectionUtil;
import com.google.common.collect.Lists;
/**
* Controller that manages locations for orchestrators.
*/
@RestController
@RequestMapping(value = {"/rest/orchestrators/{orchestratorId}/locations", "/rest/v1/orchestrators/{orchestratorId}/locations", "/rest/latest/orchestrators/{orchestratorId}/locations", "/rest/latest/orchestrators/{orchestratorId}/locations", "/rest/latest/orchestrators/{orchestratorId}/locations"}, produces = MediaType.APPLICATION_JSON_VALUE)
@Api(value = "Orchestrators Locations", description = "Manages locations for a given orchestrator.", authorizations = { @Authorization("ADMIN") }, position = 4400)
public class LocationController {
@Inject
private LocationService locationService;
@Resource(name = "location-resource-service")
private ILocationResourceService locationResourceService;
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Create a new location.", authorizations = { @Authorization("ADMIN") })
@ResponseStatus(value = HttpStatus.CREATED)
@PreAuthorize("hasAuthority('ADMIN')")
@Audit
public RestResponse<String> create(@ApiParam(value = "Id of the orchestrator for which the location is defined.") @PathVariable String orchestratorId,
@ApiParam(value = "Request for location creation", required = true) @Valid @RequestBody CreateLocationRequest locationRequest) {
String id = locationService.create(orchestratorId, locationRequest.getName(), locationRequest.getInfrastructureType());
return RestResponseBuilder.<String> builder().data(id).build();
}
@ApiOperation(value = "Delete an existing location.", authorizations = { @Authorization("ADMIN") })
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
@PreAuthorize("hasAuthority('ADMIN')")
@Audit
public RestResponse<Boolean> delete(@ApiParam(value = "Id of the orchestrator for which the location is defined.") @PathVariable String orchestratorId,
@ApiParam(value = "Id of the location to delete.", required = true) @PathVariable String id) {
return RestResponseBuilder.<Boolean> builder().data(locationService.delete(orchestratorId, id)).build();
}
@ApiOperation(value = "Get all locations for a given orchestrator.")
@RequestMapping(method = RequestMethod.GET)
@PreAuthorize("isAuthenticated()")
public RestResponse<List<LocationDTO>> getAll(
@ApiParam(value = "Id of the orchestrator for which to get all locations.") @PathVariable String orchestratorId) {
List<Location> locations = locationService.getAll(orchestratorId);
List<LocationDTO> locationDTOs = Lists.newArrayList();
for (Location location : locations) {
locationDTOs.add(buildLocationDTO(location));
}
return RestResponseBuilder.<List<LocationDTO>> builder().data(locationDTOs).build();
}
@ApiOperation(value = "Get a location from it's id.")
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@PreAuthorize("isAuthenticated()")
public RestResponse<LocationDTO> get(@ApiParam(value = "Id of the orchestrator for which the location is defined.") @PathVariable String orchestratorId,
@ApiParam(value = "Id of the location to get", required = true) @PathVariable String id) {
Location location = locationService.getOrFail(id);
AuthorizationUtil.checkAuthorizationForLocation(location, DeployerRole.DEPLOYER);
return RestResponseBuilder.<LocationDTO> builder().data(buildLocationDTO(location)).build();
}
@ApiOperation(value = "Update the name of an existing location.", authorizations = { @Authorization("ADMIN") })
@RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('ADMIN')")
@Audit
public RestResponse<Void> update(
@ApiParam(value = "Id of the orchestrator for which the location is defined.") @PathVariable String orchestratorId,
@ApiParam(value = "Id of the location to update", required = true) @PathVariable String id,
@ApiParam(value = "Location update request, representing the fields to updates and their new values.", required = true) @Valid @NotEmpty @RequestBody UpdateLocationRequest updateRequest) {
Location location = locationService.getOrFail(id);
String currentName = location.getName();
ReflectionUtil.mergeObject(updateRequest, location);
locationService.ensureNameUnicityAndSave(location, currentName);
return RestResponseBuilder.<Void> builder().build();
}
private LocationDTO buildLocationDTO(Location location) {
LocationDTO locationDTO = new LocationDTO();
locationDTO.setResources(locationResourceService.getLocationResources(location));
locationDTO.setLocation(location);
return locationDTO;
}
}