PT 156579665 - Improvements in handling CF targets in manifest LS
Changes to how CF targets are handled in manifest LS, including better error handling and association with a source type, like cf CLI or boot dashboard.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 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
|
||||
@@ -15,6 +15,7 @@ import java.net.UnknownHostException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.cloudfoundry.uaa.UaaException;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo.TargetDiagnosticMessages;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
|
||||
import reactor.ipc.netty.channel.AbortedException;
|
||||
@@ -25,15 +26,15 @@ import reactor.ipc.netty.channel.AbortedException;
|
||||
*/
|
||||
public class CFCallableContext {
|
||||
|
||||
private final CFParamsProviderMessages paramsProviderMessages;
|
||||
private final TargetDiagnosticMessages diagnosticMessages;
|
||||
private Exception lastConnectionError;
|
||||
private long lastErrorTime = 0;
|
||||
|
||||
public CFCallableContext(CFParamsProviderMessages paramsProviderMessages) {
|
||||
this.paramsProviderMessages = paramsProviderMessages;
|
||||
public CFCallableContext(TargetDiagnosticMessages diagnosticMessages) {
|
||||
this.diagnosticMessages = diagnosticMessages;
|
||||
}
|
||||
|
||||
public <T> T checkConnection(Callable<T> callable) throws Exception {
|
||||
public <T> T run(Callable<T> callable) throws Exception {
|
||||
this.lastConnectionError = null;
|
||||
try {
|
||||
return callable.call();
|
||||
@@ -56,9 +57,12 @@ public class CFCallableContext {
|
||||
Throwable deepestCause = ExceptionUtil.getDeepestCause(e);
|
||||
|
||||
if (deepestCause instanceof UaaException || deepestCause instanceof AbortedException
|
||||
|| deepestCause instanceof SocketException || deepestCause instanceof UnknownHostException
|
||||
&& this.paramsProviderMessages != null) {
|
||||
return new ConnectionException(this.paramsProviderMessages.noNetworkConnection());
|
||||
|| deepestCause instanceof SocketException || deepestCause instanceof UnknownHostException) {
|
||||
if (this.diagnosticMessages != null) {
|
||||
return new ConnectionException(this.diagnosticMessages.getConnectionError());
|
||||
} else {
|
||||
return new ConnectionException(CfTargetsInfoProvder.DEFAULT_MESSAGES.getConnectionError());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 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
|
||||
@@ -44,6 +44,7 @@ public class CFTarget {
|
||||
private LoadingCache<String, List<CFDomain>> domainCache;
|
||||
private LoadingCache<String, List<CFStack>> stacksCache;
|
||||
private CFCallableContext callableContext;
|
||||
|
||||
public CFTarget(String targetName, CFClientParams params, ClientRequests requests,
|
||||
CFCallableContext callableContext) {
|
||||
this.params = params;
|
||||
@@ -107,7 +108,7 @@ public class CFTarget {
|
||||
}
|
||||
|
||||
protected <T> T runAndCheckForFailure(Callable<T> callable) throws Exception {
|
||||
return callableContext.checkConnection(callable);
|
||||
return callableContext.run(callable);
|
||||
}
|
||||
|
||||
public boolean hasExpiredConnectionError() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 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
|
||||
@@ -12,57 +12,64 @@ package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientTimeouts;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CloudFoundryClientFactory;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo.TargetDiagnosticMessages;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class CFTargetCache {
|
||||
|
||||
private final CfClientConfig cfClientConfig;
|
||||
private Logger logger = LoggerFactory.getLogger(CFTargetCache.class);
|
||||
private final CloudFoundryClientFactory clientFactory;
|
||||
private final ClientTimeouts timeouts;
|
||||
private LoadingCache<ClientParamsCacheKey, CFTarget> cache;
|
||||
private CFCallableContext cacheCallableContext;
|
||||
private List<ClientParamsProvider> _providers;
|
||||
|
||||
public static final Duration SERVICES_EXPIRATION = Duration.ofSeconds(10);
|
||||
public static final Duration TARGET_EXPIRATION = Duration.ofHours(1);
|
||||
public static final Duration ERROR_EXPIRATION = Duration.ofSeconds(10);
|
||||
|
||||
public CFTargetCache(CfClientConfig cfClientConfig, CloudFoundryClientFactory clientFactory,
|
||||
public CFTargetCache(List<ClientParamsProvider> providers, CloudFoundryClientFactory clientFactory,
|
||||
ClientTimeouts timeouts) {
|
||||
Assert.isLegal(cfClientConfig != null,
|
||||
"A Cloud Foundry client parameters provider must be set when creating a target cache.");
|
||||
this.cfClientConfig = cfClientConfig;
|
||||
this.clientFactory = clientFactory;
|
||||
this.timeouts = timeouts;
|
||||
//TODO: I suspect that addClientParamsProviderChangedListener below is not necessary.
|
||||
// I think it results in unnessary refreshes of the cache, any time the providers are
|
||||
// changed. The cached results doesn't really depend on the providers, only on the targets. So I think,
|
||||
// it shouldn't need to refresh when the providers are changed.
|
||||
cfClientConfig.addClientParamsProviderChangedListener((newProvider, oldProvider) -> initCache());
|
||||
this._providers = providers;
|
||||
initCache();
|
||||
}
|
||||
|
||||
|
||||
private void initCache() {
|
||||
CacheLoader<ClientParamsCacheKey, CFTarget> loader = new CacheLoader<ClientParamsCacheKey, CFTarget>() {
|
||||
|
||||
@Override
|
||||
public CFTarget load(ClientParamsCacheKey params) throws Exception {
|
||||
return create(params.fullParams);
|
||||
public CFTarget load(ClientParamsCacheKey key) throws Exception {
|
||||
return create(key.fullParams, key.getProvider());
|
||||
}
|
||||
|
||||
};
|
||||
cache = CacheBuilder.newBuilder()./*maximumSize(1).*/expireAfterAccess(TARGET_EXPIRATION.toMillis(), TimeUnit.MILLISECONDS)
|
||||
.build(loader);
|
||||
this.cacheCallableContext = new CFCallableContext(cfClientConfig.getClientParamsProvider().getMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param providers list of providers that will be called in order.
|
||||
*/
|
||||
public synchronized void setProviders(ClientParamsProvider... providers) {
|
||||
this._providers = providers != null ? Arrays.asList(providers) : ImmutableList.of();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,39 +80,67 @@ public class CFTargetCache {
|
||||
* for any other error encountered
|
||||
*/
|
||||
public synchronized List<CFTarget> getOrCreate() throws NoTargetsException, Exception {
|
||||
return cacheCallableContext.checkConnection(() -> doGetOrCreate());
|
||||
}
|
||||
|
||||
protected synchronized List<CFTarget> doGetOrCreate() throws NoTargetsException, Exception {
|
||||
|
||||
Collection<CFClientParams> allParams = cfClientConfig.getClientParamsProvider().getParams();
|
||||
// Obtain an uptodate list of params from the providers and refresh the list of targets.
|
||||
List<CFTarget> targets = new ArrayList<>();
|
||||
if (allParams != null) {
|
||||
for (CFClientParams params : allParams) {
|
||||
ClientParamsCacheKey key = ClientParamsCacheKey.from(params);
|
||||
CFTarget target = cache.get(key);
|
||||
if (target != null) {
|
||||
// If any CF errors occurred in the target, refresh once
|
||||
if (target.hasExpiredConnectionError()) {
|
||||
cache.refresh(key);
|
||||
target = cache.get(key);
|
||||
}
|
||||
targets.add(target);
|
||||
}
|
||||
|
||||
Exception lastError = null;
|
||||
for (ClientParamsProvider provider : this._providers) {
|
||||
|
||||
// IMPORTANT: do not let errors stop iterating through all the providers.
|
||||
// If one provider cannot provide targets, try the next one.
|
||||
try {
|
||||
Collection<CFClientParams> providerParams = provider.getParams();
|
||||
getTargets(targets, provider, providerParams);
|
||||
} catch (Exception e) {
|
||||
lastError = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (targets.isEmpty() && lastError != null) {
|
||||
throw lastError;
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
|
||||
private void getTargets(List<CFTarget> targets, ClientParamsProvider provider,
|
||||
Collection<CFClientParams> providerParams) throws ExecutionException {
|
||||
for (CFClientParams params : providerParams) {
|
||||
ClientParamsCacheKey key = ClientParamsCacheKey.from(params, provider);
|
||||
CFTarget target = cache.get(key);
|
||||
if (target != null) {
|
||||
// If any CF errors occurred in the target, refresh once
|
||||
if (target.hasExpiredConnectionError()) {
|
||||
cache.refresh(key);
|
||||
target = cache.get(key);
|
||||
}
|
||||
targets.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected CFTarget create(CFClientParams params) throws Exception {
|
||||
/*
|
||||
* Must pass a NEW callable context. Cannot be
|
||||
* the same as the target cache callable context, as
|
||||
* contexts may contain error state
|
||||
*/
|
||||
return new CFTarget(getTargetName(params), params, clientFactory.getClient(params, timeouts),
|
||||
new CFCallableContext(cfClientConfig.getClientParamsProvider().getMessages()));
|
||||
public synchronized List<ClientParamsProvider> getParamsProviders() {
|
||||
return this._providers;
|
||||
}
|
||||
|
||||
|
||||
protected CFTarget create(CFClientParams params, ClientParamsProvider provider) throws Exception {
|
||||
TargetDiagnosticMessages messages = provider.getMessages();
|
||||
CFCallableContext context = createCallingContext(provider);
|
||||
|
||||
CFTarget target = new CFTarget(getTargetName(params), params, clientFactory.getClient(params, timeouts),
|
||||
context);
|
||||
if (messages != null && StringUtil.hasText(messages.getTargetSource())) {
|
||||
logger.info("Created CF target for [{}/{}], from {}", params.getOrgName(), params.getSpaceName(),
|
||||
messages.getTargetSource());
|
||||
} else {
|
||||
logger.info("Created CF target for [{}/{}]", params.getOrgName(), params.getSpaceName());
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private CFCallableContext createCallingContext(ClientParamsProvider provider) {
|
||||
return new CFCallableContext(provider.getMessages());
|
||||
}
|
||||
|
||||
protected static String getTargetName(CFClientParams params) {
|
||||
@@ -121,8 +156,4 @@ public class CFTargetCache {
|
||||
return cfApiUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public CfClientConfig getCfClientConfig() {
|
||||
return cfClientConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo.TargetDiagnosticMessages;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
@@ -37,7 +38,32 @@ public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
public static final String SPACE_FIELDS = "SpaceFields";
|
||||
public static final String NAME = "Name";
|
||||
public static final String SSL_DISABLED = "SSLDisabled";
|
||||
private CfCliProviderMessages cfCliProviderMessages = new CfCliProviderMessages();
|
||||
|
||||
public static final TargetDiagnosticMessages CLI_PROVIDER_MESSAGES = new TargetDiagnosticMessages() {
|
||||
|
||||
@Override
|
||||
public String getNoTargetsFound() {
|
||||
// Make this a "generic" message, instead of using "cf CLI" prefix as it shows general instructions when there are not targets
|
||||
return "No Cloud Foundry targets found: Use 'cf' CLI to login";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectionError() {
|
||||
return "cf CLI - Connection error: Verify connection or use 'cf' CLI to login again";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoOrgSpace() {
|
||||
return "cf CLI - No org/space selected: Use 'cf' CLI to login";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetSource() {
|
||||
return "cf CLI";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
|
||||
private static CfCliParamsProvider instance;
|
||||
@@ -81,7 +107,7 @@ public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
String orgName = (String) orgFields.get(NAME);
|
||||
String spaceName = (String) spaceFields.get(NAME);
|
||||
if (!StringUtil.hasText(orgName) || !StringUtil.hasText(spaceName)) {
|
||||
throw new NoTargetsException(getMessages().noOrgSpace());
|
||||
throw new NoTargetsException(getMessages().getNoOrgSpace());
|
||||
}
|
||||
params.add(new CFClientParams(target, null, credentials, orgName, spaceName, sslDisabled));
|
||||
}
|
||||
@@ -93,7 +119,7 @@ public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
}
|
||||
|
||||
if (params.isEmpty()) {
|
||||
throw new NoTargetsException(getMessages().noTargetsFound());
|
||||
throw new NoTargetsException(getMessages().getNoTargetsFound());
|
||||
} else {
|
||||
return params;
|
||||
}
|
||||
@@ -123,8 +149,7 @@ public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CFParamsProviderMessages getMessages() {
|
||||
return cfCliProviderMessages;
|
||||
public TargetDiagnosticMessages getMessages() {
|
||||
return CLI_PROVIDER_MESSAGES;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JSON-friendly representation of Cloud Foundry targets, used for integrations that need
|
||||
@@ -25,7 +24,7 @@ import java.util.Map;
|
||||
public class CfTargetsInfo {
|
||||
|
||||
private List<Target> cfTargets;
|
||||
private Map<String, String> cfDiagnosticMessages;
|
||||
private TargetDiagnosticMessages diagnosticMessages;
|
||||
|
||||
public List<Target> getCfTargets() {
|
||||
return cfTargets;
|
||||
@@ -35,12 +34,61 @@ public class CfTargetsInfo {
|
||||
this.cfTargets = cfTargets;
|
||||
}
|
||||
|
||||
public Map<String, String> getCfDiagnosticMessages() {
|
||||
return this.cfDiagnosticMessages;
|
||||
public TargetDiagnosticMessages getDiagnosticMessages() {
|
||||
return diagnosticMessages;
|
||||
}
|
||||
|
||||
public void setCfDiagnosticMessages(Map<String, String> cfDiagnosticMessages) {
|
||||
this.cfDiagnosticMessages = cfDiagnosticMessages;
|
||||
public void setDiagnosticMessages(TargetDiagnosticMessages diagnosticMessages) {
|
||||
this.diagnosticMessages = diagnosticMessages;
|
||||
}
|
||||
|
||||
public static class TargetDiagnosticMessages {
|
||||
|
||||
|
||||
private String noTargetsFound;
|
||||
private String connectionError;
|
||||
private String noOrgSpace;
|
||||
private String targetSource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return only when there are no targets available (e.g. cf CLI is not connected or no boot dash targets)
|
||||
*/
|
||||
public String getNoTargetsFound() {
|
||||
return noTargetsFound;
|
||||
}
|
||||
|
||||
public void setNoTargetsFound(String noTargetsFound) {
|
||||
this.noTargetsFound = noTargetsFound;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return error if any existing target cannot connect.
|
||||
*/
|
||||
public String getConnectionError() {
|
||||
return connectionError;
|
||||
}
|
||||
|
||||
public void setConnectionError(String connectionError) {
|
||||
this.connectionError = connectionError;
|
||||
}
|
||||
|
||||
public String getNoOrgSpace() {
|
||||
return noOrgSpace;
|
||||
}
|
||||
|
||||
public void setNoOrgSpace(String noOrgSpace) {
|
||||
this.noOrgSpace = noOrgSpace;
|
||||
}
|
||||
|
||||
public String getTargetSource() {
|
||||
return targetSource;
|
||||
}
|
||||
|
||||
public void setTargetSource(String targetSource) {
|
||||
this.targetSource = targetSource;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Target {
|
||||
@@ -66,7 +114,7 @@ public class CfTargetsInfo {
|
||||
public void setOrg(String org) {
|
||||
this.org = org;
|
||||
}
|
||||
|
||||
|
||||
public void setSpace(String space) {
|
||||
this.space = space;
|
||||
}
|
||||
@@ -90,5 +138,10 @@ public class CfTargetsInfo {
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Target [api=" + api + ", org=" + org + ", space=" + space + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo.TargetDiagnosticMessages;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
@@ -33,19 +33,31 @@ import com.google.common.base.Suppliers;
|
||||
public class CfTargetsInfoProvder implements ClientParamsProvider {
|
||||
|
||||
private static final String NO_TARGETS_FOUND_MESSAGE = "No targets found";
|
||||
private static final String NO_NETWORK_CONNECTION = "No connection to Cloud Foundry";
|
||||
public static final String NO_NETWORK_CONNECTION = "No connection to Cloud Foundry";
|
||||
private static final String NO_ORG_SPACE = "No org/space selected";
|
||||
|
||||
private static final String PROP_NO_TARGETS_FOUND = "noTargetsFound";
|
||||
private static final String PROP_UNAUTHORISED = "unauthorised";
|
||||
private static final String PROP_NO_NETWORK_CONNECTION = "noNetworkConnection";
|
||||
private static final String PROP_NO_ORG_SPACE = "noOrgSpace";
|
||||
|
||||
public static final TargetDiagnosticMessages DEFAULT_MESSAGES = new TargetDiagnosticMessages() {
|
||||
|
||||
@Override
|
||||
public String getNoTargetsFound() {
|
||||
return NO_TARGETS_FOUND_MESSAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectionError() {
|
||||
return NO_NETWORK_CONNECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoOrgSpace() {
|
||||
return NO_ORG_SPACE;
|
||||
}
|
||||
};
|
||||
|
||||
private Supplier<Collection<CFClientParams>> paramsSupplier;
|
||||
private Map<String, String> messages;
|
||||
|
||||
private TargetDiagnosticMessages messages;
|
||||
|
||||
public CfTargetsInfoProvder(CfTargetsInfo targetsInfo) {
|
||||
this.messages = targetsInfo.getCfDiagnosticMessages();
|
||||
this.messages = targetsInfo.getDiagnosticMessages();
|
||||
this.paramsSupplier = Suppliers.memoize(() -> targetsInfo.getCfTargets()
|
||||
.stream()
|
||||
.map(t -> parseCfClientParams(t))
|
||||
@@ -57,7 +69,7 @@ public class CfTargetsInfoProvder implements ClientParamsProvider {
|
||||
public Collection<CFClientParams> getParams() throws NoTargetsException, ExecutionException {
|
||||
Collection<CFClientParams> params = paramsSupplier.get();
|
||||
if (params == null || params.isEmpty()) {
|
||||
throw new NoTargetsException(getMessages().noTargetsFound());
|
||||
throw new NoTargetsException(getMessages().getNoTargetsFound());
|
||||
}
|
||||
return params;
|
||||
}
|
||||
@@ -79,42 +91,7 @@ public class CfTargetsInfoProvder implements ClientParamsProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CFParamsProviderMessages getMessages() {
|
||||
return new CFParamsProviderMessages() {
|
||||
|
||||
@Override
|
||||
public String noTargetsFound() {
|
||||
if (messages != null && messages.containsKey(PROP_NO_TARGETS_FOUND)) {
|
||||
return messages.get(PROP_NO_TARGETS_FOUND);
|
||||
}
|
||||
return NO_TARGETS_FOUND_MESSAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String unauthorised() {
|
||||
if (messages != null && messages.containsKey(PROP_UNAUTHORISED)) {
|
||||
return messages.get(PROP_UNAUTHORISED);
|
||||
}
|
||||
return NO_NETWORK_CONNECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String noNetworkConnection() {
|
||||
if (messages != null && messages.containsKey(PROP_NO_NETWORK_CONNECTION)) {
|
||||
return messages.get(PROP_NO_NETWORK_CONNECTION);
|
||||
}
|
||||
return NO_NETWORK_CONNECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String noOrgSpace() {
|
||||
if (messages != null && messages.containsKey(PROP_NO_ORG_SPACE)) {
|
||||
return messages.get(PROP_NO_ORG_SPACE);
|
||||
}
|
||||
return NO_ORG_SPACE;
|
||||
}
|
||||
|
||||
};
|
||||
public TargetDiagnosticMessages getMessages() {
|
||||
return messages != null ? messages : DEFAULT_MESSAGES;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,15 +19,23 @@ package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
public class ClientParamsCacheKey {
|
||||
|
||||
public final CFClientParams fullParams;
|
||||
private final ClientParamsProvider provider;
|
||||
|
||||
/**
|
||||
* Use static API to create: {@link #from(CFClientParams)}
|
||||
* @param fullParams
|
||||
*/
|
||||
private ClientParamsCacheKey(CFClientParams fullParams) {
|
||||
private ClientParamsCacheKey(CFClientParams fullParams, ClientParamsProvider provider) {
|
||||
this.fullParams = fullParams;
|
||||
|
||||
// Not used in evaluating key equality. It's passed into the key because when a
|
||||
// target is created from this key, it requires a provider context. See the CFTargetCache
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public ClientParamsProvider getProvider() {
|
||||
return this.provider;
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
@@ -100,11 +108,9 @@ public class ClientParamsCacheKey {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ClientParamsCacheKey from(CFClientParams params) {
|
||||
return new ClientParamsCacheKey(params);
|
||||
|
||||
public static ClientParamsCacheKey from(CFClientParams params, ClientParamsProvider provider) {
|
||||
return new ClientParamsCacheKey(params, provider);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 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
|
||||
@@ -13,6 +13,8 @@ package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo.TargetDiagnosticMessages;
|
||||
|
||||
public interface ClientParamsProvider {
|
||||
|
||||
/**
|
||||
@@ -23,6 +25,7 @@ public interface ClientParamsProvider {
|
||||
*/
|
||||
Collection<CFClientParams> getParams() throws NoTargetsException, ExecutionException;
|
||||
|
||||
CFParamsProviderMessages getMessages();
|
||||
TargetDiagnosticMessages getMessages();
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 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
|
||||
@@ -18,13 +18,14 @@ 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.mockito.Mockito;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFParamsProviderMessages;
|
||||
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.CfCliProviderMessages;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfCliParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo.TargetDiagnosticMessages;
|
||||
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.ExceptionUtil;
|
||||
@@ -36,19 +37,19 @@ public class CFClientTest {
|
||||
MockCfCli cloudfoundry = new MockCfCli();
|
||||
ClientTimeouts timeouts = new ClientTimeouts();
|
||||
CFTargetCache targetCache;
|
||||
CFParamsProviderMessages expectedMessages = new CfCliProviderMessages();
|
||||
TargetDiagnosticMessages expectedMessages = CfCliParamsProvider.CLI_PROVIDER_MESSAGES;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
targetCache = new CFTargetCache(cloudfoundry.cfClientConfig, cloudfoundry.factory, timeouts);
|
||||
targetCache = new CFTargetCache(ImmutableList.of(cloudfoundry.paramsProvider), cloudfoundry.factory, timeouts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoTarget() throws Exception {
|
||||
|
||||
when(cloudfoundry.paramsProvider.getParams())
|
||||
.thenThrow(new NoTargetsException(expectedMessages.noTargetsFound()));
|
||||
assertError(() -> targetCache.getOrCreate(), NoTargetsException.class, expectedMessages.noTargetsFound());
|
||||
.thenThrow(new NoTargetsException(expectedMessages.getNoTargetsFound()));
|
||||
assertError(() -> targetCache.getOrCreate(), NoTargetsException.class, expectedMessages.getNoTargetsFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,7 +64,7 @@ public class CFClientTest {
|
||||
ClientRequests client = cloudfoundry.client;
|
||||
when(client.getServices()).thenThrow(new UnknownHostException("api.run.pivotal.io"));
|
||||
CFTarget target = targetCache.getOrCreate().get(0);
|
||||
assertError(() -> target.getServices(), ConnectionException.class, expectedMessages.noNetworkConnection());
|
||||
assertError(() -> target.getServices(), ConnectionException.class, expectedMessages.getConnectionError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,7 +72,7 @@ public class CFClientTest {
|
||||
ClientRequests client = cloudfoundry.client;
|
||||
when(client.getBuildpacks()).thenThrow(new UnknownHostException("api.run.pivotal.io"));
|
||||
CFTarget target = targetCache.getOrCreate().get(0);
|
||||
assertError(() -> target.getBuildpacks(), ConnectionException.class, expectedMessages.noNetworkConnection());
|
||||
assertError(() -> target.getBuildpacks(), ConnectionException.class, expectedMessages.getConnectionError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,7 +80,16 @@ public class CFClientTest {
|
||||
ClientRequests client = cloudfoundry.client;
|
||||
when(client.getDomains()).thenThrow(new UnknownHostException("api.run.pivotal.io"));
|
||||
CFTarget target = targetCache.getOrCreate().get(0);
|
||||
assertError(() -> target.getDomains(), ConnectionException.class, expectedMessages.noNetworkConnection());
|
||||
assertError(() -> target.getDomains(), ConnectionException.class, expectedMessages.getConnectionError());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidRefreshToken() throws Exception {
|
||||
ClientRequests client = cloudfoundry.client;
|
||||
String mockedError = "org.cloudfoundry.uaa.UaaException: invalid_token: Invalid refresh token expired at Wed Mar 28 18:58:20 UTC 2018";
|
||||
when(client.getDomains()).thenThrow(new UaaException(1111, mockedError, mockedError));
|
||||
CFTarget target = targetCache.getOrCreate().get(0);
|
||||
assertError(() -> target.getDomains(), ConnectionException.class, expectedMessages.getConnectionError());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 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
|
||||
@@ -15,12 +15,9 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CloudFoundryClientFactory;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFCredentials;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfCliProviderMessages;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfClientConfig;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfCliParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ClientParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
|
||||
@@ -33,18 +30,16 @@ public class MockCfCli {
|
||||
|
||||
public final CloudFoundryClientFactory factory = mock(CloudFoundryClientFactory.class);
|
||||
public final ClientRequests client = mock(ClientRequests.class);
|
||||
public final CfClientConfig cfClientConfig = CfClientConfig.createDefault();
|
||||
public final ClientParamsProvider paramsProvider = mock(ClientParamsProvider.class);
|
||||
public final CfCliProviderMessages actualCfCliMessages = new CfCliProviderMessages();
|
||||
|
||||
|
||||
public MockCfCli() {
|
||||
try {
|
||||
cfClientConfig.setClientParamsProvider(paramsProvider);
|
||||
//program some default behavior into mocks... most tests will use this.
|
||||
//other tests should 'reset' the mocks and reprogram them as needed.
|
||||
when(factory.getClient(any(), any())).thenReturn(client);
|
||||
when(paramsProvider.getParams()).thenReturn(ImmutableList.of(DEFAULT_PARAMS));
|
||||
when(paramsProvider.getMessages()).thenReturn(actualCfCliMessages);
|
||||
when(paramsProvider.getMessages()).thenReturn(CfCliParamsProvider.CLI_PROVIDER_MESSAGES);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw ExceptionUtil.unchecked(e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2018 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
|
||||
@@ -15,6 +15,8 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.ConnectionException;
|
||||
@@ -29,7 +31,10 @@ import com.google.common.collect.ImmutableList;
|
||||
public abstract class AbstractCFHintsProvider implements Callable<Collection<YValueHint>> {
|
||||
|
||||
public static final String EMPTY_VALUE = "";
|
||||
public static final String PROBLEM_RESOLVING_FROM_TARGETS = "Unable to resolve hints from: ";
|
||||
|
||||
protected final CFTargetCache targetCache;
|
||||
private Logger logger = LoggerFactory.getLogger(AbstractCFHintsProvider.class);
|
||||
|
||||
public AbstractCFHintsProvider(CFTargetCache targetCache) {
|
||||
Assert.isNotNull(targetCache);
|
||||
@@ -59,12 +64,10 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
// resolving the error message. Instead, log the full error, and
|
||||
// only throw a
|
||||
// new exception with a "nicer" message
|
||||
Throwable errorNoAppending = getErrorNoAppending(e);
|
||||
if (errorNoAppending != null) {
|
||||
// Do not log the no-targets exception as it may be encountered
|
||||
// frequently
|
||||
// if a user does not have a CF client installed
|
||||
throw new ValueParseException(ExceptionUtil.getMessageNoAppendedInformation(errorNoAppending));
|
||||
Throwable targetErrors = getErrorOfType(e, ImmutableList.of(NoTargetsException.class, ConnectionException.class));
|
||||
if (targetErrors != null) {
|
||||
// This error may appear in the UI (e.g. hover pop-up) so only show the error message , not the full error with stack trace
|
||||
throw new ValueParseException(ExceptionUtil.getMessageNoAppendedInformation(targetErrors));
|
||||
} else {
|
||||
// Log any other error
|
||||
//logger.log(Level.SEVERE, ExceptionUtil.getMessage(e), e);
|
||||
@@ -80,9 +83,9 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
* @return an error that requires no additional information when showing its
|
||||
* message, or null if no such error is found
|
||||
*/
|
||||
protected Throwable getErrorNoAppending(Throwable e) {
|
||||
protected Throwable getErrorOfType(Throwable e, List<Class<? extends Throwable>> toLookFor) {
|
||||
return ExceptionUtil.findThrowable(e,
|
||||
ImmutableList.of(NoTargetsException.class, ConnectionException.class));
|
||||
toLookFor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,20 +100,31 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
}
|
||||
List<YValueHint> hints = new ArrayList<>();
|
||||
boolean validTargetsPresent = false;
|
||||
Exception lastErrorEncountered = null;
|
||||
|
||||
for (CFTarget cfTarget : targets) {
|
||||
try {
|
||||
// TODO: check if duplicate proposals can be the list of all hints. Duplicates don't seem to cause duplicate proposals. Verify this!
|
||||
getHints(cfTarget).stream().filter(hint -> !hints.contains(hint)).forEach(hint -> hints.add(hint));
|
||||
validTargetsPresent = true;
|
||||
} catch (Exception e) {
|
||||
// Drop individual target error
|
||||
// PT 156579665 - Log the Connection exceptions, as it means there are existing targets that have connection errors
|
||||
// and this information could be useful to the user,
|
||||
// but don't log the "NoTarget" errors, as they may be logged frequently and dont necessarily indicate an issue (e.g. cf CLI is not installed).
|
||||
Throwable connectionError = getErrorOfType(e, ImmutableList.of(ConnectionException.class));
|
||||
if (connectionError != null) {
|
||||
logger.error("{}", ExceptionUtil.getMessageNoAppendedInformation(connectionError));
|
||||
}
|
||||
lastErrorEncountered = e;
|
||||
}
|
||||
}
|
||||
|
||||
if (validTargetsPresent) {
|
||||
return hints;
|
||||
} else if (lastErrorEncountered != null){
|
||||
throw lastErrorEncountered;
|
||||
} else {
|
||||
throw new ConnectionException(
|
||||
targetCache.getCfClientConfig().getClientParamsProvider().getMessages().noNetworkConnection());
|
||||
throw new ConnectionException(PROBLEM_RESOLVING_FROM_TARGETS + " " + targets.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2016, 2018 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
|
||||
@@ -10,26 +10,18 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.manifest.yaml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientTimeouts;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CloudFoundryClientFactory;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFParamsProviderMessages;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfCliParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfClientConfig;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfoProvder;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo.Target;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfoProvder;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ClientParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
|
||||
@@ -38,7 +30,6 @@ import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProv
|
||||
import org.springframework.ide.vscode.commons.languageserver.hover.VscodeHoverEngineAdapter;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService;
|
||||
@@ -61,9 +52,6 @@ import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
|
||||
@@ -71,9 +59,6 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
private CfJson cfJson = new CfJson();
|
||||
private ManifestYmlSchema schema;
|
||||
private CFTargetCache cfTargetCache;
|
||||
private final CloudFoundryClientFactory cfClientFactory;
|
||||
private final CfClientConfig cfClientConfig;
|
||||
private final Logger log = LoggerFactory.getLogger(ManifestYamlLanguageServer.class);
|
||||
|
||||
private final ImmutableSet<LanguageId> FALLBACK_YML_IDS = ImmutableSet.of(LanguageId.of("yml"), LanguageId.of("yaml"));
|
||||
final private ClientParamsProvider defaultClientParamsProvider;
|
||||
@@ -84,9 +69,10 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
|
||||
public ManifestYamlLanguageServer(CloudFoundryClientFactory cfClientFactory, ClientParamsProvider defaultClientParamsProvider) {
|
||||
super("vscode-manifest-yaml");
|
||||
this.cfClientFactory = cfClientFactory;
|
||||
this.cfClientConfig=CfClientConfig.createDefault();
|
||||
this.defaultClientParamsProvider = defaultClientParamsProvider;
|
||||
|
||||
this.cfTargetCache = new CFTargetCache(ImmutableList.of(this.defaultClientParamsProvider), cfClientFactory, new ClientTimeouts());
|
||||
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
SimpleWorkspaceService workspace = getWorkspaceService();
|
||||
|
||||
@@ -144,52 +130,11 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
});
|
||||
}
|
||||
|
||||
public CfClientConfig getCfClientConfig() {
|
||||
return cfClientConfig;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void applyCfLoginParameterSettings(CfTargetsInfo info) {
|
||||
List<Target> cfTargets = info.getCfTargets();
|
||||
if (cfTargets != null) {
|
||||
|
||||
CfTargetsInfoProvder cfClientParamsProvider = new CfTargetsInfoProvder(info);
|
||||
|
||||
cfClientConfig.setClientParamsProvider(new ClientParamsProvider() {
|
||||
|
||||
@Override
|
||||
public Collection<CFClientParams> getParams() throws NoTargetsException, ExecutionException {
|
||||
List<ClientParamsProvider> providers = ImmutableList.of(defaultClientParamsProvider, cfClientParamsProvider);
|
||||
|
||||
List<CFClientParams> params = new ArrayList<>();
|
||||
|
||||
for (ClientParamsProvider provider : providers) {
|
||||
try {
|
||||
params.addAll(provider.getParams());
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
if (params.isEmpty()) {
|
||||
throw new NoTargetsException(getMessages().noTargetsFound());
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CFParamsProviderMessages getMessages() {
|
||||
return cfTargets.isEmpty() ? defaultClientParamsProvider.getMessages()
|
||||
: cfClientParamsProvider.getMessages();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Refresh the list of providers
|
||||
CfTargetsInfoProvder cfClientParamsProvider = new CfTargetsInfoProvder(info);
|
||||
// set providers in the order that they should be called
|
||||
cfTargetCache.setProviders(defaultClientParamsProvider, cfClientParamsProvider);
|
||||
}
|
||||
|
||||
private void validateOnDocumentChange(IReconcileEngine engine, TextDocument doc) {
|
||||
@@ -235,15 +180,11 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
}
|
||||
|
||||
private CFTargetCache getCfTargetCache() {
|
||||
if (cfTargetCache == null) {
|
||||
// Init CF client params provider if it's initilized
|
||||
if (cfClientConfig.getClientParamsProvider() == null) {
|
||||
cfClientConfig.setClientParamsProvider(defaultClientParamsProvider );
|
||||
}
|
||||
CloudFoundryClientFactory clientFactory = cfClientFactory;
|
||||
cfTargetCache = new CFTargetCache(cfClientConfig, clientFactory, new ClientTimeouts());
|
||||
}
|
||||
return cfTargetCache;
|
||||
return this.cfTargetCache;
|
||||
}
|
||||
|
||||
public List<ClientParamsProvider> getParamsProvider() {
|
||||
return cfTargetCache.getParamsProviders();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,11 +22,12 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientTimeouts
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CloudFoundryClientFactory;
|
||||
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.CfClientConfig;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfo;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfTargetsInfoProvder;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class ManifestYamlActualCfClientTest {
|
||||
|
||||
private CFTargetCache cfTargetCache;
|
||||
@@ -37,9 +38,8 @@ public class ManifestYamlActualCfClientTest {
|
||||
cfJson = new CfJson();
|
||||
CfTargetsInfo info = getTargetsInfoFromEnv();
|
||||
CfTargetsInfoProvder provider = new CfTargetsInfoProvder(info);
|
||||
CfClientConfig cfClientConfig = CfClientConfig.createDefault(provider);
|
||||
CloudFoundryClientFactory clientFactory = DefaultCloudFoundryClientFactoryV2.INSTANCE;
|
||||
cfTargetCache = new CFTargetCache(cfClientConfig, clientFactory, new ClientTimeouts());
|
||||
cfTargetCache = new CFTargetCache(ImmutableList.of(provider), clientFactory, new ClientTimeouts());
|
||||
}
|
||||
|
||||
private CfTargetsInfo getTargetsInfoFromEnv() {
|
||||
|
||||
@@ -18,19 +18,21 @@ import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.DidChangeConfigurationParams;
|
||||
import org.eclipse.lsp4j.InitializeResult;
|
||||
import org.eclipse.lsp4j.TextDocumentSyncKind;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ClientParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
|
||||
public class ManifestYamlLanguageServerTest {
|
||||
|
||||
@@ -99,20 +101,30 @@ public class ManifestYamlLanguageServerTest {
|
||||
);
|
||||
harness.intialize(null);
|
||||
|
||||
assertEquals(1, manifestYamlLanguageServer.getCfClientConfig().getClientParamsProvider().getParams().size());
|
||||
// This is an initial target, for example from cf CLI
|
||||
assertEquals(1, getAllParams(manifestYamlLanguageServer.getParamsProvider()).size());
|
||||
assertEquals(Arrays.asList("test.io"), manifestYamlLanguageServer.getCfTargets());
|
||||
|
||||
// This tests a change in workspace (e.g. boot dash) that results in two more targets created.
|
||||
DidChangeConfigurationParams params = new DidChangeConfigurationParams();
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
params.setSettings(parser.parse(new InputStreamReader(getClass().getResourceAsStream("/cf-targets1.json")))
|
||||
);
|
||||
params.setSettings(parser.parse(new InputStreamReader(getClass().getResourceAsStream("/cf-targets1.json"))));
|
||||
|
||||
manifestYamlLanguageServer.getWorkspaceService().didChangeConfiguration(params);
|
||||
assertEquals(3, manifestYamlLanguageServer.getCfClientConfig().getClientParamsProvider().getParams().size());
|
||||
assertEquals(3, getAllParams(manifestYamlLanguageServer.getParamsProvider()).size());
|
||||
|
||||
// End result should have the initial target as well as the two additional targets obtained on workspace change
|
||||
assertEquals(Arrays.asList("test.io", "api.system.demo-gcp.springapps.io", "api.run.pivotal.io"), manifestYamlLanguageServer.getCfTargets());
|
||||
}
|
||||
|
||||
|
||||
private List<CFClientParams> getAllParams(List<ClientParamsProvider> providers) throws Exception {
|
||||
List<CFClientParams> all = new ArrayList<>();
|
||||
for (ClientParamsProvider clientParamsProvider : providers) {
|
||||
Collection<CFClientParams> params = clientParamsProvider.getParams();
|
||||
all.addAll(params);
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user