Commit a17bc6cd authored by Francesco Chicchiricco's avatar Francesco Chicchiricco
Browse files

[CRV-19] Restoring features after technical meeting in Milan's review of ChoreographyApi

parent ab1c0123
......@@ -18,118 +18,116 @@ package eu.chorevolution.idm.choremocks.ee;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.io.InputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/v1/choreography")
@Api("Choreography")
@Produces(MediaType.APPLICATION_JSON)
public interface ChoreographyApi {
@GET
@Path("/start/{choreographyId}")
@POST
@Path("/{choreographyId}/start")
@ApiOperation(
value = "Start a running choreography."
)
Response start(
@ApiParam(name = "choreographyId", value = "The ID of the choregraphy to start", required = true)
@PathParam("choreographyId")
String choreographyId);
@PathParam("choreographyId") String choreographyId);
@GET
@Path("/stop/{choreographyId}")
@POST
@Path("/{choreographyId}/stop")
@ApiOperation(
value = "Stop a running choreography."
)
Response stop(
@ApiParam(name = "choreographyId", value = "The ID of the choregraphy to stop", required = true)
@PathParam("choreographyId")
String choreographyId);
@PathParam("choreographyId") String choreographyId);
@GET
@Path("/pause/{choreographyId}")
@POST
@Path("/{choreographyId}/pause")
@ApiOperation(
value = "Pause a running choreography."
)
Response pause(
@ApiParam(name = "choreographyId", value = "The ID of the choregraphy to pause", required = true)
@PathParam("choreographyId")
String choreographyId);
@PathParam("choreographyId") String choreographyId);
/*
@ApiOperation(
value = "Check the status of a choreography deployment process."
)
@ApiErrors(value = {
@ApiError(code = 404, reason = "Choreography not existing")
})*/
@GET
@Path("/check_status/{choreographyId}")
Response check_status(
@Path("/{choreographyId}/check_status")
Response checkStatus(
@ApiParam(name = "choreographyId", value = "The ID of the choregraphy to check", required = true)
@PathParam("choreographyId")
String choreographyId);
@PathParam("choreographyId") String choreographyId);
@POST
@Path("/deploy/{choreographyName}")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/")
@Consumes(MediaType.APPLICATION_XML)
@ApiOperation(
value = "Deploy a choreography onto a cloud environment.",
response = org.apache.brooklyn.rest.domain.TaskSummary.class
)
@ApiResponses(value = {
@ApiResponse(code = 404, message = "Undefined entity or location"),
@ApiResponse(code = 412, message = "Choreography already registered")
})
Response deploy(
@ApiParam(name = "choreographyName", value = "Choreography name", required = true)
@PathParam("choreographyName") String choreographyName,
@ApiParam(name = "chorSpec", value = "Choreography specifications", required = true)
InputStream chorSpec);
@QueryParam("choreographyName") String choreographyName,
@ApiParam(name = "chorSpec", value = "Choreography specifications", required = true) InputStream chorSpec);
@PUT
@Path("/update/{choreographyId}")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{choreographyId}")
@Consumes(MediaType.APPLICATION_XML)
@ApiOperation(
value = "Deploy a choreography onto a cloud environment.",
value = "Update an existing choreography onto a cloud environment.",
response = org.apache.brooklyn.rest.domain.TaskSummary.class
)
@ApiResponses(value = {
@ApiResponse(code = 404, message = "Undefined entity or location"),
@ApiResponse(code = 412, message = "Choreography already registered")
})
Response update(
@ApiParam(name = "choreographyId", value = "Choreography ID", required = true)
@PathParam("choreographyId") String choreographyId,
@ApiParam(name = "choreographyName", value = "Choreography name", required = true)
@QueryParam("choreographyName") String choreographyName,
@ApiParam(name = "chorSpec", value = "Choreography specifications", required = true)
InputStream chorSpec);
@ApiParam(name = "chorSpec", value = "Choreography specifications", required = true) InputStream chorSpec);
@DELETE
@Path("/{choreographyId}")
@ApiOperation(
value = "Undeploy a choreography."
)
Response undeploy(
@ApiParam(name = "choreographyId", value = "The ID of the choregraphy to undeploy", required = true)
@PathParam("choreographyId") String choreographyId);
@PUT
@Path("/{choreographyId}/replaceService/{serviceRole}/{serviceName}")
@ApiOperation(
value = "Replace the given service endpoint",
response = org.apache.brooklyn.rest.domain.TaskSummary.class
)
Response replaceService(
@ApiParam(name = "choreographyId", value = "Choreography ID", required = true)
@PathParam("choreographyId") String choreographyId,
@ApiParam(name = "serviceRole", value = "Service name", required = true)
@PathParam("serviceRole") String serviceRole,
@ApiParam(name = "serviceName", value = "Service name", required = true)
@PathParam("serviceRole") String serviceName,
@QueryParam("serviceEndpoint") String serviceEndpoint);
@POST
@Path("/resize/{choreographyId}")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{choreographyId}/resize")
@ApiOperation(
value = "Resize VM pool running a running choreography.",
response = org.apache.brooklyn.rest.domain.TaskSummary.class
)
@ApiResponses(value = {
@ApiResponse(code = 404, message = "Undefined entity or location"),
@ApiResponse(code = 412, message = "Choreography already registered")
})
Response resize(
@ApiParam(name = "choreographyId", value = "Choreography ID", required = true)
@PathParam("choreographyId") String choreographyId,
@ApiParam(name = "desired_pool_size", value = "Desired size of the VMs pool", required = true)
int desired_size);
@QueryParam("newSize") Integer newSize);
}
......@@ -19,17 +19,20 @@ import eu.chorevolution.idm.common.types.ChoreographyOperation;
import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.brooklyn.rest.domain.TaskSummary;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
import org.apache.syncope.common.rest.api.service.ChoreographyService;
......@@ -42,7 +45,7 @@ public class ChoreographyResource implements ChoreographyApi {
private static final Logger LOG = LoggerFactory.getLogger(ChoreographyResource.class);
private static final Set<String> DEPLOYED = Collections.synchronizedSet(new HashSet<>());
private static final Map<String, String> DEPLOYED = Collections.synchronizedMap(new HashMap<>());
private static final ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(5);
......@@ -52,7 +55,7 @@ public class ChoreographyResource implements ChoreographyApi {
@Override
public Response deploy(final String choreographyName, final InputStream chorSpec) {
String choreographyId = UUID.randomUUID().toString();
DEPLOYED.add(choreographyId);
DEPLOYED.put(choreographyId, choreographyName);
EXECUTOR.schedule(new CompletionNotifier(
choreographyId,
......@@ -89,9 +92,10 @@ public class ChoreographyResource implements ChoreographyApi {
@Override
public Response update(final String choreographyId, final String choreographyName, final InputStream chorSpec) {
if (!DEPLOYED.contains(choreographyId)) {
if (!DEPLOYED.containsKey(choreographyId)) {
throw new NotFoundException("Choreography " + choreographyId);
}
DEPLOYED.put(choreographyId, choreographyName);
EXECUTOR.schedule(new CompletionNotifier(
choreographyId,
......@@ -101,7 +105,7 @@ public class ChoreographyResource implements ChoreographyApi {
getClass().getResourceAsStream("/" + choreographyName + "_update.xml")),
3, TimeUnit.SECONDS);
return Response.ok().
return Response.accepted().
entity(new TaskSummary(
UUID.randomUUID().toString(),
"Update Task for " + choreographyId,
......@@ -127,17 +131,12 @@ public class ChoreographyResource implements ChoreographyApi {
}
@Override
public Response start(final String choreography_id) {
return null;
}
@Override
public Response stop(final String choreographyId) {
if (!DEPLOYED.contains(choreographyId)) {
public Response undeploy(final String choreographyId) {
if (!DEPLOYED.containsKey(choreographyId)) {
throw new NotFoundException("Choreography " + choreographyId);
}
DEPLOYED.remove(choreographyId);
String choreographyName = DEPLOYED.remove(choreographyId);
EXECUTOR.schedule(new CompletionNotifier(
choreographyId,
......@@ -147,13 +146,13 @@ public class ChoreographyResource implements ChoreographyApi {
null),
3, TimeUnit.SECONDS);
return Response.noContent().
return Response.accepted().
entity(new TaskSummary(
UUID.randomUUID().toString(),
"Delete Task for " + choreographyId,
null,
choreographyId,
null,
choreographyName,
null,
new Date().getTime(),
new Date().getTime(),
......@@ -172,18 +171,38 @@ public class ChoreographyResource implements ChoreographyApi {
build();
}
@Override
public Response checkStatus(final String choreographyId) {
return null;
}
@Override
public Response start(final String choreography_id) {
return null;
}
@Override
public Response stop(final String choreographyId) {
return null;
}
@Override
public Response pause(final String choreography_id) {
return null;
}
@Override
public Response check_status(final String choreography_id) {
public Response resize(final String choreographyId, final Integer newSize) {
return null;
}
@Override
public Response resize(final String choreography_name, final int desired_size) {
public Response replaceService(
final String choreographyId,
final String serviceRole,
final String serviceName,
final String serviceEndpoint) {
return null;
}
......@@ -222,9 +241,15 @@ public class ChoreographyResource implements ChoreographyApi {
@Override
public void run() {
LOG.debug("Notifying {} {}", id, operation);
client.getService(ChoreographyService.class).
notifyCompletion(id, name, operation, message, enactedChorSpec);
LOG.debug("Notified {} {}", id, operation);
try {
ChoreographyService service = client.getService(ChoreographyService.class);
WebClient.getConfig(service).getOutInterceptors().add(new LoggingOutInterceptor());
WebClient.client(service).type(MediaType.APPLICATION_XML_TYPE);
service.notifyCompletion(id, name, operation, message, enactedChorSpec);
LOG.debug("Notified {} {}", id, operation);
} catch (Exception e) {
LOG.error("While notifying", e);
}
}
}
......
......@@ -16,13 +16,16 @@ limitations under the License.
-->
<configuration>
<appender name="main" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<!--<logger name="org.apache.cxf" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="main"/>
</logger>-->
<root>
<level value="ERROR"/>
<appender-ref ref="main"/>
......
......@@ -17,7 +17,7 @@ package eu.chorevolution.idm.common.types;
public enum ServiceAction {
/**
* Enforce security context if and only if Secury Filter is available.
* Enforce security context if and only if Security Filter is available.
*/
ENFORCE,
/**
......
......@@ -27,6 +27,7 @@ import eu.chorevolution.idm.common.types.ChoreographyAction;
import eu.chorevolution.idm.common.types.ChoreographyOperation;
import eu.chorevolution.idm.common.types.ServiceAction;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
......@@ -38,6 +39,8 @@ import javax.ws.rs.BadRequestException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBException;
import javax.xml.stream.XMLStreamException;
import org.apache.cxf.helpers.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.common.util.Base64Utility;
......@@ -154,7 +157,7 @@ public class ChoreographyLogic extends AbstractLogic<AbstractBaseBean> {
providers.add(new JacksonJaxbJsonProvider());
return WebClient.create(
StringUtils.removeEndIgnoreCase(baseURL, "/") + endpoint, providers, username, password, null).
accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE);
accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_XML_TYPE);
}
@PreAuthorize("hasRole('" + ChorevolutionEntitlement.CHOREOGRAPHY_CREATE + "')")
......@@ -163,7 +166,7 @@ public class ChoreographyLogic extends AbstractLogic<AbstractBaseBean> {
Response response;
try {
WebClient webClient = getWebClient(enactmentEngineKey, "/deploy/" + name);
WebClient webClient = getWebClient(enactmentEngineKey, "/?choreographyName=" + name);
response = webClient.post(chorSpec);
if (response.getStatus() != Response.Status.CREATED.getStatusCode()) {
throw new WebApplicationException(response);
......@@ -205,9 +208,9 @@ public class ChoreographyLogic extends AbstractLogic<AbstractBaseBean> {
checkChoreographyExists(id);
try {
WebClient webClient = getWebClient(enactmentEngineKey, "/update/" + id + "?choreographyName=" + name);
Response response = webClient.post(chorSpec);
if (response.getStatus() != Response.Status.OK.getStatusCode()) {
WebClient webClient = getWebClient(enactmentEngineKey, "/" + id + "?choreographyName=" + name);
Response response = webClient.put(chorSpec);
if (response.getStatus() != Response.Status.ACCEPTED.getStatusCode()) {
throw new WebApplicationException(response);
}
} catch (Exception e) {
......@@ -220,9 +223,9 @@ public class ChoreographyLogic extends AbstractLogic<AbstractBaseBean> {
checkChoreographyExists(id);
try {
WebClient webClient = getWebClient(enactmentEngineKey, "/stop/" + id);
Response response = webClient.get();
if (response.getStatus() != Response.Status.NO_CONTENT.getStatusCode()) {
WebClient webClient = getWebClient(enactmentEngineKey, "/" + id);
Response response = webClient.delete();
if (response.getStatus() != Response.Status.ACCEPTED.getStatusCode()) {
throw new WebApplicationException(response);
}
} catch (Exception e) {
......@@ -247,7 +250,7 @@ public class ChoreographyLogic extends AbstractLogic<AbstractBaseBean> {
try {
chorSpecXML = IOUtils.readBytesFromStream(enactedChorSpec);
parsed = Choreography.fromXML(new ByteArrayInputStream(chorSpecXML));
} catch (Exception e) {
} catch (IOException | JAXBException | XMLStreamException e) {
throw new BadRequestException("While reading enacted chorSpec for choreography " + id, e);
}
}
......@@ -361,6 +364,30 @@ public class ChoreographyLogic extends AbstractLogic<AbstractBaseBean> {
@PreAuthorize("hasRole('" + ChorevolutionEntitlement.ON_CHOREOGRAPHY + "')")
public void onChoreography(final String id, final ChoreographyAction action, final Integer newSize) {
switch (action) {
case START:
// ChoreographyApi#start()
break;
case STOP:
// ChoreographyApi#stop()
break;
case FREEZE:
// ChoreographyApi#pause()
break;
case UNFREEZE:
// ChoreographyApi#start()
break;
case RESIZE:
// ChoreographyApi#resize()
break;
default:
}
}
@PreAuthorize("hasRole('" + ChorevolutionEntitlement.ON_CHOREOGRAPHY_SERVICE + "')")
......
......@@ -92,11 +92,12 @@ public interface ChoreographyService extends JAXRSService {
*/
@POST
@Path("{id}/{operation}/notifyCompletion")
@Consumes({ MediaType.APPLICATION_XML })
void notifyCompletion(
@NotNull @PathParam("id") String id,
@NotNull @QueryParam("name") String name,
@NotNull @PathParam("operation") ChoreographyOperation operation,
@NotNull @QueryParam("message") String message,
@QueryParam("message") String message,
InputStream enactedChorSpec);
/**
......@@ -112,7 +113,7 @@ public interface ChoreographyService extends JAXRSService {
void onChoreography(
@NotNull @PathParam("id") String id,
@NotNull @QueryParam("action") ChoreographyAction action,
Integer newSize);
@QueryParam("newSize") Integer newSize);
/**
* Performs the given action on the given choreography's service.
......@@ -130,6 +131,6 @@ public interface ChoreographyService extends JAXRSService {
@NotNull @PathParam("id") String id,
@NotNull @PathParam("serviceId") String serviceId,
@NotNull @QueryParam("action") ServiceAction action,
String argument);
@QueryParam("argument") String argument);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment