Simplify connection error handling to show only one message for now

This commit is contained in:
nsingh
2017-01-31 19:45:34 -08:00
parent dfd5cac945
commit 8ebbdc1158
7 changed files with 34 additions and 98 deletions

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.concurrent.Callable;
@@ -20,10 +21,8 @@ import reactor.ipc.netty.channel.AbortedException;
public class CFCallableContext {
public static final String UNAUTHORIZED_ERROR = "unauthorized";
private final CFParamsProviderMessages paramsProviderMessages;
private Throwable lastConnectionError;
private Exception lastConnectionError;
public CFCallableContext(CFParamsProviderMessages paramsProviderMessages) {
this.paramsProviderMessages = paramsProviderMessages;
@@ -38,29 +37,26 @@ public class CFCallableContext {
}
}
private Exception convertToCfVscodeError(Exception e) {
Throwable deepestCause = ExceptionUtil.getDeepestCause(e);
if (deepestCause instanceof UaaException) {
String error = ((UaaException) deepestCause).getError();
if (error != null && error.contains(UNAUTHORIZED_ERROR)) {
this.lastConnectionError = deepestCause;
return new UnauthorizedException(this.paramsProviderMessages.unauthorised());
}
} else if (deepestCause instanceof AbortedException) {
// This one is odd. It is thrown when a wrong token is specified, but
// instead of getting an expected UaaException, this AbortedException is thrown instead by reactor netty.
this.lastConnectionError = deepestCause;
return new UnauthorizedException(this.paramsProviderMessages.unauthorised());
} else if (deepestCause instanceof UnknownHostException) {
this.lastConnectionError = deepestCause;
String message = ExceptionUtil.getMessage(deepestCause);
return new ConnectionException(this.paramsProviderMessages.noNetworkConnection() + " " + message);
}
protected Exception convertToCfVscodeError(Exception e) {
this.lastConnectionError = getConnectionError(e);
// return the "converted" error if it is available
if (this.lastConnectionError != null) {
return this.lastConnectionError;
}
return e;
}
protected Exception getConnectionError(Exception e) {
Throwable deepestCause = ExceptionUtil.getDeepestCause(e);
if (deepestCause instanceof UaaException || deepestCause instanceof AbortedException
|| deepestCause instanceof SocketException || deepestCause instanceof UnknownHostException) {
return new ConnectionException(this.paramsProviderMessages.noNetworkConnection());
}
return null;
}
public boolean hasConnectionError() {
return this.lastConnectionError != null;
}
}
}

View File

@@ -28,11 +28,10 @@ public class CFTargetCache {
private final CloudFoundryClientFactory clientFactory;
private final ClientTimeouts timeouts;
private final LoadingCache<ClientParamsCacheKey, CFTarget> cache;
private final CFCallableContext callableContext;
private final CFCallableContext cacheCallableContext;
public static final long SERVICES_EXPIRATION = 10;
public static final long TARGET_EXPIRATION = 1;
public CFTargetCache(ClientParamsProvider paramsProvider, CloudFoundryClientFactory clientFactory,
ClientTimeouts timeouts) {
@@ -41,7 +40,7 @@ public class CFTargetCache {
this.paramsProvider = paramsProvider;
this.clientFactory = clientFactory;
this.timeouts = timeouts;
this.callableContext = new CFCallableContext(paramsProvider.getMessages());
this.cacheCallableContext = new CFCallableContext(paramsProvider.getMessages());
CacheLoader<ClientParamsCacheKey, CFTarget> loader = new CacheLoader<ClientParamsCacheKey, CFTarget>() {
@Override
@@ -50,7 +49,8 @@ public class CFTargetCache {
}
};
cache = CacheBuilder.newBuilder().maximumSize(1).expireAfterAccess(TARGET_EXPIRATION, TimeUnit.HOURS).build(loader);
cache = CacheBuilder.newBuilder().maximumSize(1).expireAfterAccess(TARGET_EXPIRATION, TimeUnit.HOURS)
.build(loader);
}
/**
@@ -61,9 +61,9 @@ public class CFTargetCache {
* for any other error encountered
*/
public synchronized List<CFTarget> getOrCreate() throws NoTargetsException, Exception {
return callableContext.checkConnection(() -> doGetOrCreate());
return cacheCallableContext.checkConnection(() -> doGetOrCreate());
}
protected synchronized List<CFTarget> doGetOrCreate() throws NoTargetsException, Exception {
List<CFClientParams> allParams = paramsProvider.getParams();
@@ -87,7 +87,8 @@ public class CFTargetCache {
}
protected CFTarget create(CFClientParams params) throws Exception {
return new CFTarget(getTargetName(params), params, clientFactory.getClient(params, timeouts), callableContext);
return new CFTarget(getTargetName(params), params, clientFactory.getClient(params, timeouts),
new CFCallableContext(paramsProvider.getMessages()));
}
protected static String getTargetName(CFClientParams params) {
@@ -103,6 +104,4 @@ public class CFTargetCache {
return cfApiUrl;
}
}
}

View File

@@ -19,8 +19,7 @@ public final class CfCliProviderMessages implements CFParamsProviderMessages {
* longer
*/
public static final String NO_CLI_TARGETS_FOUND_MESSAGE = "No Cloud Foundry targets found: Use cf CLI to login";
public static final String UNAUTHORISED_MESSAGE = "Unauthorized access: Use cf CLI to login";
public static final String NO_NETWORK_CONNECTION = "Unable to connect to network: Verify network connection";
public static final String NO_NETWORK_CONNECTION = "No connection to Cloud Foundry: Use cf CLI to login or verify network connection";
@Override
public String noTargetsFound() {
@@ -29,7 +28,7 @@ public final class CfCliProviderMessages implements CFParamsProviderMessages {
@Override
public String unauthorised() {
return UNAUTHORISED_MESSAGE;
return NO_NETWORK_CONNECTION;
}
@Override

View File

@@ -1,23 +0,0 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
public class UnauthorizedException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public UnauthorizedException(String message) {
super(message);
}
}

View File

@@ -66,7 +66,9 @@ public class CloudFoundryClientCache {
}
public synchronized CFClientProvider getOrCreate(CFClientParams params) throws Exception {
return cache.get(ClientParamsCacheKey.from(params));
return create(params);
// Disable cache as corrupted clients may be kept due to connection or auth errors
// return cache.get(ClientParamsCacheKey.from(params));
}
protected CFClientProvider create(CFClientParams params) {

View File

@@ -18,7 +18,6 @@ import static org.mockito.Mockito.when;
import java.net.UnknownHostException;
import java.util.concurrent.Callable;
import org.cloudfoundry.uaa.UaaException;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFParamsProviderMessages;
@@ -27,11 +26,8 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTar
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfCliProviderMessages;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ConnectionException;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.UnauthorizedException;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import reactor.ipc.netty.channel.AbortedException;
public class CFClientTest {
MockCfCli cloudfoundry = new MockCfCli();
@@ -75,38 +71,6 @@ public class CFClientTest {
assertError(() -> target.getBuildpacks(), ConnectionException.class, expectedMessages.noNetworkConnection());
}
@Test
public void testAbortedExceptionServices() throws Exception {
ClientRequests client = cloudfoundry.client;
when(client.getServices()).thenThrow(new AbortedException("connection aborted"));
CFTarget target = targetCache.getOrCreate().get(0);
assertError(() -> target.getServices(), UnauthorizedException.class, expectedMessages.unauthorised());
}
@Test
public void testAbortedExceptionBuildpacks() throws Exception {
ClientRequests client = cloudfoundry.client;
when(client.getBuildpacks()).thenThrow(new AbortedException("connection aborted"));
CFTarget target = targetCache.getOrCreate().get(0);
assertError(() -> target.getBuildpacks(), UnauthorizedException.class, expectedMessages.unauthorised());
}
@Test
public void testUaaExceptionServices() throws Exception {
ClientRequests client = cloudfoundry.client;
when(client.getServices()).thenThrow(new UaaException(401, "unauthorized", "Bad credentials"));
CFTarget target = targetCache.getOrCreate().get(0);
assertError(() -> target.getServices(), UnauthorizedException.class, expectedMessages.unauthorised());
}
@Test
public void testUaaExceptionBuildpacks() throws Exception {
ClientRequests client = cloudfoundry.client;
when(client.getBuildpacks()).thenThrow(new UaaException(401, "unauthorized", "Bad credentials"));
CFTarget target = targetCache.getOrCreate().get(0);
assertError(() -> target.getBuildpacks(), UnauthorizedException.class, expectedMessages.unauthorised());
}
protected void assertError(Callable<?> callable, Class<? extends Throwable> expected, String expectedMessage)
throws Exception {
Throwable error = null;

View File

@@ -18,9 +18,8 @@ import java.util.logging.Logger;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.UnauthorizedException;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ConnectionException;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import org.springframework.ide.vscode.commons.util.ValueParseException;
@@ -86,7 +85,7 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
*/
protected Throwable getErrorNoAppending(Throwable e) {
return ExceptionUtil.findThrowable(e,
ImmutableList.of(NoTargetsException.class, ConnectionException.class, UnauthorizedException.class));
ImmutableList.of(NoTargetsException.class, ConnectionException.class));
}
/**