Merge branch 'stable-3.12' into stable-3.13
* stable-3.12:
Reduce HTTP check internal to 1s in Docker tests
Use healthcheck plugin for Docker tests
Change-Id: I83572cf9efff6c0e08c2c1b6962f68354743e41a
diff --git a/BUILD b/BUILD
index 3735cb3..4beff6e 100644
--- a/BUILD
+++ b/BUILD
@@ -21,7 +21,6 @@
resources = glob(["src/main/resources/**/*"]),
deps = [
":global-refdb-neverlink",
- "@auto-value//jar",
"@failsafe//jar",
"@jgroups-kubernetes//jar",
"@jgroups//jar",
diff --git a/README.md b/README.md
index fcf0566..11a33b2 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# Gerrit high-availability plugin
-This plugin allows deploying a cluster of multiple Gerrit primaries
-on the same data-center sharing the same Git repositories.
+This plugin allows deploying a cluster of multiple Gerrit primary servers
+in the same data-center sharing the same Git repositories.
Requirements for the Gerrit primaries are:
@@ -17,6 +17,18 @@
Refer to the [build instructions in the plugin documentation](src/main/resources/Documentation/build.md).
+## Installation
+
+Install
+
+- the `high-availability` plugin in the Gerrit site's `plugins` folder.
+
+> **NOTE** the `global-refdb` lib module in the Gerrit site's `lib` folder, even if it is not used or referenced as libModule in the `gerrit.config`, because of a bug in the high-availability plugin initialisation sequence.
+
+In active-active deployments with multiple Gerrit primaries, installation of a global-refdb
+implementation is needed to maintain consistent ref updates across all
+Gerrit primary sites.
+
## Sample configuration for two Gerrit primaries in high-availability
Assuming that the Gerrit primaries in the clusters are `gerrit-01.mycompany.com` and
@@ -76,7 +88,11 @@
It is the simplest and safest configuration, where only one Gerrit primary at a
time serves the incoming requests.
+<<<<<<< HEAD
+In case of failure of the active primary, the traffic is forwarded to the backup.
+=======
In case of failure of the primary, the traffic is forwarded to the backup.
+>>>>>>> stable-3.12
Assuming a load-balancing implemented using [HAProxy](http://www.haproxy.org/)
associated with the domain name `gerrit.mycompany.com`, exposing Gerrit cluster nodes
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
index 9229d01..c770092 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
@@ -26,9 +26,6 @@
import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbRefUpdate;
import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbRepository;
import com.gerritforge.gerrit.globalrefdb.validation.SharedRefLogger;
-import com.gerritforge.gerrit.globalrefdb.validation.dfsrefdb.CustomSharedRefEnforcementByProject;
-import com.gerritforge.gerrit.globalrefdb.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.gerritforge.gerrit.globalrefdb.validation.dfsrefdb.SharedRefEnforcement;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.ExceptionHook;
@@ -60,14 +57,6 @@
bind(GitRepositoryManager.class).to(SharedRefDbGitRepositoryManager.class);
- if (configuration.sharedRefDb().getSharedRefDb().getEnforcementRules().isEmpty()) {
- bind(SharedRefEnforcement.class).to(DefaultSharedRefEnforcement.class).in(Scopes.SINGLETON);
- } else {
- bind(SharedRefEnforcement.class)
- .to(CustomSharedRefEnforcementByProject.class)
- .in(Scopes.SINGLETON);
- }
-
DynamicSet.bind(binder(), ExceptionHook.class).to(SharedRefDbExceptionHook.class);
}
}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcher.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcher.java
index baf512f..ac6ea4c 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcher.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcher.java
@@ -26,7 +26,7 @@
@Singleton
class CachePatternMatcher {
private static final List<String> DEFAULT_PATTERNS =
- ImmutableList.of("^groups.*", "ldap_usernames", "projects", "sshkeys");
+ ImmutableList.of("^groups.*", "ldap_usernames", "projects", "sshkeys", "tokens");
private final Pattern pattern;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/Constants.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/Constants.java
index b456998..d4fab98 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/Constants.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/Constants.java
@@ -22,6 +22,7 @@
public static final String GROUPS_BYINCLUDE = "groups_byinclude";
public static final String GROUPS_MEMBERS = "groups_members";
public static final String PROJECTS = "projects";
+ public static final String TOKENS = "tokens";
private Constants() {}
}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheKeyJsonParser.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheKeyJsonParser.java
index ba28650..b8f5e9c 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheKeyJsonParser.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheKeyJsonParser.java
@@ -44,6 +44,7 @@
// Need to add a case for 'adv_bases'
switch (cacheName) {
case Constants.ACCOUNTS:
+ case Constants.TOKENS:
return id.get() == null ? null : Account.id(id.get().getAsInt());
case Constants.GROUPS:
return id.get() == null ? null : AccountGroup.id(id.get().getAsInt());
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java
index 63f65d6..6079804 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java
@@ -14,10 +14,10 @@
package com.ericsson.gerrit.plugins.highavailability.peers.jgroups;
-import autovalue.shaded.com.google.common.collect.ImmutableMap;
import com.ericsson.gerrit.plugins.highavailability.Configuration;
import com.ericsson.gerrit.plugins.highavailability.peers.PeerInfo;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.events.LifecycleListener;
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index 6fcd2e2..f62c035 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -27,15 +27,18 @@
sharing or synchronizing them.
#### Caches
+
Every time a cache eviction occurs in one of the instances, the eviction will be
forwarded the other nodes so their caches do not contain stale entries.
#### Secondary indexes
+
Every time the secondary index is modified in one of the instances, e.g., a change
is added, updated or removed from the index, the others instances index are updated
accordingly. This way, both indexes are kept synchronized.
#### Stream events
+
Every time a stream event occurs in one of the instances
(see [more events info](https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.html#events)),
the event is forwarded to the other instances which re-plays it. This way, the output
@@ -43,6 +46,7 @@
connected to.
#### Web session
+
The built-in Gerrit H2 based web session cache is replaced with a file based
implementation that is shared amongst the instances.
@@ -55,8 +59,8 @@
For the instances:
-* Configure gerrit.basePath in gerrit.config to the shared repositories location
-* Configure gerrit.serverId in gerrit.config based on [config](config.md)'s introduction
+* Configure `gerrit.basePath` in `gerrit.config` to the shared repositories location
+* Configure `gerrit.serverId` in `gerrit.config` based on [config](config.md)'s introduction
* Install and configure this @PLUGIN@ plugin [further](config.md) or based on below.
Here is an example of the minimal @PLUGIN@.config:
@@ -110,25 +114,34 @@
* Git repositories must be located on a shared file system
* A directory on a shared file system must be available for @PLUGIN@ to use
-* An implementation of global-refdb (e.g. Zookeeper) must be accessible from all the active
-instances
+* An implementation of `global-refdb` (e.g. Zookeeper) must be accessible from all the active
+ instances to maintain consistent ref updates across all Gerrit primary sites
+
+The following `global-refdb` implementations are available:
+
+* [zookeeper-refdb plugin](https://gerrit.googlesource.com/plugins/zookeeper-refdb/+/refs/heads/master)
+ using Apache Zookeeper
+* [aws-dynamodb-refdb plugin](https://gerrit.googlesource.com/plugins/aws-dynamodb-refdb/+/refs/heads/master)
+ using AWS DynamoDB
+* [spanner-refdb plugin](https://gerrit.googlesource.com/plugins/spanner-refdb/+/refs/heads/master)
+ using Google Cloud Spanner
For the instances:
-* Configure gerrit.basePath in gerrit.config to the shared repositories location
-* Configure gerrit.serverId in gerrit.config based on [config](config.md)'s introduction
+* Configure `gerrit.basePath` in `gerrit.config` to the shared repositories location
+* Configure `gerrit.serverId` in `gerrit.config` based on [config](config.md)'s introduction
* Install and configure this @PLUGIN@ plugin [further](config.md) or based on example
configuration
-* Install @PLUGIN@ plugin as a database module in $GERRIT_SITE/lib(please note that
-@PLUGIN plugin must be installed as a plugin and as a database module) and add
-`installDbModule = com.ericsson.gerrit.plugins.highavailability.ValidationModule`
-to the gerrit section in gerrit.config
-* Install [global-refdb library](https://mvnrepository.com/artifact/com.gerritforge/global-refdb) as a library module in $GERRIT_SITE/lib and add
-`installModule = com.gerritforge.gerrit.globalrefdb.validation.LibModule` to the gerrit
-section in gerrit.config
+* Install @PLUGIN@ plugin as a database module in `$GERRIT_SITE/lib` (please note that
+@PLUGIN plugin must be installed as a plugin and as a database module) and add <br/>
+`installDbModule = com.ericsson.gerrit.plugins.highavailability.ValidationModule` <br/>
+to the gerrit section in `gerrit.config`
+* Install [global-refdb library](https://mvnrepository.com/artifact/com.gerritforge/global-refdb) as a library module in $GERRIT_SITE/lib and add <br/>
+`installModule = com.gerritforge.gerrit.globalrefdb.validation.LibModule` <br/>
+to the `gerrit` section in `gerrit.config`
* Install and configure [zookeeper-refdb plugin](https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-zookeeper-refdb-bazel-master) based on [config.md](https://gerrit.googlesource.com/plugins/zookeeper-refdb/+/refs/heads/master/src/main/resources/Documentation/config.md)
-* Configure ref-database.enabled = true in @PLUGIN@.config to enable validation with
-global-refdb.
+* Configure `ref-database.enabled = true` in @PLUGIN@.config to enable validation with
+`global-refdb`.
Here is an example of the minimal @PLUGIN@.config:
@@ -166,12 +179,13 @@
enabled = true
```
-Minimal zookeeper-refdb.config for both active instances:
+Minimal `zookeeper-refdb.config` for both active instances:
```
[ref-database "zookeeper"]
connectString = zookeeperhost:2181
```
+
### Last index update timestamp storage
The plugin keeps track of the timestamp when it lastly updated an index.
@@ -180,6 +194,7 @@
sync with the primary, for example, after a node being offline for a long time.
The HA plugin keeps the last update timestamp for each index in the following files:
+
* `<gerrit_home>/data/high-availability/account`
* `<gerrit_home>/data/high-availability/change`
diff --git a/src/test/README.md b/src/test/README.md
index 80fe2e4..b0aa3c4 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -1,8 +1,8 @@
# Gerrit high-availability docker setup example
The Docker Compose project in the docker directory contains a simple test
-environment of two Gerrit primaries in HA configuration, with their git repos
-hosted on NFS filesystem.
+environment of two Gerrit primary servers in HA configuration, with their
+git repos hosted on NFS filesystem.
## How to build
diff --git a/src/test/docker/gerrit/Dockerfile b/src/test/docker/gerrit/Dockerfile
index ebb4b84..d18e060 100644
--- a/src/test/docker/gerrit/Dockerfile
+++ b/src/test/docker/gerrit/Dockerfile
@@ -11,7 +11,7 @@
nfs-utils \
&& yum -y clean all
-ENV GERRIT_BRANCH stable-3.12
+ENV GERRIT_BRANCH stable-3.13
# Add gerrit user
RUN adduser -p -m --uid 1000 gerrit --home-dir /home/gerrit
@@ -42,7 +42,7 @@
/var/gerrit/lib/global-refdb.jar
ADD --chown=gerrit:gerrit \
- "https://gerrit-ci.gerritforge.com/job/plugin-zookeeper-refdb-bazel-$GERRIT_BRANCH/lastSuccessfulBuild/artifact/bazel-bin/plugins/zookeeper-refdb/zookeeper-refdb.jar" \
+ "https://gerrit-ci.gerritforge.com/job/plugin-zookeeper-refdb-gh-bazel-$GERRIT_BRANCH/lastSuccessfulBuild/artifact/bazel-bin/plugins/zookeeper-refdb/zookeeper-refdb.jar" \
/var/gerrit/plugins/zookeeper-refdb.jar
ADD --chown=gerrit:gerrit \
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
index b51e1a0..0fb7dad 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
@@ -217,9 +217,6 @@
globalPluginConfig.setInt(HTTP_SECTION, null, CONNECTION_TIMEOUT_KEY, TIMEOUT);
assertThat(getConfiguration().http().connectionTimeout().toMillis()).isEqualTo(TIMEOUT);
-
- globalPluginConfig.setString(HTTP_SECTION, null, CONNECTION_TIMEOUT_KEY, INVALID_INT);
- assertThat(getConfiguration().http().connectionTimeout()).isEqualTo(DEFAULT_TIMEOUT);
}
@Test
@@ -228,9 +225,6 @@
globalPluginConfig.setInt(HTTP_SECTION, null, SOCKET_TIMEOUT_KEY, TIMEOUT);
assertThat(getConfiguration().http().socketTimeout().toMillis()).isEqualTo(TIMEOUT);
-
- globalPluginConfig.setString(HTTP_SECTION, null, SOCKET_TIMEOUT_KEY, INVALID_INT);
- assertThat(getConfiguration().http().socketTimeout()).isEqualTo(DEFAULT_TIMEOUT);
}
@Test
@@ -256,9 +250,6 @@
globalPluginConfig.setInt(HTTP_SECTION, null, RETRY_INTERVAL_KEY, RETRY_INTERVAL);
assertThat(getConfiguration().http().retryInterval().toMillis()).isEqualTo(RETRY_INTERVAL);
-
- globalPluginConfig.setString(HTTP_SECTION, null, RETRY_INTERVAL_KEY, INVALID_INT);
- assertThat(getConfiguration().http().retryInterval()).isEqualTo(DEFAULT_RETRY_INTERVAL);
}
@Test
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcherTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcherTest.java
index caf50b9..088b42e 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcherTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CachePatternMatcherTest.java
@@ -47,6 +47,7 @@
"ldap_usernames",
"projects",
"sshkeys",
+ "tokens",
"my_cache_a",
"my_cache_b",
"other")) {
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheRestApiServletTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheRestApiServletTest.java
index e4ffd59..58c0aef 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheRestApiServletTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/CacheRestApiServletTest.java
@@ -87,6 +87,12 @@
}
@Test
+ public void evictTokensCache() throws Exception {
+ configureMocksFor(Constants.TOKENS);
+ verifyResponseIsOK();
+ }
+
+ @Test
public void evictDefault() throws Exception {
configureMocksFor(Constants.PROJECTS);
verifyResponseIsOK();
@@ -134,6 +140,8 @@
} else if (Constants.GROUPS_BYINCLUDE.equals(cacheName)
|| Constants.GROUPS_MEMBERS.equals(cacheName)) {
when(readerMock.readLine()).thenReturn("{\"uuid\":\"abcd1234\"}");
+ } else if (Constants.TOKENS.equals(cacheName)) {
+ when(readerMock.readLine()).thenReturn("{\"id\":\"1234\"}");
} else {
when(readerMock.readLine()).thenReturn("{}");
}