Skip to content

Commit

Permalink
Issue fixes (#463)
Browse files Browse the repository at this point in the history
* [Resolves #458] timeout adjust: read 120 conn 60

* [Resolves #461] Support log analytics and app insights endpoints

* Fix timeout for RestClient.newBuilder()

* [#455] Support rfc 1123 retry-after header

* Add US GOV log analytics endpoint

* Up adal and commons-codec version

* [Resolves #440] Allow setting max retry for MSI creds
  • Loading branch information
jianghaolu authored Aug 7, 2018
1 parent 1193ad8 commit 690042a
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
package com.microsoft.azure.arm.utils;

import com.microsoft.azure.arm.resources.ResourceUtilsCore;
import com.microsoft.rest.DateTimeRfc1123;
import okhttp3.Interceptor;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.slf4j.LoggerFactory;

import java.io.IOException;
Expand Down Expand Up @@ -71,13 +74,27 @@ public Response intercept(Chain chain) throws IOException {
String retryAfterHeader = response.header("Retry-After");
int retryAfter = 0;
if (retryAfterHeader != null) {
retryAfter = Integer.parseInt(retryAfterHeader);
DateTime retryWhen = null;
try {
retryWhen = new DateTimeRfc1123(retryAfterHeader).dateTime();
} catch (Exception e) { }
if (retryWhen == null) {
retryAfter = Integer.parseInt(retryAfterHeader);
} else {
retryAfter = new Duration(null, retryWhen).toStandardSeconds().getSeconds();
}
}
if (retryAfter <= 0) {
Pattern pattern = Pattern.compile("try again after '([0-9]*)' minutes", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(content(response.body()));
if (matcher.find()) {
retryAfter = (int) TimeUnit.MINUTES.toSeconds(Integer.parseInt(matcher.group(1)));
} else {
pattern = Pattern.compile("try again after '([0-9]*)' seconds", Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher(content(response.body()));
if (matcher.find()) {
retryAfter = Integer.parseInt(matcher.group(1));
}
}
}
if (retryAfter > 0) {
Expand All @@ -86,7 +103,7 @@ public Response intercept(Chain chain) throws IOException {
context = "";
}
LoggerFactory.getLogger(context)
.info("Azure Resource Manager read/write per hour limit reached. Will retry in: " + retryAfter + " seconds");
.info("Azure Resource Manager read/write per hour limit reached. Will retry in: " + retryAfter + " seconds");
SdkContext.sleep((int) (TimeUnit.SECONDS.toMillis(retryAfter) + 100));
}
return chain.proceed(chain.request());
Expand Down
4 changes: 4 additions & 0 deletions azure-client-authentication/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
<artifactId>azure-client-runtime</artifactId>
<version>1.6.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
public class MSICredentials extends AzureTokenCredentials {
//
private final List<Integer> retrySlots = new ArrayList<>(Arrays.asList(new Integer[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765}));
private final int maxRetry = retrySlots.size();
private int maxRetry = retrySlots.size();
private final Lock lock = new ReentrantLock();
private final ConcurrentHashMap<String, MSIToken> cache = new ConcurrentHashMap<>();
//
Expand Down Expand Up @@ -287,6 +287,22 @@ private static void sleep(int millis) {
}
}

/**
* @return the maximum retries allowed
*/
public int maxRetry() {
return maxRetry;
}

/**
* Sets the maximum retries allowed. Retry timeouts grow
* exponentially up to ~2 hours as the client keeps retrying.
* @param maxRetry the max retries allowed
*/
public void setMaxRetry(int maxRetry) {
this.maxRetry = maxRetry;
}

/**
* The source of MSI token.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public AzureEnvironment(Map<String, String> endpoints) {
put("keyVaultDnsSuffix", ".vault.azure.net");
put("azureDataLakeStoreFileSystemEndpointSuffix", "azuredatalakestore.net");
put("azureDataLakeAnalyticsCatalogAndJobEndpointSuffix", "azuredatalakeanalytics.net");
put("azureLogAnalyticsResourceId", "https://api.loganalytics.io/");
put("azureApplicationInsightsResourceId", "https://api.applicationinsights.io/");
}});

/**
Expand All @@ -73,6 +75,8 @@ public AzureEnvironment(Map<String, String> endpoints) {
// TODO: add dns suffixes for the china cloud for datalake store and datalake analytics once they are defined.
put("azureDataLakeStoreFileSystemEndpointSuffix", "N/A");
put("azureDataLakeAnalyticsCatalogAndJobEndpointSuffix", "N/A");
put("azureLogAnalyticsResourceId", "N/A");
put("azureApplicationInsightsResourceId", "N/A");
}});

/**
Expand All @@ -97,6 +101,8 @@ public AzureEnvironment(Map<String, String> endpoints) {
// TODO: add dns suffixes for the US government for datalake store and datalake analytics once they are defined.
put("azureDataLakeStoreFileSystemEndpointSuffix", "N/A");
put("azureDataLakeAnalyticsCatalogAndJobEndpointSuffix", "N/A");
put("azureLogAnalyticsResourceId", "https://api.loganalytics.us/");
put("azureApplicationInsightsResourceId", "N/A");
}});

/**
Expand All @@ -121,6 +127,8 @@ public AzureEnvironment(Map<String, String> endpoints) {
// TODO: add dns suffixes for the germany cloud for datalake store and datalake analytics once they are defined.
put("azureDataLakeStoreFileSystemEndpointSuffix", "N/A");
put("azureDataLakeAnalyticsCatalogAndJobEndpointSuffix", "N/A");
put("azureLogAnalyticsResourceId", "N/A");
put("azureApplicationInsightsResourceId", "N/A");
}});

/**
Expand Down Expand Up @@ -250,6 +258,20 @@ public String azureDataLakeAnalyticsCatalogAndJobEndpointSuffix() {
return endpoints.get("azureDataLakeAnalyticsCatalogAndJobEndpointSuffix");
}

/**
* @return the log analytics endpoint.
*/
public String logAnalyticsEndpoint() {
return endpoints.get("azureLogAnalyticsResourceId");
}

/**
* @return the log analytics endpoint.
*/
public String applicationInsightsEndpoint() {
return endpoints.get("azureApplicationInsightsResourceId");
}


/**
* The enum representing available endpoints in an environment.
Expand All @@ -272,7 +294,11 @@ public enum Endpoint implements Environment.Endpoint {
/** Azure Data Lake Store DNS suffix. */
DATA_LAKE_STORE("azureDataLakeStoreFileSystemEndpointSuffix"),
/** Azure Data Lake Analytics DNS suffix. */
DATA_LAKE_ANALYTICS("azureDataLakeAnalyticsCatalogAndJobEndpointSuffix");
DATA_LAKE_ANALYTICS("azureDataLakeAnalyticsCatalogAndJobEndpointSuffix"),
/** Azure Log Analytics endpoint. */
LOG_ANALYTICS("azureLogAnalyticsResourceId"),
/** Azure Application Insights. */
APPLICATION_INSIGHTS("azureApplicationInsightsResourceId");

private String field;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import okhttp3.Response;
import okhttp3.Route;

import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.Proxy;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLSocketFactory;

/**
* AzureTokenCredentials represents a credentials object with access to Azure
Expand Down Expand Up @@ -57,9 +57,17 @@ protected final String getToken(Request request) throws IOException {
break;
} else if (endpoint.getKey().equals(Endpoint.GRAPH.identifier())) {
resource = environment().graphEndpoint();
break;
} else if (endpoint.getKey().equals(Endpoint.LOG_ANALYTICS.identifier())) {
resource = environment().logAnalyticsEndpoint();
break;
} else if (endpoint.getKey().equals(Endpoint.APPLICATION_INSIGHTS.identifier())) {
resource = environment().applicationInsightsEndpoint();
break;
} else if (endpoint.getKey().equals(Endpoint.DATA_LAKE_STORE.identifier())
|| endpoint.getKey().equals(Endpoint.DATA_LAKE_ANALYTICS.identifier())) {
resource = environment().dataLakeEndpointResourceId();
break;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ public Builder() {

private Builder(final RestClient restClient) {
this(restClient.httpClient.newBuilder(), new Retrofit.Builder());
this.httpClientBuilder.readTimeout(restClient.httpClient.readTimeoutMillis(), TimeUnit.MILLISECONDS);
this.httpClientBuilder.connectTimeout(restClient.httpClient.connectTimeoutMillis(), TimeUnit.MILLISECONDS);
this.httpClientBuilder.interceptors().clear();
this.httpClientBuilder.networkInterceptors().clear();
this.baseUrl = restClient.retrofit.baseUrl().toString();
Expand Down Expand Up @@ -244,7 +246,8 @@ public Builder(OkHttpClient.Builder httpClientBuilder, Retrofit.Builder retrofit
// Set up OkHttp client
this.httpClientBuilder = httpClientBuilder
.cookieJar(new JavaNetCookieJar(cookieManager))
.readTimeout(60, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.addInterceptor(new RequestIdHeaderInterceptor())
.addInterceptor(new BaseUrlHandler());
this.retrofitBuilder = retrofitBuilder;
Expand Down Expand Up @@ -489,6 +492,9 @@ public RestClient build() {
if (baseUrl == null) {
throw new IllegalArgumentException("Please set base URL.");
}
if (!baseUrl.endsWith("/")) {
baseUrl += "/";
}
if (responseBuilderFactory == null) {
throw new IllegalArgumentException("Please set response builder factory.");
}
Expand Down
12 changes: 6 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,7 @@
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>com.microsoft.aad</groupId>
<artifactId>adal</artifactId>
<version>1.1.11</version>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
Expand All @@ -128,6 +123,11 @@
<artifactId>azure-annotations</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down

0 comments on commit 690042a

Please sign in to comment.