Merge pull request #1555 from jclouds/issue-1492-1.6.x
fix issue #1492: invalidate dynect session on ip mismatch (1.6.x)
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/filters/SessionManager.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/filters/SessionManager.java
index 07174e5..7cfdb02 100644
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/filters/SessionManager.java
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/filters/SessionManager.java
@@ -101,12 +101,15 @@
return builder.build();
}
+ private static final String IP_MISMATCH = "IP address does not match current session";
+
@Override
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
boolean retry = false; // default
try {
- if (response.getStatusCode() == 401) {
- closeClientButKeepContentStream(response);
+ byte[] data = closeClientButKeepContentStream(response);
+ String message = data != null ? new String(data) : null;
+ if (response.getStatusCode() == 401 || (message != null && message.indexOf(IP_MISMATCH) != -1)) {
logger.debug("invalidating session");
sessionCache.invalidateAll();
retry = super.shouldRetryRequest(command, response);
diff --git a/providers/dynect/src/test/java/org/jclouds/dynect/v3/filters/SessionManagerTest.java b/providers/dynect/src/test/java/org/jclouds/dynect/v3/filters/SessionManagerTest.java
index 66f25ae..c80401e 100644
--- a/providers/dynect/src/test/java/org/jclouds/dynect/v3/filters/SessionManagerTest.java
+++ b/providers/dynect/src/test/java/org/jclouds/dynect/v3/filters/SessionManagerTest.java
@@ -18,6 +18,8 @@
*/
package org.jclouds.dynect.v3.filters;
+import static com.google.common.io.Resources.getResource;
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.FORBIDDEN;
import static javax.ws.rs.core.Response.Status.UNAUTHORIZED;
import static org.easymock.EasyMock.createMock;
@@ -30,6 +32,8 @@
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
+import java.io.IOException;
+
import org.jclouds.domain.Credentials;
import org.jclouds.dynect.v3.domain.Session;
import org.jclouds.dynect.v3.domain.SessionCredentials;
@@ -97,6 +101,34 @@
@SuppressWarnings("unchecked")
@Test
+ public void testIPMismatchShouldInvalidateSessionAndRetry() throws IOException {
+ HttpCommand command = createMock(HttpCommand.class);
+ Supplier<Credentials> creds = createMock(Supplier.class);
+ LoadingCache<Credentials, Session> sessionCache = createMock(LoadingCache.class);
+ SessionApi sessionApi = createMock(SessionApi.class);
+
+ sessionCache.invalidateAll();
+ expectLastCall();
+ expect(command.incrementFailureCount()).andReturn(1);
+ expect(command.isReplayable()).andReturn(true);
+ expect(command.getFailureCount()).andReturn(1).atLeastOnce();
+
+ replay(creds, sessionCache, sessionApi, command);
+
+ HttpResponse response = HttpResponse.builder()
+ .statusCode(BAD_REQUEST.getStatusCode())
+ .payload(getResource("ip_mismatch.json").openStream())
+ .build();
+
+ SessionManager retry = new SessionManager(creds, sessionCache, sessionApi);
+
+ assertTrue(retry.shouldRetryRequest(command, response));
+
+ verify(creds, sessionCache, sessionApi, command);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
public void testForbiddenShouldNotInvalidateSessionOrRetry() {
HttpCommand command = createMock(HttpCommand.class);
Supplier<Credentials> creds = createMock(Supplier.class);
diff --git a/providers/dynect/src/test/resources/ip_mismatch.json b/providers/dynect/src/test/resources/ip_mismatch.json
new file mode 100644
index 0000000..1fdcb6b
--- /dev/null
+++ b/providers/dynect/src/test/resources/ip_mismatch.json
@@ -0,0 +1,17 @@
+{
+ "status": "failure",
+ "data": {},
+ "job_id": 305900967,
+ "msgs": [{
+ "INFO": "login: IP address does not match current session",
+ "SOURCE": "BLL",
+ "ERR_CD": "INVALID_DATA",
+ "LVL": "ERROR"
+ }, {
+ "INFO": "login: There was a problem with your credentials",
+ "SOURCE": "BLL",
+ "ERR_CD": null,
+ "LVL": "INFO"
+ }
+ ]
+}