Procházet zdrojové kódy

Merge pull request #79 from overleaf/sk-add-health-check

Add `/api/status` and `/api/health_check` endpoints
Shane Kilkelly před 6 roky
rodič
revize
0830102cec

+ 15 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java

@@ -263,6 +263,21 @@ public class Bridge {
         gcJob.start();
         gcJob.start();
     }
     }
 
 
+    public boolean healthCheck() {
+       try {
+         dbStore.getNumProjects();
+         File rootDirectory = new File("/");
+         if (!rootDirectory.exists()) {
+           throw new Exception("bad filesystem state, root directory does not exist");
+         }
+         Log.info("[HealthCheck] passed");
+         return true;
+       } catch (Exception e)  {
+         Log.error("[HealthCheck] FAILED!", e);
+         return false;
+       }
+    }
+
     /**
     /**
      * Performs a check of inconsistencies in the DB. This was used to upgrade
      * Performs a check of inconsistencies in the DB. This was used to upgrade
      * the schema.
      * the schema.

+ 11 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java

@@ -119,10 +119,21 @@ public class GitBridgeServer {
     ) throws ServletException {
     ) throws ServletException {
         HandlerCollection handlers = new HandlerList();
         HandlerCollection handlers = new HandlerList();
         handlers.addHandler(initApiHandler());
         handlers.addHandler(initApiHandler());
+        handlers.addHandler(initBaseHandler());
         handlers.addHandler(initGitHandler(config, repoStore, snapshotApi));
         handlers.addHandler(initGitHandler(config, repoStore, snapshotApi));
         jettyServer.setHandler(handlers);
         jettyServer.setHandler(handlers);
     }
     }
 
 
+    private Handler initBaseHandler() {
+        ContextHandler base = new ContextHandler();
+        base.setContextPath("/");
+        HandlerCollection handlers = new HandlerList();
+        handlers.addHandler(new StatusHandler(bridge));
+        handlers.addHandler(new HealthCheckHandler(bridge));
+        base.setHandler(handlers);
+        return base;
+    }
+
     private Handler initApiHandler() {
     private Handler initApiHandler() {
         ContextHandler api = new ContextHandler();
         ContextHandler api = new ContextHandler();
         api.setContextPath("/api");
         api.setContextPath("/api");

+ 45 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/HealthCheckHandler.java

@@ -0,0 +1,45 @@
+package uk.ac.ic.wlgitbridge.server;
+
+import org.eclipse.jetty.server.HttpConnection;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import uk.ac.ic.wlgitbridge.bridge.Bridge;
+import uk.ac.ic.wlgitbridge.util.Log;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class HealthCheckHandler extends AbstractHandler {
+
+  private final Bridge bridge;
+
+  public HealthCheckHandler(Bridge bridge) {
+    this.bridge = bridge;
+  }
+
+  @Override
+  public void handle(
+    String target,
+    Request baseRequest,
+    HttpServletRequest request,
+    HttpServletResponse response
+  ) throws IOException {
+    if ("GET".equals(baseRequest.getMethod()) && "/health_check".equals(target)) {
+      Log.info("GET <- /health_check");
+      baseRequest.setHandled(true);
+      response.setContentType("text/plain");
+      if (bridge.healthCheck()) {
+        response.setStatus(200);
+        response.getWriter().println("ok");
+      } else {
+        response.setStatus(500);
+        response.getWriter().println("failed");
+      }
+    }
+  }
+
+}

+ 40 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/StatusHandler.java

@@ -0,0 +1,40 @@
+package uk.ac.ic.wlgitbridge.server;
+
+import org.eclipse.jetty.server.HttpConnection;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import uk.ac.ic.wlgitbridge.bridge.Bridge;
+import uk.ac.ic.wlgitbridge.util.Log;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class StatusHandler extends AbstractHandler {
+
+  private final Bridge bridge;
+
+  public StatusHandler(Bridge bridge) {
+    this.bridge = bridge;
+  }
+
+  @Override
+  public void handle(
+    String target,
+    Request baseRequest,
+    HttpServletRequest request,
+    HttpServletResponse response
+  ) throws IOException {
+    if ("GET".equals(baseRequest.getMethod()) && "/status".equals(target)) {
+      Log.info("GET <- /status");
+      baseRequest.setHandled(true);
+      response.setContentType("text/plain");
+      response.setStatus(200);
+      response.getWriter().println("ok");
+    }
+  }
+
+}

+ 30 - 0
services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/WLGitBridgeIntegrationTest.java

@@ -3,6 +3,13 @@ package uk.ac.ic.wlgitbridge.application;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.IOUtils;
 import static org.asynchttpclient.Dsl.*;
 import static org.asynchttpclient.Dsl.*;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.HttpClients;
 import org.asynchttpclient.*;
 import org.asynchttpclient.*;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.junit.After;
 import org.junit.After;
@@ -891,6 +898,29 @@ public class WLGitBridgeIntegrationTest {
         wlgb.stop();
         wlgb.stop();
     }
     }
 
 
+    @Test
+    public void testStatusAndHealthCheckEndpoints() throws ClientProtocolException, IOException {
+        int gitBridgePort = 33887;
+        int mockServerPort = 3887;
+        server = new MockSnapshotServer(mockServerPort, getResource("/canCloneARepository").toFile());
+        server.start();
+        server.setState(states.get("canCloneARepository").get("state"));
+        wlgb = new GitBridgeApp(new String[] {
+          makeConfigFile(gitBridgePort, mockServerPort)
+        });
+        wlgb.run();
+        HttpClient client = HttpClients.createDefault();
+        String urlBase = "http://127.0.0.1:" + gitBridgePort;
+        // Status
+        HttpGet statusRequest = new HttpGet(urlBase+"/status");
+        HttpResponse statusResponse = client.execute(statusRequest);
+        assertEquals(200, statusResponse.getStatusLine().getStatusCode());
+        // Health Check
+        HttpGet healthCheckRequest = new HttpGet(urlBase+"/health_check");
+        HttpResponse healthCheckResponse = client.execute(healthCheckRequest);
+        assertEquals(200, healthCheckResponse.getStatusLine().getStatusCode());
+    }
+
     private String makeConfigFile(
     private String makeConfigFile(
             int port,
             int port,
             int apiPort
             int apiPort