blob: aaf2b15134b587d2f62a7b9b71794f7dcda9feae [file] [log] [blame]
// Copyright (C) 2018 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;
import static com.googlesource.gerrit.plugins.replication.GerritSshApi.GERRIT_ADMIN_PROTOCOL_PREFIX;
import static com.googlesource.gerrit.plugins.replication.ReplicationQueue.repLog;
import com.google.common.base.Charsets;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicHeader;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
public class GerritRestApi implements AdminApi {
public interface Factory {
GerritRestApi create(URIish uri);
}
private final CredentialsFactory credentials;
private final CloseableHttpClient httpClient;
private final RemoteConfig remoteConfig;
private final URIish uri;
@Inject
GerritRestApi(
CredentialsFactory credentials,
CloseableHttpClient httpClient,
RemoteConfig remoteConfig,
@Assisted URIish uri) {
this.credentials = credentials;
this.httpClient = httpClient;
this.remoteConfig = remoteConfig;
this.uri = uri;
}
@Override
public boolean createProject(Project.NameKey project, String head) {
repLog.info("Creating project {} on {}", project, uri);
String url = String.format("%s/a/projects/%s", toHttpUri(uri), Url.encode(project.get()));
try {
return httpClient
.execute(new HttpPut(url), new HttpResponseHandler(), getContext())
.isSuccessful();
} catch (IOException e) {
repLog.error("Couldn't perform project creation on {}", uri, e);
return false;
}
}
@Override
public boolean deleteProject(Project.NameKey project) {
repLog.info("Deleting project {} on {}", project, uri);
String url = String.format("%s/a/projects/%s", toHttpUri(uri), Url.encode(project.get()));
try {
httpClient.execute(new HttpDelete(url), new HttpResponseHandler(), getContext());
return true;
} catch (IOException e) {
repLog.error("Couldn't perform project deletion on {}", uri, e);
}
return false;
}
@Override
public boolean updateHead(Project.NameKey project, String newHead) {
repLog.info("Updating head of {} on {}", project, uri);
String url = String.format("%s/a/projects/%s/HEAD", toHttpUri(uri), Url.encode(project.get()));
try {
HttpPut req = new HttpPut(url);
req.setEntity(
new StringEntity(String.format("{\"ref\": \"%s\"}", newHead), Charsets.UTF_8.name()));
req.addHeader(new BasicHeader("Content-Type", "application/json"));
httpClient.execute(req, new HttpResponseHandler(), getContext());
return true;
} catch (IOException e) {
repLog.error("Couldn't perform update head on {}", uri, e);
}
return false;
}
private HttpClientContext getContext() {
HttpClientContext ctx = HttpClientContext.create();
ctx.setCredentialsProvider(adapt(credentials.create(remoteConfig.getName())));
return ctx;
}
private CredentialsProvider adapt(org.eclipse.jgit.transport.CredentialsProvider cp) {
CredentialItem.Username user = new CredentialItem.Username();
CredentialItem.Password pass = new CredentialItem.Password();
if (cp.supports(user, pass) && cp.get(uri, user, pass)) {
CredentialsProvider adapted = new BasicCredentialsProvider();
adapted.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(user.getValue(), new String(pass.getValue())));
return adapted;
}
return null;
}
private static String toHttpUri(URIish uri) {
String u = uri.toString();
if (u.startsWith(GERRIT_ADMIN_PROTOCOL_PREFIX)) {
u = u.substring(GERRIT_ADMIN_PROTOCOL_PREFIX.length());
}
if (u.endsWith("/")) {
return u.substring(0, u.length() - 1);
}
return u;
}
}