Poke test during proposal phase.
| | |
| | | * 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()) {
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * 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();
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | 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;
|
| | |
| | | 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);
|
| | |
| | | response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
| | | 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
|
| | |
| | | logger.error(MessageFormat.format("Rejected {0} federation proposal from {1}",
|
| | | proposal.tokenType.name(), proposal.url));
|
| | | response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
|
| | | 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;
|
| | | }
|
| | |
|
| | |
| | | }
|
| | |
|
| | | // 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(
|
| | |
| | | * @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) {
|
| | |
| | | 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;
|
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * 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;
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | 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;
|
| | |
| | | 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())) {
|
| | |
| | | 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;
|
| | |
| | | "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")) {
|