Преглед на файлове

Poke test during proposal phase.

tags/v0.6.0
James Moger преди 12 години
родител
ревизия
4aafd4362c

+ 13
- 1
src/com/gitblit/Constants.java Целия файл

@@ -115,7 +115,7 @@ public class Constants {
* Enumeration representing the types of federation requests.
*/
public static enum FederationRequest {
PROPOSAL, PULL_REPOSITORIES, PULL_USERS, PULL_SETTINGS, STATUS;
POKE, PROPOSAL, PULL_REPOSITORIES, PULL_USERS, PULL_SETTINGS, STATUS;
public static FederationRequest fromName(String name) {
for (FederationRequest type : values()) {
@@ -181,4 +181,16 @@ public class Constants {
}
}
/**
* Enumeration representing the possible results of federation proposal
* requests.
*/
public static enum FederationProposalResult {
ERROR, FEDERATION_DISABLED, MISSING_DATA, NO_PROPOSALS, NO_POKE, ACCEPTED;
@Override
public String toString() {
return name();
}
}
}

+ 26
- 5
src/com/gitblit/FederationServlet.java Целия файл

@@ -35,6 +35,7 @@ import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.FederationUtils;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;
@@ -110,6 +111,16 @@ public class FederationServlet extends HttpServlet {
private void processRequest(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
java.io.IOException {
FederationRequest reqType = FederationRequest.fromName(request.getParameter("req"));
logger.info(MessageFormat.format("Federation {0} request from {1}", reqType,
request.getRemoteAddr()));
if (FederationRequest.POKE.equals(reqType)) {
// Gitblit always responds to POKE requests to verify a connection
logger.info("Received federation POKE from " + request.getRemoteAddr());
return;
}
if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {
logger.warn(Keys.git.enableGitServlet + " must be set TRUE for federation requests.");
response.sendError(HttpServletResponse.SC_FORBIDDEN);
@@ -124,11 +135,6 @@ public class FederationServlet extends HttpServlet {
return;
}
String token = request.getParameter("token");
FederationRequest reqType = FederationRequest.fromName(request.getParameter("req"));
logger.info(MessageFormat.format("Federation {0} request from {1}", reqType,
request.getRemoteAddr()));
if (FederationRequest.PROPOSAL.equals(reqType)) {
// Receive a gitblit federation proposal
BufferedReader reader = request.getReader();
@@ -159,6 +165,20 @@ public class FederationServlet extends HttpServlet {
return;
}
// poke the origin Gitblit instance that is proposing federation
boolean poked = false;
try {
poked = FederationUtils.poke(proposal.url);
} catch (Exception e) {
logger.error("Failed to poke origin", e);
}
if (!poked) {
logger.error(MessageFormat.format("Failed to send federation poke to {0}",
proposal.url));
response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
return;
}
String url = HttpUtils.getGitblitURL(request);
GitBlit.self().submitFederationProposal(proposal, url);
logger.info(MessageFormat.format(
@@ -207,6 +227,7 @@ public class FederationServlet extends HttpServlet {
}
// Determine the federation tokens for this gitblit instance
String token = request.getParameter("token");
List<String> tokens = GitBlit.self().getFederationTokens();
if (!tokens.contains(token)) {
logger.warn(MessageFormat.format(

+ 2
- 1
src/com/gitblit/GitBlit.java Целия файл

@@ -971,7 +971,8 @@ public class GitBlit implements ServletContextListener {
* @param proposal
* the proposal
* @param gitblitUrl
* the url of your gitblit instance
* the url of your gitblit instance to send an email to
* administrators
* @return true if the proposal was submitted
*/
public boolean submitFederationProposal(FederationProposal proposal, String gitblitUrl) {

+ 44
- 4
src/com/gitblit/utils/FederationUtils.java Целия файл

@@ -45,6 +45,7 @@ import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.FederationProposalResult;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.FederationServlet;
import com.gitblit.IStoredSettings;
@@ -82,7 +83,7 @@ public class FederationUtils {
private static final SSLContext SSL_CONTEXT;
private static final DummyHostnameVerifier HOSTNAME_VERIFIER;
private static final Logger LOGGER = LoggerFactory.getLogger(FederationUtils.class);
static {
@@ -181,6 +182,26 @@ public class FederationUtils {
return federationRegistrations;
}
/**
* Sends a federation poke to the Gitblit instance at remoteUrl. Pokes are
* sent by an pulling Gitblit instance to an origin Gitblit instance as part
* of the proposal process. This is to ensure that the pulling Gitblit
* instance has an IP route to the origin instance.
*
* @param remoteUrl
* the remote Gitblit instance to send a federation proposal to
* @param proposal
* a complete federation proposal
* @return true if there is a route to the remoteUrl
*/
public static boolean poke(String remoteUrl) throws Exception {
String url = FederationServlet.asFederationLink(remoteUrl, null, FederationRequest.POKE);
Gson gson = new Gson();
String json = gson.toJson("POKE");
int status = writeJson(url, json);
return status == HttpServletResponse.SC_OK;
}
/**
* Sends a federation proposal to the Gitblit instance at remoteUrl
*
@@ -188,15 +209,34 @@ public class FederationUtils {
* the remote Gitblit instance to send a federation proposal to
* @param proposal
* a complete federation proposal
* @return true if the proposal was received
* @return the federation proposal result code
*/
public static boolean propose(String remoteUrl, FederationProposal proposal) throws Exception {
public static FederationProposalResult propose(String remoteUrl, FederationProposal proposal)
throws Exception {
String url = FederationServlet
.asFederationLink(remoteUrl, null, FederationRequest.PROPOSAL);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(proposal);
int status = writeJson(url, json);
return status == HttpServletResponse.SC_OK;
switch (status) {
case HttpServletResponse.SC_FORBIDDEN:
// remote Gitblit Federation disabled
return FederationProposalResult.FEDERATION_DISABLED;
case HttpServletResponse.SC_BAD_REQUEST:
// remote Gitblit did not receive any JSON data
return FederationProposalResult.MISSING_DATA;
case HttpServletResponse.SC_METHOD_NOT_ALLOWED:
// remote Gitblit not accepting proposals
return FederationProposalResult.NO_PROPOSALS;
case HttpServletResponse.SC_NOT_ACCEPTABLE:
// remote Gitblit failed to poke this Gitblit instance
return FederationProposalResult.NO_POKE;
case HttpServletResponse.SC_OK:
// received
return FederationProposalResult.ACCEPTED;
default:
return FederationProposalResult.ERROR;
}
}
/**

+ 33
- 5
src/com/gitblit/wicket/pages/SendProposalPage.java Целия файл

@@ -26,6 +26,7 @@ import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import com.gitblit.Constants.FederationProposalResult;
import com.gitblit.GitBlit;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.RepositoryModel;
@@ -78,17 +79,44 @@ public class SendProposalPage extends BasePage {
error("Please enter a destination url for your proposal!");
return;
}
// build new proposal
FederationProposal proposal = GitBlit.self().createFederationProposal(myUrl, token);
proposal.url = myUrl;
proposal.message = message;
try {
if (FederationUtils.propose(destinationUrl, proposal)) {
info(MessageFormat.format("Proposal successfully received by {0}.", destinationUrl));
FederationProposalResult res = FederationUtils
.propose(destinationUrl, proposal);
switch (res) {
case ACCEPTED:
info(MessageFormat.format("Proposal successfully received by {0}.",
destinationUrl));
setResponsePage(RepositoriesPage.class);
} else {
error(MessageFormat.format("Sorry, {0} rejected your proposal.", destinationUrl));
break;
case NO_POKE:
error(MessageFormat.format(
"Sorry, {0} could not find a Gitblit instance at {1}.",
destinationUrl, myUrl));
break;
case NO_PROPOSALS:
error(MessageFormat.format(
"Sorry, {0} is not accepting proposals at this time.",
destinationUrl));
break;
case FEDERATION_DISABLED:
error(MessageFormat
.format("Sorry, {0} is not configured to federate with any Gitblit instances.",
destinationUrl));
break;
case MISSING_DATA:
error(MessageFormat.format("Sorry, {0} did not receive any proposal data!",
destinationUrl));
break;
case ERROR:
error(MessageFormat.format(
"Sorry, {0} reports that an unexpected error occurred!",
destinationUrl));
break;
}
} catch (Exception e) {
if (!StringUtils.isEmpty(e.getMessage())) {

+ 6
- 4
tests/com/gitblit/tests/FederationTests.java Целия файл

@@ -24,6 +24,7 @@ import java.util.concurrent.Executors;
import junit.framework.TestCase;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.FederationProposalResult;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.FederationServlet;
@@ -91,14 +92,15 @@ public class FederationTests extends TestCase {
"testtoken", repositories);
// propose federation
assertTrue("proposal refused",
FederationUtils.propose("http://localhost:" + port, proposal));
assertEquals("proposal refused",
FederationUtils.propose("http://localhost:" + port, proposal),
FederationProposalResult.NO_PROPOSALS);
}
public void testPullRepositories() throws Exception {
try {
String url = FederationServlet.asFederationLink("http://localhost:" + port, "testtoken",
FederationRequest.PULL_REPOSITORIES);
String url = FederationServlet.asFederationLink("http://localhost:" + port,
"testtoken", FederationRequest.PULL_REPOSITORIES);
String json = FederationUtils.readJson(url);
} catch (IOException e) {
if (!e.getMessage().contains("403")) {

Loading…
Отказ
Запис