Merge branch 'stable-3.3' into stable-3.4 * stable-3.3: Extract FetchApiClient interface Add user/password authentication for CGit client Change-Id: Id84173f7f7bc0cad6a4ada86bfc684b14172bb7e
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java index ed584b7..44c6556 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/DeleteProjectTask.java
@@ -22,7 +22,7 @@ import com.google.gerrit.server.util.IdGenerator; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; -import com.googlesource.gerrit.plugins.replication.pull.client.FetchRestApiClient; +import com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient; import com.googlesource.gerrit.plugins.replication.pull.client.HttpResult; import java.io.IOException; import java.net.URISyntaxException; @@ -39,11 +39,11 @@ private final Source source; private final String uri; private final Project.NameKey project; - private final FetchRestApiClient.Factory fetchClientFactory; + private final FetchApiClient.Factory fetchClientFactory; @Inject DeleteProjectTask( - FetchRestApiClient.Factory fetchClientFactory, + FetchApiClient.Factory fetchClientFactory, IdGenerator ig, @Assisted Source source, @Assisted String uri,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java index 29ec93a..c17d5df 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
@@ -43,6 +43,7 @@ import com.googlesource.gerrit.plugins.replication.ReplicationFileBasedConfig; import com.googlesource.gerrit.plugins.replication.StartReplicationCapability; import com.googlesource.gerrit.plugins.replication.pull.api.PullReplicationApiModule; +import com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient; import com.googlesource.gerrit.plugins.replication.pull.client.FetchRestApiClient; import com.googlesource.gerrit.plugins.replication.pull.client.HttpClient; import com.googlesource.gerrit.plugins.replication.pull.client.SourceHttpClient; @@ -82,7 +83,10 @@ .build(SourceHttpClient.Factory.class)); install(new FactoryModuleBuilder().build(Source.Factory.class)); - install(new FactoryModuleBuilder().build(FetchRestApiClient.Factory.class)); + install( + new FactoryModuleBuilder() + .implement(FetchApiClient.class, FetchRestApiClient.class) + .build(FetchApiClient.Factory.class)); bind(FetchReplicationMetrics.class).in(Scopes.SINGLETON);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java index 7449263..cfe01e2 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
@@ -31,7 +31,7 @@ import com.googlesource.gerrit.plugins.replication.pull.FetchResultProcessing.GitUpdateProcessing; import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData; import com.googlesource.gerrit.plugins.replication.pull.api.exception.MissingParentObjectException; -import com.googlesource.gerrit.plugins.replication.pull.client.FetchRestApiClient; +import com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient; import com.googlesource.gerrit.plugins.replication.pull.client.HttpResult; import com.googlesource.gerrit.plugins.replication.pull.filter.ExcludedRefsFilter; import java.io.IOException; @@ -71,7 +71,7 @@ private volatile boolean running; private volatile boolean replaying; private final Queue<ReferenceUpdatedEvent> beforeStartupEventsQueue; - private FetchRestApiClient.Factory fetchClientFactory; + private FetchApiClient.Factory fetchClientFactory; private Integer fetchCallsTimeout; private ExcludedRefsFilter refsFilter; private RevisionReader revisionReader; @@ -82,7 +82,7 @@ Provider<SourcesCollection> rd, DynamicItem<EventDispatcher> dis, ReplicationStateListeners sl, - FetchRestApiClient.Factory fetchClientFactory, + FetchApiClient.Factory fetchClientFactory, ExcludedRefsFilter refsFilter, RevisionReader revReader) { workQueue = wq; @@ -273,7 +273,7 @@ for (String apiUrl : source.getApis()) { try { URIish uri = new URIish(apiUrl); - FetchRestApiClient fetchClient = fetchClientFactory.create(source); + FetchApiClient fetchClient = fetchClientFactory.create(source); HttpResult result = fetchClient.callSendObject(project, refName, isDelete, revision, uri); if (isProjectMissing(result, project) && source.isCreateMissingRepositories()) { @@ -309,7 +309,7 @@ for (String apiUrl : source.getApis()) { try { URIish uri = new URIish(apiUrl); - FetchRestApiClient fetchClient = fetchClientFactory.create(source); + FetchApiClient fetchClient = fetchClientFactory.create(source); HttpResult result = fetchClient.callFetch(project, refName, uri); if (isProjectMissing(result, project) && source.isCreateMissingRepositories()) { result = initProject(project, uri, fetchClient, result); @@ -344,7 +344,7 @@ } private HttpResult initProject( - Project.NameKey project, URIish uri, FetchRestApiClient fetchClient, HttpResult result) + Project.NameKey project, URIish uri, FetchApiClient fetchClient, HttpResult result) throws IOException, ClientProtocolException { HttpResult initProjectResult = fetchClient.initProject(project, uri); if (initProjectResult.isSuccessful()) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java index 943ea92..bded7d1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/UpdateHeadTask.java
@@ -22,14 +22,14 @@ import com.google.gerrit.server.util.IdGenerator; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; -import com.googlesource.gerrit.plugins.replication.pull.client.FetchRestApiClient; +import com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient; import com.googlesource.gerrit.plugins.replication.pull.client.HttpResult; import java.io.IOException; import org.eclipse.jgit.transport.URIish; public class UpdateHeadTask implements Runnable { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final FetchRestApiClient.Factory fetchClientFactory; + private final FetchApiClient.Factory fetchClientFactory; private final Source source; private final URIish apiURI; private final Project.NameKey project; @@ -42,7 +42,7 @@ @Inject UpdateHeadTask( - FetchRestApiClient.Factory fetchClientFactory, + FetchApiClient.Factory fetchClientFactory, IdGenerator ig, @Assisted Source source, @Assisted URIish apiURI,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchApiClient.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchApiClient.java new file mode 100644 index 0000000..476a35b --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchApiClient.java
@@ -0,0 +1,46 @@ +// Copyright (C) 2022 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.replication.pull.client; + +import com.google.gerrit.entities.Project; +import com.googlesource.gerrit.plugins.replication.pull.Source; +import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData; +import java.io.IOException; +import org.apache.http.client.ClientProtocolException; +import org.eclipse.jgit.transport.URIish; + +public interface FetchApiClient { + + public interface Factory { + FetchApiClient create(Source source); + } + + HttpResult callFetch(Project.NameKey project, String refName, URIish targetUri) + throws ClientProtocolException, IOException; + + HttpResult initProject(Project.NameKey project, URIish uri) throws IOException; + + HttpResult deleteProject(Project.NameKey project, URIish apiUri) throws IOException; + + HttpResult updateHead(Project.NameKey project, String newHead, URIish apiUri) throws IOException; + + HttpResult callSendObject( + Project.NameKey project, + String refName, + boolean isDelete, + RevisionData revisionData, + URIish targetUri) + throws ClientProtocolException, IOException; +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java index ab3d3c5..f2f57cd 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
@@ -56,17 +56,13 @@ import org.eclipse.jgit.transport.CredentialItem; import org.eclipse.jgit.transport.URIish; -public class FetchRestApiClient implements ResponseHandler<HttpResult> { +public class FetchRestApiClient implements FetchApiClient, ResponseHandler<HttpResult> { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); static String GERRIT_ADMIN_PROTOCOL_PREFIX = "gerrit+"; private static final Gson GSON = new GsonBuilder().setFieldNamingPolicy(LOWER_CASE_WITH_UNDERSCORES).create(); - public interface Factory { - FetchRestApiClient create(Source source); - } - private final CredentialsFactory credentials; private final SourceHttpClient.Factory httpClientFactory; private final Source source; @@ -95,6 +91,10 @@ Strings.emptyToNull(instanceLabel), "replication.instanceLabel cannot be null or empty"); } + /* (non-Javadoc) + * @see com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient#callFetch(com.google.gerrit.entities.Project.NameKey, java.lang.String, org.eclipse.jgit.transport.URIish) + */ + @Override public HttpResult callFetch(Project.NameKey project, String refName, URIish targetUri) throws ClientProtocolException, IOException { String url = @@ -113,6 +113,10 @@ return httpClientFactory.create(source).execute(post, this, getContext(targetUri)); } + /* (non-Javadoc) + * @see com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient#initProject(com.google.gerrit.entities.Project.NameKey, org.eclipse.jgit.transport.URIish) + */ + @Override public HttpResult initProject(Project.NameKey project, URIish uri) throws IOException { String url = String.format( @@ -123,6 +127,10 @@ return httpClientFactory.create(source).execute(put, this, getContext(uri)); } + /* (non-Javadoc) + * @see com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient#deleteProject(com.google.gerrit.entities.Project.NameKey, org.eclipse.jgit.transport.URIish) + */ + @Override public HttpResult deleteProject(Project.NameKey project, URIish apiUri) throws IOException { String url = String.format("%s/%s", apiUri.toASCIIString(), getProjectDeletionUrl(project.get())); @@ -130,6 +138,10 @@ return httpClientFactory.create(source).execute(delete, this, getContext(apiUri)); } + /* (non-Javadoc) + * @see com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient#updateHead(com.google.gerrit.entities.Project.NameKey, java.lang.String, org.eclipse.jgit.transport.URIish) + */ + @Override public HttpResult updateHead(Project.NameKey project, String newHead, URIish apiUri) throws IOException { logger.atFine().log("Updating head of %s on %s", project.get(), newHead); @@ -142,6 +154,10 @@ return httpClientFactory.create(source).execute(req, this, getContext(apiUri)); } + /* (non-Javadoc) + * @see com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient#callSendObject(com.google.gerrit.entities.Project.NameKey, java.lang.String, boolean, com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData, org.eclipse.jgit.transport.URIish) + */ + @Override public HttpResult callSendObject( Project.NameKey project, String refName,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java index 9f055c8..c404e30 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java
@@ -19,6 +19,7 @@ import com.google.common.collect.Lists; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; +import com.googlesource.gerrit.plugins.replication.CredentialsFactory; import com.googlesource.gerrit.plugins.replication.pull.SourceConfiguration; import java.io.BufferedReader; import java.io.File; @@ -30,6 +31,8 @@ import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.URIish; @@ -40,17 +43,20 @@ private int timeout; @Inject - public CGitFetch(SourceConfiguration config, @Assisted URIish uri, @Assisted Repository git) { - + public CGitFetch( + SourceConfiguration config, + CredentialsFactory cpFactory, + @Assisted URIish uri, + @Assisted Repository git) { this.localProjectDirectory = git.getDirectory(); - this.uri = uri; + this.uri = appendCredentials(uri, cpFactory.create(config.getRemoteConfig().getName())); this.timeout = config.getRemoteConfig().getTimeout(); } @Override public List<RefUpdateState> fetch(List<RefSpec> refsSpec) throws IOException { List<String> refs = refsSpec.stream().map(s -> s.toString()).collect(Collectors.toList()); - List<String> command = Lists.newArrayList("git", "fetch", uri.toASCIIString()); + List<String> command = Lists.newArrayList("git", "fetch", uri.toPrivateASCIIString()); command.addAll(refs); ProcessBuilder pb = new ProcessBuilder().command(command).directory(localProjectDirectory); repLog.info("Fetch references {} from {}", refs, uri); @@ -83,6 +89,19 @@ } } + protected URIish appendCredentials(URIish uri, CredentialsProvider credentialsProvider) { + CredentialItem.Username user = new CredentialItem.Username(); + CredentialItem.Password pass = new CredentialItem.Password(); + if (credentialsProvider.supports(user, pass) + && credentialsProvider.get(uri, user, pass) + && uri.getScheme() != null + && !"ssh".equalsIgnoreCase(uri.getScheme())) { + return uri.setUser(user.getValue()).setPass(String.valueOf(pass.getValue())); + } + + return uri; + } + public boolean waitForTaskToFinish(Process process) throws InterruptedException { if (timeout == 0) { process.waitFor();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java index a02f43f..406cd8c 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java
@@ -34,7 +34,12 @@ import com.google.gerrit.extensions.config.FactoryModule; import com.google.gerrit.server.config.SitePaths; import com.google.inject.Inject; +import com.google.inject.Scopes; import com.google.inject.assistedinject.FactoryModuleBuilder; +import com.googlesource.gerrit.plugins.replication.AutoReloadSecureCredentialsFactoryDecorator; +import com.googlesource.gerrit.plugins.replication.CredentialsFactory; +import com.googlesource.gerrit.plugins.replication.ReplicationConfig; +import com.googlesource.gerrit.plugins.replication.ReplicationFileBasedConfig; import com.googlesource.gerrit.plugins.replication.pull.fetch.BatchFetchClient; import com.googlesource.gerrit.plugins.replication.pull.fetch.CGitFetch; import com.googlesource.gerrit.plugins.replication.pull.fetch.Fetch; @@ -270,6 +275,10 @@ try { RemoteConfig remoteConfig = new RemoteConfig(cf, "test_config"); SourceConfiguration sourceConfig = new SourceConfiguration(remoteConfig, cf); + bind(ReplicationConfig.class).to(ReplicationFileBasedConfig.class); + bind(CredentialsFactory.class) + .to(AutoReloadSecureCredentialsFactoryDecorator.class) + .in(Scopes.SINGLETON); bind(SourceConfiguration.class).toInstance(sourceConfig); install(
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java index 82dc2b8..4e831bc 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
@@ -43,6 +43,7 @@ import com.googlesource.gerrit.plugins.replication.ReplicationFileBasedConfig; import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData; import com.googlesource.gerrit.plugins.replication.pull.api.exception.RefUpdateException; +import com.googlesource.gerrit.plugins.replication.pull.client.FetchApiClient; import com.googlesource.gerrit.plugins.replication.pull.client.FetchRestApiClient; import com.googlesource.gerrit.plugins.replication.pull.client.HttpResult; import com.googlesource.gerrit.plugins.replication.pull.filter.ExcludedRefsFilter; @@ -73,7 +74,7 @@ @Mock private DynamicItem<EventDispatcher> dis; @Mock ReplicationStateListeners sl; @Mock FetchRestApiClient fetchRestApiClient; - @Mock FetchRestApiClient.Factory fetchClientFactory; + @Mock FetchApiClient.Factory fetchClientFactory; @Mock AccountInfo accountInfo; @Mock RevisionReader revReader; @Mock RevisionData revisionData;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java index 394a4a4..a1c2172 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java
@@ -135,7 +135,7 @@ + " ]\n" + "}"; - FetchRestApiClient objectUnderTest; + FetchApiClient objectUnderTest; @Before public void setup() throws ClientProtocolException, IOException {