mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2024-12-22 15:13:41 -06:00
workspaces incremental progress
This commit is contained in:
parent
4e8370a6a3
commit
1b96f8876d
@ -4,11 +4,18 @@ package io.nosqlbench.docsys.api;
|
|||||||
* Any class which is annotated with <pre>{@code @Service(WebServiceObject.class)}</pre>
|
* Any class which is annotated with <pre>{@code @Service(WebServiceObject.class)}</pre>
|
||||||
* will be found and loaded as a service.
|
* will be found and loaded as a service.
|
||||||
*
|
*
|
||||||
* For the methods used to configure these objects, consult
|
* For the methods used to configure these objects, consult the
|
||||||
* <A href="https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/jaxrs-resources.html#d0e2040">jax-rs resources documentation</A>
|
* references below:
|
||||||
*
|
*
|
||||||
* and
|
* @see <A href="https://eclipse-ee4j.github.io/jersey.github
|
||||||
* <A href="https://jax-rs.github.io/apidocs/2.1/">Jax-RS API Docs</A>
|
* .io/documentation/latest/jaxrs-resources.html#d0e2040">Jersey jax-rs
|
||||||
|
* resources documentation</A>
|
||||||
|
*
|
||||||
|
* @see <A href="https://github.com/jax-rs/spec/blob/master/spec
|
||||||
|
* .pdf">JAX-RS: Java™ API for RESTful Web Services Version 2.1
|
||||||
|
* Proposed Final Draft June 9, 2017</A>
|
||||||
|
**
|
||||||
|
* @see <A href="https://jax-rs.github.io/apidocs/2.1/">Jax-RS API Docs</A>
|
||||||
*/
|
*/
|
||||||
public interface WebServiceObject {
|
public interface WebServiceObject {
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import javax.ws.rs.core.MediaType;
|
|||||||
@Singleton
|
@Singleton
|
||||||
@Path("_")
|
@Path("_")
|
||||||
public class DocServerStatusEndpoint implements WebServiceObject {
|
public class DocServerStatusEndpoint implements WebServiceObject {
|
||||||
|
|
||||||
private final static Logger logger =
|
private final static Logger logger =
|
||||||
LogManager.getLogger(DocServerStatusEndpoint.class);
|
LogManager.getLogger(DocServerStatusEndpoint.class);
|
||||||
|
|
||||||
|
32
docsys/src/main/node/docsys/pages/ui/workspaces/index.vue
Normal file
32
docsys/src/main/node/docsys/pages/ui/workspaces/index.vue
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<template>
|
||||||
|
<v-app>
|
||||||
|
<v-app-bar app dark color="secondary">
|
||||||
|
<v-toolbar-title>NoSQLBench - Workspaces</v-toolbar-title>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-toolbar-items>
|
||||||
|
<v-btn text href="https://github.com/nosqlbench/nosqlbench/wiki/Submitting-Feedback">SUBMIT FEEDBACK</v-btn>
|
||||||
|
</v-toolbar-items>
|
||||||
|
</v-app-bar>
|
||||||
|
|
||||||
|
<v-layout justify-center align-center>
|
||||||
|
<v-content>
|
||||||
|
<v-card max-width="344">
|
||||||
|
<v-card-title>workspace-name</v-card-title>
|
||||||
|
<v-card-text>workspace details go here</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
</v-content>
|
||||||
|
</v-layout>
|
||||||
|
|
||||||
|
</v-app>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "workspaces.vue"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -1,93 +1,103 @@
|
|||||||
package io.nosqlbench.engine.rest.resources;
|
package io.nosqlbench.engine.rest.resources;
|
||||||
|
|
||||||
import io.nosqlbench.docsys.api.WebServiceObject;
|
import io.nosqlbench.docsys.api.WebServiceObject;
|
||||||
import io.nosqlbench.engine.rest.domain.WorkSpace;
|
import io.nosqlbench.engine.rest.services.WorkspaceService;
|
||||||
import io.nosqlbench.engine.rest.transfertypes.WorkspaceView;
|
import io.nosqlbench.engine.rest.transfertypes.WorkspaceView;
|
||||||
import io.nosqlbench.engine.rest.transfertypes.WorkspacesInfo;
|
|
||||||
import io.nosqlbench.nb.annotations.Service;
|
import io.nosqlbench.nb.annotations.Service;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.*;
|
||||||
|
import javax.ws.rs.core.Configuration;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.io.IOException;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Optional;
|
import java.util.List;
|
||||||
|
|
||||||
@Path("/services/workspaces")
|
@Path("/services/workspaces/")
|
||||||
@Singleton
|
@Singleton
|
||||||
@Service(WebServiceObject.class)
|
@Service(WebServiceObject.class)
|
||||||
public class WorkspacesEndpoint implements WebServiceObject {
|
public class WorkspacesEndpoint implements WebServiceObject {
|
||||||
|
|
||||||
private final static java.nio.file.Path workspacesRoot = Paths.get("workspaces");
|
private final static Logger logger =
|
||||||
|
LogManager.getLogger(WorkspacesEndpoint.class);
|
||||||
|
|
||||||
|
public static final String WORKSPACE_ROOT = "workspace_root";
|
||||||
|
|
||||||
|
@Context
|
||||||
|
private Configuration config;
|
||||||
|
|
||||||
|
private final static java.nio.file.Path workspacesRoot = Paths.get("workspaces");
|
||||||
|
private WorkspaceService svc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A list of workspaces as a
|
||||||
|
* {@link List} of {@link WorkspaceView}
|
||||||
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response listWorkspaces() {
|
public Response getWorkspacesInfo() {
|
||||||
WorkspacesInfo info = new WorkspacesInfo(workspacesRoot);
|
List<WorkspaceView> wsviews = getSvc().getWorkspaceViews();
|
||||||
return Response.ok(info).build();
|
return Response.ok(wsviews).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{workspace}")
|
@Path("{workspace}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response listWorkspace(@PathParam("workspace") String workspace) {
|
public Response getWorkspaceInfo(@PathParam("workspace") String workspace) {
|
||||||
WorkspaceView view = new WorkspaceView(workspace);
|
WorkspaceView workpaceView = getSvc().getWorkspaceView(workspace);
|
||||||
return Response.ok(view).build();
|
return Response.ok(workpaceView).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("{workspaceName}/upload/{filepath}")
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
public Response uploadFileIntoWorkspace(
|
||||||
|
) {
|
||||||
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("{workspaceName}/{filepath}")
|
@Path("{workspaceName}/{filepath}")
|
||||||
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
|
public Response putFileInWorkspace(
|
||||||
public Response putFile(
|
@PathParam("workspaceName") String workspaceName,
|
||||||
@PathParam("workspaceName") String workspaceName,
|
@PathParam("filepath") String filename,
|
||||||
@PathParam("filepath") String filename
|
ByteBuffer content
|
||||||
) {
|
) {
|
||||||
WorkSpace workspace = getWorkspace(workspaceName);
|
try {
|
||||||
Optional<Path> puttedFile = workspace.put(workspace);
|
getSvc().putFile(workspaceName, filename, content);
|
||||||
if (puttedFile.isPresent()) {
|
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
} else {
|
} catch (Exception e) {
|
||||||
return Response.status(Response.Status.BAD_REQUEST).build();
|
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{workspaceName}/{filename}")
|
@Path("{workspaceName}/{filename}")
|
||||||
public Response getFile(
|
public Response getFileInWorkspace(
|
||||||
@PathParam("workspaceName") String workspaceName,
|
@PathParam("workspaceName") String workspaceName,
|
||||||
@PathParam("filename") String filename) {
|
@PathParam("filename") String filename) {
|
||||||
|
|
||||||
WorkSpace workSpace = new WorkSpace(workspacesRoot, workspaceName);
|
try {
|
||||||
Optional<java.nio.file.Path> optFile = workSpace.get(filename);
|
WorkspaceService.FileInfo fileinfo = getSvc().readFile(workspaceName, filename);
|
||||||
|
if (fileinfo != null) {
|
||||||
if (optFile.isPresent()) {
|
return Response.ok(fileinfo.getContent(), fileinfo.getMediaType()).build();
|
||||||
try {
|
} else {
|
||||||
java.nio.file.Path filepath = optFile.get();
|
return Response.noContent().status(Response.Status.NOT_FOUND).build();
|
||||||
String contentType = Files.probeContentType(filepath);
|
|
||||||
MediaType mediaType = MediaType.valueOf(contentType);
|
|
||||||
|
|
||||||
byte[] bytes = Files.readAllBytes(filepath);
|
|
||||||
return Response.ok(bytes, mediaType).build();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
} else {
|
} catch (Exception e) {
|
||||||
return Response.noContent().status(Response.Status.NOT_FOUND).build();
|
return Response.serverError().entity(e.getMessage()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WorkspaceService getSvc() {
|
||||||
private WorkSpace getWorkspace(String workspace) {
|
if (svc == null) {
|
||||||
if (!workspace.matches("[a-zA-Z][a-zA-Z0-9]+")) {
|
svc = new WorkspaceService(config.getProperties().get(WORKSPACE_ROOT));
|
||||||
throw new RuntimeException("Workspaces must start with an alphabetic" +
|
|
||||||
" character, and contain only letters and numbers.");
|
|
||||||
}
|
}
|
||||||
WorkSpace workSpace = new WorkSpace(workspacesRoot, workspace);
|
return svc;
|
||||||
return workSpace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,134 @@
|
|||||||
|
package io.nosqlbench.engine.rest.services;
|
||||||
|
|
||||||
|
import io.nosqlbench.engine.rest.transfertypes.WorkspaceView;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WorkspaceService {
|
||||||
|
private final Path root;
|
||||||
|
public static String DEFAULT = "default";
|
||||||
|
|
||||||
|
public WorkspaceService(Object root) {
|
||||||
|
if (root instanceof Path) {
|
||||||
|
this.root = (Path) root;
|
||||||
|
} else if (root instanceof CharSequence) {
|
||||||
|
this.root = Paths.get(((CharSequence) root).toString());
|
||||||
|
} else if (root == null) {
|
||||||
|
this.root = Paths.get(System.getProperty("user.dir"),
|
||||||
|
"workspaces");
|
||||||
|
try {
|
||||||
|
Files.createDirectories(this.root);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unable to use workspaces root " +
|
||||||
|
"path of type " + root.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
createDefaultIfNotExist();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createDefaultIfNotExist() {
|
||||||
|
getWorkspaceView(DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WorkspaceView> getWorkspaceViews() {
|
||||||
|
List<WorkspaceView> views = new ArrayList<>();
|
||||||
|
DirectoryStream<Path> wsrEntries = null;
|
||||||
|
try {
|
||||||
|
wsrEntries = Files.newDirectoryStream(root);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Path entry : wsrEntries) {
|
||||||
|
views.add(new WorkspaceView(entry));
|
||||||
|
}
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkspaceView getWorkspaceView(String workspace) {
|
||||||
|
if (!workspace.matches("[a-zA-Z][a-zA-Z0-9]+")) {
|
||||||
|
throw new RuntimeException("Workspaces must start with an alphabetic" +
|
||||||
|
" character, and contain only letters and numbers.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Path wspath = root.resolve(Paths.get(workspace));
|
||||||
|
if (!Files.exists(wspath)) {
|
||||||
|
try {
|
||||||
|
Files.createDirectories(wspath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new WorkspaceView(wspath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putFile(String workspaceName, String filename, ByteBuffer content) {
|
||||||
|
Path toWrite = root.resolve(workspaceName).resolve(filename);
|
||||||
|
try {
|
||||||
|
Files.write(toWrite, content.array(),
|
||||||
|
StandardOpenOption.TRUNCATE_EXISTING,
|
||||||
|
StandardOpenOption.CREATE,
|
||||||
|
StandardOpenOption.WRITE);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the bytes of the named file in the named workspace.
|
||||||
|
*
|
||||||
|
* @param workspaceName The workspace name to look in for the file
|
||||||
|
* @param filename The filename within the workspace to read
|
||||||
|
* @return null if the file is not found
|
||||||
|
* @throws RuntimeException if the file was found but could not be
|
||||||
|
* read.
|
||||||
|
*/
|
||||||
|
public FileInfo readFile(String workspaceName, String filename) {
|
||||||
|
Path filePath = workspacePath(workspaceName).resolve(filename);
|
||||||
|
if (Files.exists(filePath)) {
|
||||||
|
return new FileInfo(filePath);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path workspacePath(String workspaceName) {
|
||||||
|
return root.resolve(workspaceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static class FileInfo {
|
||||||
|
private final Path path;
|
||||||
|
|
||||||
|
public FileInfo(Path path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaType getMediaType() {
|
||||||
|
try {
|
||||||
|
String contentType = Files.probeContentType(path);
|
||||||
|
MediaType mediaType = MediaType.valueOf(contentType);
|
||||||
|
return mediaType;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getContent() {
|
||||||
|
byte[] bytes = new byte[0];
|
||||||
|
try {
|
||||||
|
bytes = Files.readAllBytes(path);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return ByteBuffer.wrap(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Classes in this package are meant to provide a basic
|
||||||
|
* internal service facade to be used by endpoints.
|
||||||
|
* This simplifies endpoint implementations and facilitates DRY
|
||||||
|
* implementations.
|
||||||
|
*
|
||||||
|
* These implementations should only expose primitive types,
|
||||||
|
* collections of primitive types, or views of transfer types
|
||||||
|
* as implemented in that package.
|
||||||
|
*/
|
||||||
|
package io.nosqlbench.engine.rest.services;
|
@ -1,10 +1,16 @@
|
|||||||
package io.nosqlbench.engine.rest.transfertypes;
|
package io.nosqlbench.engine.rest.transfertypes;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public class WorkspaceView {
|
public class WorkspaceView {
|
||||||
|
|
||||||
private final String workspace;
|
private final Path workspaceRoot;
|
||||||
|
|
||||||
public WorkspaceView(String workspace) {
|
public WorkspaceView(Path workspaceRoot) {
|
||||||
this.workspace = workspace;
|
this.workspaceRoot = workspaceRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return workspaceRoot.getFileName().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ import java.nio.file.Path;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class WorkspacesInfo {
|
public class WorkspacesView {
|
||||||
|
|
||||||
private Path workspacesRoot;
|
private Path workspacesRoot;
|
||||||
public WorkspacesInfo(Path workspacesRoot) {
|
public WorkspacesView(Path workspacesRoot) {
|
||||||
this.workspacesRoot = workspacesRoot;
|
this.workspacesRoot = workspacesRoot;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Types in this package are meant to provide a mapping
|
||||||
|
* between internal state and external views. Specifically,
|
||||||
|
* these types should only include details which are meant to
|
||||||
|
* be shared by endpoints. This can be achieved by wrapping
|
||||||
|
* internal state and exposing only the visible properties, or
|
||||||
|
* it can be done by implementing types which are built from
|
||||||
|
* common internal types.
|
||||||
|
*
|
||||||
|
* Service objects in the services package should only provide
|
||||||
|
* primitive values or the view types from this package.
|
||||||
|
*/
|
||||||
|
package io.nosqlbench.engine.rest.transfertypes;
|
@ -27,3 +27,6 @@ echo "Do mvn release:prepare..."
|
|||||||
#mvn $MAVEN_REPO_LOCAL --batch-mode --global-settings release.xml -Dusername=$GITHUB_ACCESS_TOKEN release:prepare
|
#mvn $MAVEN_REPO_LOCAL --batch-mode --global-settings release.xml -Dusername=$GITHUB_ACCESS_TOKEN release:prepare
|
||||||
mvn --batch-mode --global-settings release.xml -Dusername=$GITHUB_ACCESS_TOKEN clean release:prepare -DdevelopmentVersion=${NEXT_SNAPSHOT} -DreleaseVersion=${RELEASE_VERSION}
|
mvn --batch-mode --global-settings release.xml -Dusername=$GITHUB_ACCESS_TOKEN clean release:prepare -DdevelopmentVersion=${NEXT_SNAPSHOT} -DreleaseVersion=${RELEASE_VERSION}
|
||||||
|
|
||||||
|
echo "files after release:prepare..."
|
||||||
|
pwd
|
||||||
|
ls -l
|
||||||
|
Loading…
Reference in New Issue
Block a user