Skip to content
Permalink
Browse files
IGNITE-10498: Fix for handling conflict error returned by TeamCity fo…
…r some build problem
  • Loading branch information
dspavlov committed May 29, 2019
1 parent fe4d519 commit d419ebc43ed88c1ffcc3a9e92bdd0613c77de78a
Showing 12 changed files with 107 additions and 11 deletions.
@@ -81,5 +81,9 @@ default void setAuthData(String user, String pwd) {
Base64Util.encodeUtf8String(user + ":" + pwd));
}

/**
* @param username Username.
* @throws RuntimeException in case loading failed, see details in {@link ITeamcityConn}.
*/
User getUserByUsername(String username);
}
@@ -73,11 +73,13 @@
import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
import org.apache.ignite.ci.tcmodel.user.User;
import org.apache.ignite.ci.tcmodel.user.Users;
import org.apache.ignite.ci.teamcity.pure.ITeamcityConn;
import org.apache.ignite.ci.teamcity.pure.ITeamcityHttpConnection;
import org.apache.ignite.ci.util.ExceptionUtil;
import org.apache.ignite.ci.util.HttpUtil;
import org.apache.ignite.ci.util.XmlUtil;
import org.apache.ignite.ci.util.ZipUtil;
import org.apache.ignite.ci.web.rest.exception.ConflictException;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -324,6 +326,15 @@ public CompletableFuture<File> unzipFirstFile(CompletableFuture<File> fut) {
.getBuildTypesNonNull();
}

/**
* @param url Url.
* @param rootElem Root elem.
*
* @throws UncheckedIOException caused by FileNotFoundException - If not found (404) was returned from service.
* @throws ConflictException If conflict (409) was returned from service.
* @throws IllegalStateException if some unexpected HTTP error returned.
* @throws UncheckedIOException in case communication failed.
*/
private <T> T sendGetXmlParseJaxb(String url, Class<T> rootElem) {
try {
try (InputStream inputStream = teamcityHttpConn.sendGet(basicAuthTok, url)) {
@@ -417,6 +428,10 @@ private CompletableFuture<LogCheckTask> checkBuildLogNoCache(int buildId, ISuite
this.executor = executor;
}

/**
*
* @throws RuntimeException in case loading failed. See details in {@link ITeamcityConn}.
*/
@AutoProfiling
public Users getUsers() {
return getJaxbUsingHref("app/rest/latest/users", Users.class);
@@ -129,7 +129,7 @@ public void setValue(String str) {
data = gzip;
}

logger.info("U " + uncompressed.length + " S " + snappyLen + " Z " + gzipLen + ": F (" +
logger.debug("U " + uncompressed.length + " S " + snappyLen + " Z " + gzipLen + ": F (" +
flag + ")");
}

@@ -36,6 +36,7 @@
import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
import org.apache.ignite.ci.teamcity.pure.ITeamcityConn;
import org.apache.ignite.ci.util.ExceptionUtil;
import org.apache.ignite.ci.web.rest.exception.ConflictException;
import org.apache.ignite.internal.util.GridConcurrentHashSet;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
@@ -323,7 +324,7 @@ public FatBuildCompacted loadBuild(ITeamcityConn conn, int buildId,
* @param conn
* @param buildId
* @param existingBuild
* @return new build if it was updated or null if no updates detected
* @return new build if it was updated or <code>null</code> if no updates detected
*/
@SuppressWarnings({"WeakerAccess"})
@AutoProfiling
@@ -382,7 +383,9 @@ public FatBuildCompacted loadBuild(ITeamcityConn conn, int buildId,
}
}
catch (Exception e) {
if (Throwables.getRootCause(e) instanceof FileNotFoundException) {
Throwable cause = Throwables.getRootCause(e);

if (cause instanceof FileNotFoundException || cause instanceof ConflictException) {
logger.info("Loading build [" + buildId + "] for server [" + srvName + "] failed:" + e.getMessage(), e);

if (existingBuild != null) {
@@ -263,7 +263,7 @@ public void setDetails(String dtlsStr) {
}


logger.info("U " + uncompressed.length + " S " + snappyLen + " Z " + gzipLen + ": F (" +
logger.debug("U " + uncompressed.length + " S " + snappyLen + " Z " + gzipLen + ": F (" +
flags.get(COMPRESS_TYPE_FLAG1) + ", " +
flags.get(COMPRESS_TYPE_FLAG2) +")");
}
@@ -17,6 +17,8 @@

package org.apache.ignite.ci.teamcity.pure;

import java.io.FileNotFoundException;
import java.io.UncheckedIOException;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
@@ -36,10 +38,18 @@
import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrences;
import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
import org.apache.ignite.ci.web.rest.exception.ConflictException;

/**
* Pure Teamcity Connection API for calling methods from REST service: <br>
* https://confluence.jetbrains.com/display/TCD10/REST+API
* https://confluence.jetbrains.com/display/TCD10/REST+API.<br><br>
*
*
* HTTP methods return following errors in case HTTP communication failures:
* <ul><li>{@link UncheckedIOException} caused by {@link FileNotFoundException} - If not found (404) was returned from service.</li>
* <li>{@link ConflictException} If conflict (409) was returned from service.</li>
* <li>{@link IllegalStateException} if some unexpected HTTP error returned.</li>
* <li>{@link UncheckedIOException} in case communication failed.</ul>
*/
public interface ITeamcityConn {
/**
@@ -62,6 +72,8 @@ default String host() {

/**
* @param buildId Build id.
*
* @throws RuntimeException in case loading failed, see details in {@link ITeamcityConn}.
*/
public Build getBuild(int buildId);

@@ -102,21 +114,29 @@ public Build triggerBuild(String buildTypeId, @Nonnull String branchName, boolea

/**
* @param buildId Build id.
*
* @throws RuntimeException in case loading failed, see details in {@link ITeamcityConn}.
*/
public ProblemOccurrences getProblems(int buildId);

/**
* @param buildId Build id.
*
* @throws RuntimeException in case loading failed, see details in {@link ITeamcityConn}.
*/
public Statistics getStatistics(int buildId);

/**
* @param buildId Build id.
*
* @throws RuntimeException in case loading failed, see details in {@link ITeamcityConn}.
*/
public ChangesList getChangesList(int buildId);

/**
* @param changeId Change id.
*
* @throws RuntimeException in case loading failed, see details in {@link ITeamcityConn}.
*/
public Change getChange(int changeId);

@@ -17,13 +17,18 @@

package org.apache.ignite.ci.teamcity.pure;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ignite.ci.web.rest.exception.ConflictException;

public interface ITeamcityHttpConnection {
/**
* @param basicAuthTok Basic auth token.
* @param url Url.
* @throws FileNotFoundException If not found (404) was returned from service.
* @throws ConflictException If conflict (409) was returned from service.
* @throws IllegalStateException if some unexpected HTTP error returned.
*/
public InputStream sendGet(String basicAuthTok, String url) throws IOException;
}
@@ -22,6 +22,9 @@
import java.io.IOException;
import java.io.InputStream;

/**
*
*/
public class TeamcityRecordingConnection implements ITeamcityHttpConnection {
/** Recorder. */
@Inject private TeamcityRecorder recorder;
@@ -33,6 +33,7 @@
import java.nio.file.StandardCopyOption;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.ignite.ci.web.rest.exception.ConflictException;
import org.apache.ignite.ci.web.rest.exception.ServiceUnauthorizedException;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -73,6 +74,9 @@ private static String readIsToString(InputStream inputStream) throws IOException
* @param url URL.
* @return Input stream from connection.
* @throws IOException If failed.
* @throws FileNotFoundException If not found (404) was returned from service.
* @throws ConflictException If conflict (409) was returned from service.
* @throws IllegalStateException if some unexpected HTTP error returned.
*/
public static InputStream sendGetWithBasicAuth(String basicAuthTok, String url) throws IOException {
final Stopwatch started = Stopwatch.createStarted();
@@ -171,7 +175,10 @@ private static InputStream sendPostWithBasicAuth(String tok, String url,
*
* @param con Http connection.
* @return Input stream from connection.
* @throws IOException If failed.
* @throws IOException If communication failed.
* @throws FileNotFoundException If not found (404) was returned from service.
* @throws ConflictException If conflict (409) was returned from service.
* @throws IllegalStateException if some unexpected HTTP error returned.
*/
private static InputStream getInputStream(HttpURLConnection con) throws IOException {
int resCode = con.getResponseCode();
@@ -180,18 +187,22 @@ private static InputStream getInputStream(HttpURLConnection con) throws IOExcept
if (resCode / 100 == 2)
return con.getInputStream();

String detailsFromResponeText = readIsToString(con.getErrorStream());

if (resCode == 400)
throw new BadRequestException(readIsToString(con.getErrorStream()));
throw new BadRequestException(detailsFromResponeText);

if (resCode == 401)
throw new ServiceUnauthorizedException("Service " + con.getURL() + " returned forbidden error.");

if (resCode == 404)
throw new FileNotFoundException("Service " + con.getURL() + " returned not found error."
+ readIsToString(con.getErrorStream()));
throw new FileNotFoundException("Service " + con.getURL() + " returned not found error. " + detailsFromResponeText);

if (resCode == 409)
throw new ConflictException("Service " + con.getURL() + " returned Conflict Response Code :\n" + detailsFromResponeText);

throw new IllegalStateException("Service " + con.getURL() + " returned Invalid Response Code : " + resCode + ":\n"
+ readIsToString(con.getErrorStream()));
+ detailsFromResponeText);
}

/**
@@ -28,7 +28,7 @@
public static final String GITHUB_REF = "https://github.com/apache/ignite-teamcity-bot";

/** TC Bot Version. */
public static final String VERSION = "20190516";
public static final String VERSION = "20190529";

/** Java version, where Web App is running. */
public String javaVer;
@@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.ignite.ci.web.rest.exception;

/**
* The request could not be completed due to a conflict with the current state of the target resource.
*
* This exception is thrown in case HTTP 409-Conflict is returned.
*/
public class ConflictException extends RuntimeException {
/**
* @param msg Message.
*/
public ConflictException(String msg) {
super(msg);
}
}
@@ -21,6 +21,9 @@
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

/**
* Exception is thrown if 3rd party service returned 401 - unauthorized.
*/
@Provider
public class ServiceUnauthorizedException extends RuntimeException
implements ExceptionMapper<ServiceUnauthorizedException> {

0 comments on commit d419ebc

Please sign in to comment.