From 57ad0d7ebddb117fb64b4d2753f286e4367adb26 Mon Sep 17 00:00:00 2001 From: Kristijan Mitrovic Date: Tue, 4 Aug 2020 13:03:59 +0000 Subject: [PATCH] Add support for ttl management in log flag API calls (#37) Merge branch 'master' into kris/log_flag_ui # Conflicts: # utils/cobbzilla-wizard Add labels needed for log flag UI Add expire time in log flag status response Speed up reading of log flag Set log flag's TTL witin API call Update lib Co-authored-by: Kristijan Mitrovic Reviewed-on: https://git.bubblev.org/bubblev/bubble/pulls/37 --- .../bubble/resources/cloud/LogsResource.java | 23 ++++++++++++++---- .../bubble/service/boot/SelfNodeService.java | 14 +++++++++-- .../service/boot/StandardSelfNodeService.java | 24 ++++++++++++------- .../DbFilterSelfNodeService.java | 12 ++++++++-- .../post_auth/ResourceMessages.properties | 10 ++++++++ 5 files changed, 65 insertions(+), 18 deletions(-) diff --git a/bubble-server/src/main/java/bubble/resources/cloud/LogsResource.java b/bubble-server/src/main/java/bubble/resources/cloud/LogsResource.java index 2ea1623f..68cd80ce 100644 --- a/bubble-server/src/main/java/bubble/resources/cloud/LogsResource.java +++ b/bubble-server/src/main/java/bubble/resources/cloud/LogsResource.java @@ -10,9 +10,13 @@ import lombok.NonNull; import org.glassfish.jersey.server.ContainerRequest; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Nullable; import javax.ws.rs.*; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; +import java.util.HashMap; +import java.util.Optional; +import java.util.concurrent.TimeUnit; import static bubble.ApiConstants.*; import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON; @@ -33,17 +37,26 @@ public class LogsResource { @GET @Path(EP_STATUS) @NonNull public Response getLoggingStatus(@NonNull @Context final ContainerRequest ctx) { - return ok(selfNodeService.getLogFlag()); + final var flag = new HashMap(2); + flag.put("flag", selfNodeService.getLogFlag()); + flag.put("expireAt", selfNodeService.getLogFlagExpirationTime().orElse(null)); + return ok(flag); } @POST @Path(EP_START) - @NonNull public Response startLogging(@NonNull @Context final ContainerRequest ctx) { return setLogFlag(true); } + @NonNull public Response startLogging(@NonNull @Context final ContainerRequest ctx, + @Nullable @QueryParam("ttlDays") final Byte ttlDays) { + return setLogFlag(true, Optional.ofNullable(ttlDays)); + } + @POST @Path(EP_STOP) - @NonNull public Response stopLogging(@NonNull @Context final ContainerRequest ctx) { return setLogFlag(false); } + @NonNull public Response stopLogging(@NonNull @Context final ContainerRequest ctx) { + return setLogFlag(false, Optional.empty()); + } - @NonNull private Response setLogFlag(final boolean b) { + @NonNull private Response setLogFlag(final boolean b, @NonNull final Optional ttlInDays) { if (!account.admin()) throw forbiddenEx(); // caller must be admin - selfNodeService.setLogFlag(b); + selfNodeService.setLogFlag(b, ttlInDays.map(days -> (int) TimeUnit.DAYS.toSeconds(days))); return ok(); } } diff --git a/bubble-server/src/main/java/bubble/service/boot/SelfNodeService.java b/bubble-server/src/main/java/bubble/service/boot/SelfNodeService.java index afa89650..2d490a06 100644 --- a/bubble-server/src/main/java/bubble/service/boot/SelfNodeService.java +++ b/bubble-server/src/main/java/bubble/service/boot/SelfNodeService.java @@ -7,6 +7,9 @@ package bubble.service.boot; import bubble.model.bill.BubblePlan; import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.BubbleNode; +import lombok.NonNull; + +import java.util.Optional; public interface SelfNodeService { @@ -24,6 +27,13 @@ public interface SelfNodeService { BubblePlan getThisPlan(); - Boolean getLogFlag(); - void setLogFlag(final boolean logFlag); + boolean getLogFlag(); + + /** + * @return Empty if TTL for log flag is a special one (less than 0), else timestamp (milliseconds) when log flag + * will be expired (to be precise, a very close time after the real expiration time as some time is spent + * for processing here). + */ + @NonNull Optional getLogFlagExpirationTime(); + void setLogFlag(final boolean logFlag, @NonNull final Optional ttlInSeconds); } diff --git a/bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java b/bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java index 68c1a692..3e48b889 100644 --- a/bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java +++ b/bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java @@ -41,6 +41,7 @@ import org.springframework.stereotype.Service; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -52,8 +53,7 @@ import static bubble.server.BubbleServer.isRestoreMode; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.function.Predicate.not; -import static org.cobbzilla.util.daemon.ZillaRuntime.background; -import static org.cobbzilla.util.daemon.ZillaRuntime.die; +import static org.cobbzilla.util.daemon.ZillaRuntime.*; import static org.cobbzilla.util.io.FileUtil.abs; import static org.cobbzilla.util.io.FileUtil.toFileOrDie; import static org.cobbzilla.util.json.JsonUtil.*; @@ -72,8 +72,8 @@ public class StandardSelfNodeService implements SelfNodeService { public static final long MIN_SAGE_KEY_TTL = MINUTES.toMillis(5); private static final String REDIS_LOG_FLAG_KEY = "bubble_server_logs_enabled"; - private static final long TTL_LOG_FLAG_NODE = DAYS.toSeconds(7); - private static final long TTL_LOG_FLAG_SAGE = DAYS.toSeconds(30); + private static final int TTL_LOG_FLAG_NODE = (int) DAYS.toSeconds(7); + private static final int TTL_LOG_FLAG_SAGE = (int) DAYS.toSeconds(30); @Autowired private BubbleNodeDAO nodeDAO; @Autowired private BubbleNodeKeyDAO nodeKeyDAO; @@ -442,16 +442,22 @@ public class StandardSelfNodeService implements SelfNodeService { } @Override - public Boolean getLogFlag() { - if (!getNodeConfig().exists(REDIS_LOG_FLAG_KEY)) return false; - return Boolean.valueOf(getNodeConfig().get_plaintext(REDIS_LOG_FLAG_KEY)); + public boolean getLogFlag() { + var flagStr = getNodeConfig().get_plaintext(REDIS_LOG_FLAG_KEY); + return empty(flagStr) ? false : Boolean.valueOf(flagStr); } @Override - public void setLogFlag(final boolean logFlag) { + @NonNull public Optional getLogFlagExpirationTime() { + var ttl = getNodeConfig().get_ttl(REDIS_LOG_FLAG_KEY); + return ttl < 0 ? Optional.empty() : Optional.of(now() + ttl * 1000); + } + + @Override + public void setLogFlag(final boolean logFlag, @NonNull final Optional ttlInSeconds) { if (logFlag) { getNodeConfig().set_plaintext(REDIS_LOG_FLAG_KEY, "true", EX, - isSelfSage() ? TTL_LOG_FLAG_SAGE : TTL_LOG_FLAG_NODE); + ttlInSeconds.orElse(isSelfSage() ? TTL_LOG_FLAG_SAGE : TTL_LOG_FLAG_NODE)); } else { // just (try to) remove the flag getNodeConfig().del(REDIS_LOG_FLAG_KEY); diff --git a/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterSelfNodeService.java b/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterSelfNodeService.java index 22b5b25f..7bc406cb 100644 --- a/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterSelfNodeService.java +++ b/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterSelfNodeService.java @@ -8,8 +8,11 @@ import bubble.model.bill.BubblePlan; import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.BubbleNode; import bubble.service.boot.SelfNodeService; +import lombok.NonNull; import org.springframework.stereotype.Service; +import java.util.Optional; + import static org.cobbzilla.util.daemon.ZillaRuntime.notSupported; @Service @@ -29,7 +32,12 @@ public class DbFilterSelfNodeService implements SelfNodeService { @Override public BubblePlan getThisPlan() { return notSupported("getThisPlan"); } - @Override public Boolean getLogFlag() { return notSupported("getLogFlag"); } - @Override public void setLogFlag(boolean logFlag) { notSupported("setLogFlag"); } + @Override public boolean getLogFlag() { return notSupported("getLogFlag"); } + @Override @NonNull public Optional getLogFlagExpirationTime() { + return notSupported("getLogFlagExpirationTime"); + } + @Override public void setLogFlag(boolean logFlag, @NonNull final Optional ttlInSeconds) { + notSupported("setLogFlag"); + } } diff --git a/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties b/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties index 088f5ba3..918bbea0 100644 --- a/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties +++ b/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties @@ -250,6 +250,16 @@ button_label_restore=Restore button_description_restore=You will need full network restore key build from this bubble while if was running. restore_not_possible_nodes_exist_html=Cannot restore bubbles with existing nodes. Please contact support@getbubblenow.com +# Network Page - Log flag +node_logs_enabled=logs enabled +node_logs_until=until +button_node_logs_disable=Disable Logs +node_logs_disable_after=Disable Logging After +node_logs_days=Days +button_node_logs_set_disable_after=Set +node_logs_disabled=logs are disabled +button_node_logs_enable=Enable Logs + # Network Page - Danger Zone title_network_danger_zone=Danger Zone link_network_action_stop=Stop