Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement a method to delete a directory from a template. #1199

Open
wants to merge 3 commits into
base: nightly
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,17 @@ default boolean deployDirectory(@NonNull ServiceTemplate target, @NonNull Path d
*/
boolean deleteFile(@NonNull ServiceTemplate template, @NonNull String path);

/**
* Deletes the given directory at the given path in the given template in this storage.
* This method recursively deletes all files and directories inside the given directory.
*
* @param template the template in which the directory to delete is located in.
* @param path the path to the directory in the template to delete.
* @return true if the directory at the given path was deleted successfully, false otherwise.
* @throws NullPointerException if the given template or path is null.
*/
boolean deleteDirectory(@NonNull ServiceTemplate template, @NonNull String path);

/**
* Opens a new input stream to read the content of the file at the given path in the given template in this storage.
* This method returns null if either the file doesn't exist or is a directory.
Expand Down Expand Up @@ -480,6 +491,19 @@ default boolean deployDirectory(@NonNull ServiceTemplate target, @NonNull Path d
return Task.supply(() -> this.deleteFile(template, path));
}

/**
* Deletes the given directory at the given path in the given template in this storage. This method recursively
* deletes all files and directories inside the given directory.
*
* @param template the template in which the directory to delete is located in.
* @param path the path to the directory in the template to delete.
* @return a task completed with true if the directory at the given path was deleted successfully, false otherwise.
* @throws NullPointerException if the given template or path is null.
*/
default @NonNull Task<Boolean> deleteDirectoryAsync(@NonNull ServiceTemplate template, @NonNull String path) {
return Task.supply(() -> this.deleteDirectory(template, path));
}

/**
* Opens a new input stream to read the content of the file at the given path in the given template in this storage.
* This method returns null if either the file doesn't exist or is a directory.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,25 @@ private void handleFileDeleteRequest(
});
}

@BearerAuth
@HttpRequestHandler(paths = "/api/v2/template/{storage}/{prefix}/{name}/directory", methods = "DELETE")
private void handleDirectoryDeleteRequest(
@NonNull HttpContext context,
@NonNull @RequestPathParam("storage") String storageName,
@NonNull @RequestPathParam("prefix") String prefix,
@NonNull @RequestPathParam("name") String templateName,
@NonNull @FirstRequestQueryParam("path") String path
) {
this.handleWithTemplateContext(context, storageName, prefix, templateName, (template, storage) -> {
var status = storage.deleteDirectory(template, path);
this.ok(context)
.body(status ? this.success().toString() : this.failure().toString())
.context()
.closeAfter(true)
.cancelNext(true);
});
}

@BearerAuth
@HttpRequestHandler(paths = "/api/v2/template/{storage}/{prefix}/{name}", methods = "DELETE")
private void handleTemplateDeleteRequest(
Expand Down
49 changes: 49 additions & 0 deletions modules/rest/src/main/resources/documentation/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -3235,6 +3235,55 @@
}
}
},
"/template/{storage}/{prefix}/{name}/directory" : {
"delete" : {
"parameters" : [ {
"name" : "storage",
"in" : "path",
"required" : true,
"schema" : {
"type" : "string"
}
}, {
"name" : "prefix",
"in" : "path",
"required" : true,
"schema" : {
"type" : "string"
}
}, {
"name" : "name",
"in" : "path",
"required" : true,
"schema" : {
"type" : "string"
}
}, {
"name" : "path",
"in" : "query",
"required" : true,
"schema" : {
"type" : "string"
}
} ],
"tags" : [ "Templates" ],
"summary" : "Deletes a directory and all its contents recursively from a template",
"responses" : {
"200" : {
"$ref" : "#/components/responses/Success"
},
"400" : {
"$ref" : "#/components/responses/BadRequest"
},
"401" : {
"$ref" : "#/components/responses/Unauthorized"
},
"403" : {
"$ref" : "#/components/responses/Forbidden"
}
}
}
},
"/serviceversion" : {
"get" : {
"tags" : [ "Service Versions" ],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,29 @@ public boolean deleteFile(@NonNull ServiceTemplate template, @NonNull String pat
}
}

@Override
public boolean deleteDirectory(@NonNull ServiceTemplate template, @NonNull String path) {
try {
// get the contents we want to delete
Set<ObjectIdentifier> toDelete = new HashSet<>();
this.listAllObjects(
this.getBucketPath(template, path),
null,
object -> toDelete.add(ObjectIdentifier.builder().key(object.key()).build()));

// build the delete request
var deleteRequest = DeleteObjectsRequest.builder()
.bucket(this.config().bucket())
.delete(Delete.builder().quiet(true).objects(toDelete).build())
.build();
this.client.deleteObjects(deleteRequest);
// success
return true;
} catch (Exception exception) {
return false;
}
}

@Override
public @Nullable InputStream newInputStream(@NonNull ServiceTemplate template, @NonNull String path) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,15 @@ void testTemplateDelete() {
Assertions.assertFalse(storage.contains(TEMPLATE));
Assertions.assertFalse(storage.hasFile(TEMPLATE, "test.txt"));
}

@Test
@Order(120)
void testDeleteDirectory() {
var directory = "hello";
Assertions.assertTrue(storage.createDirectory(TEMPLATE, directory));
Assertions.assertTrue(storage.createFile(TEMPLATE, directory + "/test.txt"));
Assertions.assertTrue(storage.hasFile(TEMPLATE, directory + "/test.txt"));
Assertions.assertTrue(storage.deleteDirectory(TEMPLATE, directory));
Assertions.assertFalse(storage.hasFile(TEMPLATE, directory + "/test.txt"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ public boolean deleteFile(@NonNull ServiceTemplate template, @NonNull String pat
}, false);
}

@Override
public boolean deleteDirectory(@NonNull ServiceTemplate template, @NonNull String path) {
return this.executeWithClient(client -> {
this.deleteDir(client, this.constructRemotePath(template, path));
return true;
}, false);
}

@Override
public @Nullable InputStream newInputStream(@NonNull ServiceTemplate st, @NonNull String path) throws IOException {
var client = this.pool.takeClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,15 @@ void testTemplateDelete() {
Assertions.assertFalse(storage.contains(TEMPLATE));
Assertions.assertFalse(storage.hasFile(TEMPLATE, "test.txt"));
}

@Test
@Order(120)
void testDeleteDirectory() {
var directory = "hello";
Assertions.assertTrue(storage.createDirectory(TEMPLATE, directory));
Assertions.assertTrue(storage.createFile(TEMPLATE, directory + "/test.txt"));
Assertions.assertTrue(storage.hasFile(TEMPLATE, directory + "/test.txt"));
Assertions.assertTrue(storage.deleteDirectory(TEMPLATE, directory));
Assertions.assertFalse(storage.hasFile(TEMPLATE, directory + "/test.txt"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,17 @@ public boolean deleteFile(@NonNull ServiceTemplate template, @NonNull String pat
return false;
}

@Override
public boolean deleteDirectory(@NonNull ServiceTemplate template, @NonNull String path) {
var dirPath = this.getTemplatePath(template).resolve(path);
if (Files.exists(dirPath) && Files.isDirectory(dirPath)) {
FileUtil.delete(dirPath);
return true;
}

return false;
}

@Override
public @Nullable InputStream newInputStream(
@NonNull ServiceTemplate template,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,15 @@ void testTemplateDelete() {
Assertions.assertFalse(storage.contains(TEMPLATE));
Assertions.assertFalse(storage.hasFile(TEMPLATE, "test.txt"));
}

@Test
@Order(120)
void testDeleteDirectory() {
var directory = "hello";
Assertions.assertTrue(storage.createDirectory(TEMPLATE, directory));
Assertions.assertTrue(storage.createFile(TEMPLATE, directory + "/test.txt"));
Assertions.assertTrue(storage.hasFile(TEMPLATE, directory + "/test.txt"));
Assertions.assertTrue(storage.deleteDirectory(TEMPLATE, directory));
Assertions.assertFalse(storage.hasFile(TEMPLATE, directory + "/test.txt"));
}
}
Loading