fix issue #1492: invalidate dynect session on ip mismatch

This commit is contained in:
adriancole 2013-04-21 13:13:09 -07:00
parent 00b9fbe921
commit 874d835e75
3 changed files with 54 additions and 2 deletions

View File

@ -101,12 +101,15 @@ public final class SessionManager extends BackoffLimitedRetryHandler implements
return builder.build(); return builder.build();
} }
private static final String IP_MISMATCH = "IP address does not match current session";
@Override @Override
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
boolean retry = false; // default boolean retry = false; // default
try { try {
if (response.getStatusCode() == 401) { byte[] data = closeClientButKeepContentStream(response);
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"); logger.debug("invalidating session");
sessionCache.invalidateAll(); sessionCache.invalidateAll();
retry = super.shouldRetryRequest(command, response); retry = super.shouldRetryRequest(command, response);

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.dynect.v3.filters; 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.FORBIDDEN;
import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; import static javax.ws.rs.core.Response.Status.UNAUTHORIZED;
import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createMock;
@ -30,6 +32,8 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertSame; import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import java.io.IOException;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.dynect.v3.domain.Session; import org.jclouds.dynect.v3.domain.Session;
import org.jclouds.dynect.v3.domain.SessionCredentials; import org.jclouds.dynect.v3.domain.SessionCredentials;
@ -95,6 +99,34 @@ public class SessionManagerTest {
verify(creds, sessionCache, sessionApi, command); verify(creds, sessionCache, sessionApi, command);
} }
@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") @SuppressWarnings("unchecked")
@Test @Test
public void testForbiddenShouldNotInvalidateSessionOrRetry() { public void testForbiddenShouldNotInvalidateSessionOrRetry() {

View File

@ -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"
}
]
}