diff options
author | James Moger <james.moger@gitblit.com> | 2011-09-27 08:22:26 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2011-09-27 08:22:26 -0400 |
commit | 4aafd4362caf198bdea97d2fdf2957aa5c345465 (patch) | |
tree | 2ecfc88d20cea169757483a491ef0d7456521f19 /src/com/gitblit | |
parent | b083f5a956e69715efaaf95b810b02dec687c82e (diff) | |
download | gitblit-4aafd4362caf198bdea97d2fdf2957aa5c345465.tar.gz gitblit-4aafd4362caf198bdea97d2fdf2957aa5c345465.zip |
Poke test during proposal phase.
Diffstat (limited to 'src/com/gitblit')
-rw-r--r-- | src/com/gitblit/Constants.java | 14 | ||||
-rw-r--r-- | src/com/gitblit/FederationServlet.java | 31 | ||||
-rw-r--r-- | src/com/gitblit/GitBlit.java | 3 | ||||
-rw-r--r-- | src/com/gitblit/utils/FederationUtils.java | 48 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/SendProposalPage.java | 38 |
5 files changed, 118 insertions, 16 deletions
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java index b52f055d..befa5fe1 100644 --- a/src/com/gitblit/Constants.java +++ b/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();
+ }
+ }
}
diff --git a/src/com/gitblit/FederationServlet.java b/src/com/gitblit/FederationServlet.java index 784ec33f..7dc5d6a9 100644 --- a/src/com/gitblit/FederationServlet.java +++ b/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(
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index 62b93e7c..f7c43a85 100644 --- a/src/com/gitblit/GitBlit.java +++ b/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) {
diff --git a/src/com/gitblit/utils/FederationUtils.java b/src/com/gitblit/utils/FederationUtils.java index 9fd88173..fde95575 100644 --- a/src/com/gitblit/utils/FederationUtils.java +++ b/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 {
@@ -182,21 +183,60 @@ public class FederationUtils { }
/**
+ * 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
*
* @param remoteUrl
* 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;
+ }
}
/**
diff --git a/src/com/gitblit/wicket/pages/SendProposalPage.java b/src/com/gitblit/wicket/pages/SendProposalPage.java index ea91f1b2..635b4321 100644 --- a/src/com/gitblit/wicket/pages/SendProposalPage.java +++ b/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())) {
|