Implement JGit health-check Check that JGit is able to open and read objects from All-Projects repository. Change-Id: Ibc7dc325b2f3529636b6ed8297bf3ca13269b444
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java index 9e6ebc5..55bf18b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java
@@ -17,12 +17,18 @@ import com.google.gerrit.extensions.registration.DynamicSet; import com.google.inject.AbstractModule; import com.googlesource.gerrit.plugins.healthcheck.check.HealthCheck; +import com.googlesource.gerrit.plugins.healthcheck.check.JGitHealthCheck; import com.googlesource.gerrit.plugins.healthcheck.check.ReviewDbHealthCheck; public class HealthCheckSubsystemsModule extends AbstractModule { @Override protected void configure() { - DynamicSet.bind(binder(), HealthCheck.class).to(ReviewDbHealthCheck.class); + bindChecker(ReviewDbHealthCheck.class); + bindChecker(JGitHealthCheck.class); + } + + private void bindChecker(Class<? extends HealthCheck> healthCheckClass) { + DynamicSet.bind(binder(), HealthCheck.class).to(healthCheckClass); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/AbstractHealthCheck.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/AbstractHealthCheck.java new file mode 100644 index 0000000..f186092 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/AbstractHealthCheck.java
@@ -0,0 +1,47 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.plugins.healthcheck.check; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractHealthCheck implements HealthCheck { + private static final Logger log = LoggerFactory.getLogger(AbstractHealthCheck.class); + private final String name; + + protected AbstractHealthCheck(String name) { + this.name = name; + } + + @Override + public String name() { + return name; + } + + @Override + public Status run() { + Result healthy; + long ts = System.currentTimeMillis(); + try { + healthy = doCheck(); + } catch (Exception e) { + log.warn("Check {} failed", name, e); + healthy = Result.FAILED; + } + return new Status(healthy, ts, System.currentTimeMillis() - ts); + } + + protected abstract Result doCheck() throws Exception; +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java index e33b755..1c88f0e 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java
@@ -17,4 +17,5 @@ public interface HealthCheckNames { String REVIEWDB = "reviewdb"; + String JGIT = "jgit"; }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/JGitHealthCheck.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/JGitHealthCheck.java new file mode 100644 index 0000000..be0a373 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/JGitHealthCheck.java
@@ -0,0 +1,44 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.plugins.healthcheck.check; + +import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.JGIT; + +import com.google.gerrit.server.config.AllProjectsName; +import com.google.gerrit.server.git.GitRepositoryManager; +import com.google.inject.Inject; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; + +public class JGitHealthCheck extends AbstractHealthCheck { + private final GitRepositoryManager repositoryManager; + private final AllProjectsName allProjectsName; + + @Inject + public JGitHealthCheck(GitRepositoryManager repositoryManager, AllProjectsName allProjectsName) { + super(JGIT); + this.repositoryManager = repositoryManager; + this.allProjectsName = allProjectsName; + } + + @Override + protected Result doCheck() throws Exception { + try (Repository allProjects = repositoryManager.openRepository(allProjectsName)) { + ObjectId headObj = allProjects.resolve("refs/meta/config"); + allProjects.open(headObj).getType(); + return Result.PASSED; + } + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/ReviewDbHealthCheck.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/ReviewDbHealthCheck.java index ff9b74b..10aad07 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/ReviewDbHealthCheck.java +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/ReviewDbHealthCheck.java
@@ -23,38 +23,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class ReviewDbHealthCheck implements HealthCheck { +public class ReviewDbHealthCheck extends AbstractHealthCheck { private static final Logger log = LoggerFactory.getLogger(ReviewDbHealthCheck.class); private final Provider<ReviewDb> reviewDb; @Inject public ReviewDbHealthCheck(Provider<ReviewDb> reviewDb) { + super(REVIEWDB); this.reviewDb = reviewDb; } @Override - public HealthCheck.Status run() { - HealthCheck.Result healthy; - long ts = System.currentTimeMillis(); - try { - healthy = doCheck(); - } catch (Exception e) { - log.warn("Check reviewdb has failed", e); - healthy = HealthCheck.Result.FAILED; - } - return new HealthCheck.Status(healthy, ts, System.currentTimeMillis() - ts); - } - - @Override - public String name() { - return REVIEWDB; - } - - private HealthCheck.Result doCheck() throws Exception { + protected Result doCheck() throws Exception { try (ReviewDb db = reviewDb.get()) { db.schemaVersion().get(new CurrentSchemaVersion.Key()); - return HealthCheck.Result.PASSED; + return Result.PASSED; } } }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java index 4471372..f5c6036 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java
@@ -16,17 +16,16 @@ import static com.google.common.net.HttpHeaders.CONTENT_TYPE; import static com.google.common.truth.Truth.assertThat; +import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.JGIT; import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.REVIEWDB; -import java.io.IOException; - -import org.junit.Test; - import com.google.gerrit.acceptance.LightweightPluginDaemonTest; import com.google.gerrit.acceptance.RestResponse; import com.google.gerrit.acceptance.TestPlugin; import com.google.gson.Gson; import com.google.gson.JsonObject; +import java.io.IOException; +import org.junit.Test; @TestPlugin(name = "healthcheck", sysModule = "com.googlesource.gerrit.plugins.healthcheck.Module") public class HealthCheckIT extends LightweightPluginDaemonTest { @@ -48,14 +47,28 @@ resp.assertOK(); JsonObject respPayload = gson.fromJson(resp.getReader(), JsonObject.class); - assertThat(respPayload.has(REVIEWDB)).isTrue(); - JsonObject reviewDbStatus = respPayload.get(REVIEWDB).getAsJsonObject(); - assertThat(reviewDbStatus.has("result")).isTrue(); - assertThat(reviewDbStatus.get("result").getAsString()).isEqualTo("passed"); + assertCheckResult(respPayload, REVIEWDB, "passed"); + } + + @Test + public void shouldReturnJGitCheck() throws Exception { + RestResponse resp = getHealthCheckStatus(); + resp.assertOK(); + + JsonObject respPayload = gson.fromJson(resp.getReader(), JsonObject.class); + + assertCheckResult(respPayload, JGIT, "passed"); } private RestResponse getHealthCheckStatus() throws IOException { return adminRestSession.get("/config/server/healthcheck~status"); } + + private void assertCheckResult(JsonObject respPayload, String checkName, String result) { + assertThat(respPayload.has(checkName)).isTrue(); + JsonObject reviewDbStatus = respPayload.get(checkName).getAsJsonObject(); + assertThat(reviewDbStatus.has("result")).isTrue(); + assertThat(reviewDbStatus.get("result").getAsString()).isEqualTo(result); + } }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java new file mode 100644 index 0000000..677d22a --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java
@@ -0,0 +1,107 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.plugins.healthcheck; + +import static com.google.common.truth.Truth.assertThat; +import static org.eclipse.jgit.lib.RefUpdate.Result.NEW; + +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.server.config.AllProjectsName; +import com.google.gerrit.server.git.GitRepositoryManager; +import com.google.gerrit.server.git.RepositoryCaseMismatchException; +import com.google.gerrit.testutil.InMemoryRepositoryManager; +import com.googlesource.gerrit.plugins.healthcheck.check.HealthCheck.Result; +import com.googlesource.gerrit.plugins.healthcheck.check.JGitHealthCheck; +import java.io.IOException; +import java.util.Collections; +import java.util.SortedSet; +import org.eclipse.jgit.errors.RepositoryNotFoundException; +import org.eclipse.jgit.lib.CommitBuilder; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.lib.Repository; +import org.junit.Before; +import org.junit.Test; + +public class JGitHealthCheckTest { + private AllProjectsName allProjectsName = new AllProjectsName("All-Projects"); + private InMemoryRepositoryManager inMemoryRepositoryManager = new InMemoryRepositoryManager(); + PersonIdent personIdent = new PersonIdent("Gerrit Rietveld", "gerrit@rietveld.nl"); + + @Before + public void setupAllProjects() throws Exception { + InMemoryRepositoryManager.Repo repo = + inMemoryRepositoryManager.createRepository(allProjectsName); + createCommit(repo, "refs/meta/config"); + } + + @Test + public void shouldBeHealthyWhenJGitIsWorking() { + JGitHealthCheck reviewDbCheck = + new JGitHealthCheck(getWorkingRepositoryManager(), allProjectsName); + assertThat(reviewDbCheck.run().result).isEqualTo(Result.PASSED); + } + + @Test + public void shouldBeUnhealthyWhenJGitIsFailing() { + JGitHealthCheck jGitHealthCheck = + new JGitHealthCheck(getFailingGitRepositoryManager(), allProjectsName); + assertThat(jGitHealthCheck.run().result).isEqualTo(Result.FAILED); + } + + private GitRepositoryManager getFailingGitRepositoryManager() { + return new GitRepositoryManager() { + + @Override + public Repository openRepository(Project.NameKey name) + throws RepositoryNotFoundException, IOException { + throw new RepositoryNotFoundException("Can't fine repository " + name); + } + + @Override + public Repository createRepository(Project.NameKey name) + throws RepositoryCaseMismatchException, RepositoryNotFoundException, IOException { + throw new IOException("Can't create repositories"); + } + + @Override + public SortedSet<Project.NameKey> list() { + return Collections.emptySortedSet(); + } + }; + } + + private GitRepositoryManager getWorkingRepositoryManager() { + return inMemoryRepositoryManager; + } + + private void createCommit(InMemoryRepositoryManager.Repo repo, String ref) throws IOException { + try (ObjectInserter oi = repo.newObjectInserter()) { + CommitBuilder cb = new CommitBuilder(); + cb.setTreeId(oi.insert(Constants.OBJ_TREE, new byte[] {})); + cb.setAuthor(personIdent); + cb.setCommitter(personIdent); + cb.setMessage("Test commit\n"); + ObjectId id = oi.insert(cb); + oi.flush(); + RefUpdate ru = repo.updateRef(ref); + ru.setNewObjectId(id); + assertThat(ru.update()).isEqualTo(NEW); + } + } +}