Added caching of services, buildpacks and targets using guava caching

This commit is contained in:
nsingh
2017-01-16 16:57:27 -08:00
parent 9519a790fe
commit 1abda9aedf
13 changed files with 401 additions and 307 deletions

View File

@@ -53,6 +53,11 @@ public class CFClientParams {
this.orgName = orgName;
this.spaceName = spaceName;
}
public CFClientParams(String apiUrl, String username, CFCredentials credentials, boolean skipSslValidation) {
this(apiUrl, username, credentials, null /* no org */,
null /* no space */, skipSslValidation);
}
public CFCredentials getCredentials() {
return credentials;

View File

@@ -11,12 +11,17 @@
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.ClientRequests;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
*
* Wrapper around a {@link ClientRequests} that may contain cached information
@@ -32,28 +37,50 @@ public class CFTarget {
/*
* Cached information
*/
private List<CFBuildpack> buildpacks;
private final static Logger logger = Logger.getLogger(CFTarget.class.getName());
private final LoadingCache<String, List<CFBuildpack>> buildpacksCache;
private final LoadingCache<String, List<CFServiceInstance>> servicesCache;
public CFTarget(CFClientParams params, ClientRequests requests, String targetName) {
public CFTarget(String targetName, CFClientParams params, ClientRequests requests) {
this.params = params;
this.requests = requests;
this.targetName = targetName;
CacheLoader<String, List<CFServiceInstance>> servicesLoader = new CacheLoader<String, List<CFServiceInstance>>() {
@Override
public List<CFServiceInstance> load(String key) throws Exception {
/*
* Ignore the key. Not used.
*/
return requests.getServices();
}
};
this.servicesCache = CacheBuilder.newBuilder()
.expireAfterAccess(CFTargetCache.EXPIRATION_20_SECS, TimeUnit.SECONDS).build(servicesLoader);
CacheLoader<String, List<CFBuildpack>> buildpacksLoader = new CacheLoader<String, List<CFBuildpack>>() {
@Override
public List<CFBuildpack> load(String key) throws Exception {
/*
* Ignore the key. Not used.
*/
return requests.getBuildpacks();
}
};
this.buildpacksCache = CacheBuilder.newBuilder()
.expireAfterAccess(CFTargetCache.EXPIRATION_1_HOUR, TimeUnit.HOURS).build(buildpacksLoader);
}
public CFClientParams getParams() {
return params;
}
public List<CFBuildpack> getBuildpacks() {
if (buildpacks == null) {
try {
buildpacks = getClientRequests().getBuildpacks();
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
return buildpacks;
public List<CFBuildpack> getBuildpacks() throws ExecutionException {
return this.buildpacksCache.get(getName());
}
public List<CFServiceInstance> getServices() throws ExecutionException {
return this.servicesCache.get(getName());
}
public ClientRequests getClientRequests() {

View File

@@ -0,0 +1,95 @@
/*******************************************************************************
* 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;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.ClientTimeouts;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.CloudFoundryClientFactory;
import org.springframework.ide.vscode.commons.util.Assert;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
public class CFTargetCache {
private final ClientParamsProvider paramsProvider;
private final CloudFoundryClientFactory clientFactory;
private final ClientTimeouts timeouts;
private final LoadingCache<CFClientParams, CFTarget> cache;
public static final long EXPIRATION_20_SECS = 20;
public static final long EXPIRATION_1_HOUR = 1;
public CFTargetCache(ClientParamsProvider paramsProvider, CloudFoundryClientFactory clientFactory,
ClientTimeouts timeouts) {
Assert.isLegal(paramsProvider != null,
"A Cloud Foundry client parameters provider must be set when creating a target cache.");
this.paramsProvider = paramsProvider;
this.clientFactory = clientFactory;
this.timeouts = timeouts;
CacheLoader<CFClientParams, CFTarget> loader = new CacheLoader<CFClientParams, CFTarget>() {
@Override
public CFTarget load(CFClientParams params) throws Exception {
return create(params);
}
};
cache = CacheBuilder.newBuilder().expireAfterAccess(EXPIRATION_1_HOUR, TimeUnit.HOURS).build(loader);
}
/**
* @return non-null list of targets, or throws exception if no targets found
* @throws Exception if no targets found, or error in resolving targets
*/
public synchronized List<CFTarget> getOrCreate() throws Exception {
List<CFClientParams> allParams = paramsProvider.getParams();
List<CFTarget> targets = new ArrayList<>();
if (allParams != null) {
for (CFClientParams params : allParams) {
CFTarget target = cache.get(params);
if (target != null) {
targets.add(target);
}
}
}
if (targets.isEmpty()) {
throw new ExecutionException(new Error(paramsProvider.noParamsAvailableMessage()));
}
return targets;
}
protected CFTarget create(CFClientParams params) throws Exception {
return new CFTarget(getTargetName(params), params, clientFactory.getClient(params, timeouts));
}
protected static String getTargetName(CFClientParams params) {
return labelFromCfApi(params.getApiUrl());
}
protected static String labelFromCfApi(String cfApiUrl) {
if (cfApiUrl.startsWith("https://")) {
return cfApiUrl.substring("https://".length());
} else if (cfApiUrl.startsWith("http://")) {
return cfApiUrl.substring("http://".length());
} else {
return cfApiUrl;
}
}
}

View File

@@ -1,72 +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;
import java.util.ArrayList;
import java.util.List;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.ClientRequests;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.ClientTimeouts;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.CloudFoundryClientFactory;
/**
* Creates targets given a client parameters provider and a client factory.
*
*/
public class CFTargetsFactory {
private final CloudFoundryClientFactory clientFactory;
private final ClientParamsProvider paramsProvider;
private final ClientTimeouts timeouts;
public CFTargetsFactory(ClientParamsProvider paramsProvider, CloudFoundryClientFactory clientFactory, ClientTimeouts timeouts) {
this.clientFactory = clientFactory;
this.paramsProvider = paramsProvider;
this.timeouts = timeouts;
}
/**
*
* @return up-to-date list of CF targets.
* @throws Exception
*/
public List<CFTarget> getTargets() throws Exception {
List<CFClientParams> allParams = paramsProvider.getParams();
List<CFTarget> targets = new ArrayList<>();
if (allParams != null) {
for (CFClientParams parameters : allParams) {
ClientRequests requests = clientFactory.getClient(parameters, timeouts);
if (requests != null) {
targets.add(new CFTarget(parameters, requests, getTargetName(parameters)));
}
}
}
return targets;
}
public String noTargetsMessage() {
return paramsProvider.noParamsAvailableMessage();
}
protected String getTargetName(CFClientParams params) {
return labelFromCfApi(params.getApiUrl());
}
public static String labelFromCfApi(String cfApiUrl) {
if (cfApiUrl.startsWith("https://")) {
return cfApiUrl.substring("https://".length());
} else if (cfApiUrl.startsWith("http://")) {
return cfApiUrl.substring("http://".length());
} else {
return cfApiUrl;
}
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Pivotal, Inc.
* Copyright (c) 2016, 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
@@ -41,26 +41,18 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.CFStack;
import com.google.common.collect.ImmutableList;
/**
* Various helper methods to 'wrap' objects returned by CF client into
* our own types, so that we do not directly expose library types to our
* code.
* Various helper methods to 'wrap' objects returned by CF client into our own
* types, so that we do not directly expose library types to our code.
*
* @author Kris De Volder
*/
public class CFWrappingV2 {
private static final Logger logger = Logger.getLogger(DefaultClientRequestsV2.class.getName());
private static final Logger logger = Logger.getLogger(DefaultClientRequestsV2.class.getName());
public static CFBuildpack wrap(BuildpackResource rsrc) {
String name = rsrc.getEntity().getName();
return new CFBuildpack() {
@Override
public String getName() {
return name;
}
};
return new CFBuildpackImpl(name);
}
public static CFApplicationDetail wrap(ApplicationDetail details, ApplicationExtras extras) {
@@ -191,43 +183,8 @@ public class CFWrappingV2 {
);
}
public static CFServiceInstance wrap(final ServiceInstance service) {
return new CFServiceInstance() {
@Override
public String getName() {
return service.getName();
}
@Override
public String getPlan() {
return service.getPlan();
}
@Override
public String getDashboardUrl() {
return service.getDashboardUrl();
}
@Override
public String getService() {
if (service.getType()==ServiceInstanceType.USER_PROVIDED) {
return "user-provided";
} else {
return service.getService();
}
}
@Override
public String getDescription() {
return service.getDescription();
}
@Override
public String getDocumentationUrl() {
return service.getDocumentationUrl();
}
};
public static CFServiceInstance wrap(ServiceInstance service) {
return new CFServiceInstanceImpl(service);
}
public static CFAppState wrapAppState(String s) {
@@ -276,12 +233,154 @@ public class CFWrappingV2 {
}
public static CFBuildpack buildpack(String name) {
return new CFBuildpack() {
@Override
public String getName() {
return name;
}
};
return new CFBuildpackImpl(name);
}
public static class CFBuildpackImpl implements CFBuildpack {
private final String name;
public CFBuildpackImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CFBuildpackImpl other = (CFBuildpackImpl) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public static class CFServiceInstanceImpl implements CFServiceInstance {
private final String name;
private final String plan;
private final String dashboardUrl;
private final String service;
private final String description;
private final String documentationUrl;
public CFServiceInstanceImpl(ServiceInstance serviceInstance) {
this.name = serviceInstance.getName();
this.plan = serviceInstance.getPlan();
this.dashboardUrl = serviceInstance.getDashboardUrl();
this.service = serviceInstance.getType() == ServiceInstanceType.USER_PROVIDED ? "user-provided"
: serviceInstance.getService();
this.description = serviceInstance.getDescription();
this.documentationUrl = serviceInstance.getDocumentationUrl();
}
@Override
public String getName() {
return this.name;
}
@Override
public String getPlan() {
return this.plan;
}
@Override
public String getDashboardUrl() {
return this.dashboardUrl;
}
@Override
public String getService() {
return this.service;
}
@Override
public String getDescription() {
return this.description;
}
@Override
public String getDocumentationUrl() {
return this.documentationUrl;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dashboardUrl == null) ? 0 : dashboardUrl.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((documentationUrl == null) ? 0 : documentationUrl.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((plan == null) ? 0 : plan.hashCode());
result = prime * result + ((service == null) ? 0 : service.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CFServiceInstanceImpl other = (CFServiceInstanceImpl) obj;
if (dashboardUrl == null) {
if (other.dashboardUrl != null)
return false;
} else if (!dashboardUrl.equals(other.dashboardUrl))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (documentationUrl == null) {
if (other.documentationUrl != null)
return false;
} else if (!documentationUrl.equals(other.documentationUrl))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (plan == null) {
if (other.plan != null)
return false;
} else if (!plan.equals(other.plan))
return false;
if (service == null) {
if (other.service != null)
return false;
} else if (!service.equals(other.service))
return false;
return true;
}
}
}

View File

@@ -29,6 +29,9 @@ import reactor.core.publisher.Mono;
public interface ClientRequests {
List<CFBuildpack> getBuildpacks() throws Exception;
List<CFServiceInstance> getServices() throws Exception;
// /**
// * The actual Rest API version that cloud controller claims to be.
// */
@@ -38,48 +41,47 @@ public interface ClientRequests {
// * The minimum version that the CF V2 java client claims to support.
// */
// Version getSupportedApiVersion();
/**
* Returns null if the application does not exist. Throws some kind of Exception if there's any other kind of problem.
*/
CFApplicationDetail getApplication(String appName) throws Exception;
//TODO: consider removing the getXXXSupport method and directly adding the apis that these support
// objects provide.
SshClientSupport getSshClientSupport() throws Exception;
void deleteApplication(String name) throws Exception;
void logout();
List<CFApplication> getApplicationsWithBasicInfo() throws Exception;
List<CFBuildpack> getBuildpacks() throws Exception;
List<CFCloudDomain> getDomains() throws Exception;
List<CFServiceInstance> getServices() throws Exception;
List<CFSpace> getSpaces() throws Exception;
List<CFStack> getStacks() throws Exception;
void restartApplication(String appName, CancelationToken token) throws Exception;
void stopApplication(String appName) throws Exception;
Flux<CFApplicationDetail> getApplicationDetails(List<CFApplication> appsToLookUp) throws Exception;
String getHealthCheck(UUID appGuid) throws Exception;
void setHealthCheck(UUID guid, String hcType) throws Exception;
boolean applicationExists(String appName) throws Exception;
//Removed in V2
//void createApplication(CloudApplicationDeploymentProperties deploymentProperties) throws Exception;
//Added since v2:
void push(CFPushArguments args, CancelationToken cancelationToken) throws Exception;
Map<String, String> getApplicationEnvironment(String appName) throws Exception;
Mono<Void> deleteServiceAsync(String serviceName);
/**
* Gets current value of the client's refresh token. Note that the token is only set once it is known.
* Initially, if a client is created via password auth, then the refreshToken won't be known until
* some operation has been executed.
*
* @return Refresh token if it is already known, null otherwise.
*/
String getRefreshToken();
Mono<String> getUserName();
//
// /**
// * Returns null if the application does not exist. Throws some kind of Exception if there's any other kind of problem.
// */
// CFApplicationDetail getApplication(String appName) throws Exception;
//
// //TODO: consider removing the getXXXSupport method and directly adding the apis that these support
// // objects provide.
// SshClientSupport getSshClientSupport() throws Exception;
//
//
// void deleteApplication(String name) throws Exception;
// void logout();
// List<CFCloudDomain> getDomains() throws Exception;
//
// List<CFApplication> getApplicationsWithBasicInfo() throws Exception;
//
// List<CFSpace> getSpaces() throws Exception;
// List<CFStack> getStacks() throws Exception;
// void restartApplication(String appName, CancelationToken token) throws Exception;
// void stopApplication(String appName) throws Exception;
// Flux<CFApplicationDetail> getApplicationDetails(List<CFApplication> appsToLookUp) throws Exception;
// String getHealthCheck(UUID appGuid) throws Exception;
// void setHealthCheck(UUID guid, String hcType) throws Exception;
// boolean applicationExists(String appName) throws Exception;
//
// //Removed in V2
// //void createApplication(CloudApplicationDeploymentProperties deploymentProperties) throws Exception;
//
// //Added since v2:
// void push(CFPushArguments args, CancelationToken cancelationToken) throws Exception;
// Map<String, String> getApplicationEnvironment(String appName) throws Exception;
// Mono<Void> deleteServiceAsync(String serviceName);
//
// /**
// * Gets current value of the client's refresh token. Note that the token is only set once it is known.
// * Initially, if a client is created via password auth, then the refreshToken won't be known until
// * some operation has been executed.
// *
// * @return Refresh token if it is already known, null otherwise.
// */
// String getRefreshToken();
// Mono<String> getUserName();
}

View File

@@ -26,6 +26,7 @@ import org.cloudfoundry.reactor.tokenprovider.OneTimePasscodeTokenProvider;
import org.cloudfoundry.reactor.tokenprovider.PasswordGrantTokenProvider;
import org.cloudfoundry.reactor.tokenprovider.RefreshTokenGrantTokenProvider;
import org.cloudfoundry.reactor.uaa.ReactorUaaClient;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFCredentials;
/**
@@ -99,16 +100,16 @@ public class CloudFoundryClientCache {
return null;
}
public CFClientProvider(Params params) {
public CFClientProvider(CFClientParams params) {
long sslTimeout = Long.getLong("sts.bootdash.cf.client.ssl.handshake.timeout", 60); //TODO: make a preference for this?
Optional<Boolean> keepAlive = getBooleanSystemProp("http.keepAlive");
debug("cf client keepAlive = "+keepAlive);
connection = DefaultConnectionContext.builder()
.proxyConfiguration(Optional.ofNullable(getProxy(params.host)))
.apiHost(params.host)
.proxyConfiguration(Optional.ofNullable(getProxy(params.getHost())))
.apiHost(params.getHost())
.sslHandshakeTimeout(Duration.ofSeconds(sslTimeout))
.keepAlive(keepAlive)
.skipSslValidation(params.skipSsl)
.skipSslValidation(params.skipSslValidation())
.build();
tokenProvider = createTokenProvider(params);
@@ -129,12 +130,12 @@ public class CloudFoundryClientCache {
.build();
}
private TokenProvider createTokenProvider(Params params) {
CFCredentials creds = params.credentials;
private TokenProvider createTokenProvider(CFClientParams params) {
CFCredentials creds = params.getCredentials();
switch (creds.getType()) {
case PASSWORD:
return PasswordGrantTokenProvider.builder()
.username(params.username)
.username(params.getUsername())
.password(creds.getSecret())
.build();
case REFRESH_TOKEN:
@@ -167,71 +168,12 @@ public class CloudFoundryClientCache {
}
}
public static class Params {
public final String username;
public final CFCredentials credentials;
public final String host;
public final boolean skipSsl;
public Params(String username, CFCredentials credentials, String host, boolean skipSsl) {
super();
this.username = username;
this.credentials = credentials;
this.host = host;
this.skipSsl = skipSsl;
}
@Override
public String toString() {
return "Params [username=" + username + ", host=" + host + ", skipSsl=" + skipSsl
+ "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((host == null) ? 0 : host.hashCode());
result = prime * result + ((credentials == null) ? 0 : credentials.hashCode());
result = prime * result + (skipSsl ? 1231 : 1237);
result = prime * result + ((username == null) ? 0 : username.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Params other = (Params) obj;
if (host == null) {
if (other.host != null)
return false;
} else if (!host.equals(other.host))
return false;
if (credentials == null) {
if (other.credentials != null)
return false;
} else if (!credentials.equals(other.credentials))
return false;
if (skipSsl != other.skipSsl)
return false;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;
}
}
private Map<Params, CFClientProvider> cache = new HashMap<>();
private Map<CFClientParams, CFClientProvider> cache = new HashMap<>();
private int clientCount = 0;
public synchronized CFClientProvider getOrCreate(String username, CFCredentials credentials, String host, boolean skipSsl) {
Params params = new Params(username, credentials, host, skipSsl);
public synchronized CFClientProvider getOrCreate(CFClientParams params) {
CFClientProvider client = cache.get(params);
if (client==null) {
clientCount++;
@@ -243,7 +185,7 @@ public class CloudFoundryClientCache {
return client;
}
protected CFClientProvider create(Params params) {
protected CFClientProvider create(CFClientParams params) {
return new CFClientProvider(params);
}

View File

@@ -151,7 +151,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
public DefaultClientRequestsV2(CloudFoundryClientCache clients, CFClientParams params, ClientTimeouts timeouts) {
this.params = params;
CFClientProvider provider = clients.getOrCreate(params.getUsername(), params.getCredentials(), params.getHost(), params.skipSslValidation());
CFClientProvider provider = clients.getOrCreate(params);
this._client = provider.client;
this._uaa = provider.uaaClient;
this._tokenProvider = (AbstractUaaTokenProvider) provider.tokenProvider;
@@ -203,7 +203,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
}
}
@Override
// @Override
public List<CFApplication> getApplicationsWithBasicInfo() throws Exception {
return ReactorUtils.get(operations_listApps());
}
@@ -330,7 +330,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
* list. This is to avoid one 'bad apple' from spoiling the whole batch. (I.e if failing to fetch details for
* some apps we can still return details for the others rather than throw an exception).
*/
@Override
// @Override
public Flux<CFApplicationDetail> getApplicationDetails(List<CFApplication> appsToLookUp) throws Exception {
return Flux.fromIterable(appsToLookUp)
.flatMap((CFApplication appSummary) -> {
@@ -383,7 +383,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
};
}
@Override
// @Override
public void stopApplication(String appName) throws Exception {
ReactorUtils.get(
stopApp(appName)
@@ -399,7 +399,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public void restartApplication(String appName, CancelationToken cancelationToken) throws Exception {
ReactorUtils.get(timeouts.getAppStartTimeout(), cancelationToken,
restartApp(appName)
@@ -414,7 +414,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public void logout() {
_operations = null;
_client = null;
@@ -424,7 +424,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
return _client==null;
}
@Override
// @Override
public List<CFStack> getStacks() throws Exception {
return ReactorUtils.get(
log("operations.stacks().list()",
@@ -436,7 +436,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public SshClientSupport getSshClientSupport() throws Exception {
return new SshClientSupport() {
@@ -492,7 +492,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
return client_createOperations(org);
}
@Override
// @Override
public List<CFSpace> getSpaces() throws Exception {
Object it = ReactorUtils.get(timeouts.getSpacesTimeout(), log("operations.organizations().list()",
_operations.organizations()
@@ -514,7 +514,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
return (List<CFSpace>) it;
}
@Override
// @Override
public String getHealthCheck(UUID appGuid) throws Exception {
//XXX CF V2: getHealthcheck (via operations API)
// See: https://www.pivotaltracker.com/story/show/116462215
@@ -524,7 +524,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public void setHealthCheck(UUID guid, String hcType) throws Exception {
//XXX CF V2: setHealthCheck (via operations API)
// See: https://www.pivotaltracker.com/story/show/116462369
@@ -533,7 +533,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public List<CFCloudDomain> getDomains() throws Exception {
//XXX CF V2: list domains using 'operations' api.
return ReactorUtils.get(Duration.ofMinutes(2),
@@ -561,7 +561,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public CFApplicationDetail getApplication(String appName) throws Exception {
return ReactorUtils.get(
getApplicationMono(appName)
@@ -579,7 +579,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
}
@Override
// @Override
public void deleteApplication(String appName) throws Exception {
ReactorUtils.get(
log("operations.applications().delete(name="+appName+")",
@@ -592,7 +592,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public boolean applicationExists(String appName) throws Exception {
return ReactorUtils.get(
getApplicationMono(appName)
@@ -615,7 +615,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
});
}
@Override
// @Override
public void push(CFPushArguments params, CancelationToken cancelationToken) throws Exception {
String appName = params.getAppName();
ReactorUtils.get(timeouts.getAppStartTimeout(), cancelationToken,
@@ -1113,7 +1113,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
// deleteServiceMono(serviceName).get();
// }
@Override
// @Override
public Mono<Void> deleteServiceAsync(String serviceName) {
return getService(serviceName)
.then(this::deleteServiceInstance);
@@ -1150,7 +1150,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
.map(this::dropObjectsFromMap);
}
@Override
// @Override
public Map<String, String> getApplicationEnvironment(String appName) throws Exception {
return ReactorUtils.get(getEnv(appName));
}
@@ -1318,12 +1318,12 @@ public class DefaultClientRequestsV2 implements ClientRequests {
);
}
@Override
// @Override
public String getRefreshToken() {
return _tokenProvider.getRefreshToken();
}
@Override
// @Override
public Mono<String> getUserName() {
return log("uaa.getUsername",
_uaa.getUsername()

View File

@@ -17,9 +17,9 @@ import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetsFactory;
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.cloudfoundry.client.cftarget.CFTargetCache;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.ClientTimeouts;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.CloudFoundryClientFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
@@ -38,8 +38,8 @@ public class CFClientTest {
CloudFoundryClientFactory clientFactory = DefaultCloudFoundryClientFactoryV2.INSTANCE;
ClientTimeouts timeouts = ClientTimeouts.DEFAULT_TIMEOUTS;
CFTargetsFactory targets = new CFTargetsFactory(cliProvider, clientFactory, timeouts);
CFTarget target = targets.getTargets().get(0);
CFTargetCache targetCache = new CFTargetCache(cliProvider, clientFactory, timeouts);
CFTarget target = targetCache.getOrCreate().get(0);
List<CFBuildpack> buildPacks = target.getBuildpacks();
assertTrue(!buildPacks.isEmpty());

View File

@@ -20,7 +20,7 @@ import java.util.logging.Logger;
import javax.inject.Provider;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetsFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import org.springframework.ide.vscode.commons.yaml.schema.BasicYValueHint;
@@ -29,13 +29,13 @@ import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
public abstract class AbstractCFHintsProvider implements Provider<Collection<YValueHint>> {
public static final String EMPTY_VALUE = "";
protected final CFTargetsFactory targetsFactory;
protected final CFTargetCache targetCache;
private static final Logger logger = Logger.getLogger(AbstractCFHintsProvider.class.getName());
public AbstractCFHintsProvider(CFTargetsFactory targetsFactory) {
Assert.isNotNull(targetsFactory);
this.targetsFactory = targetsFactory;
public AbstractCFHintsProvider(CFTargetCache targetCache) {
Assert.isNotNull(targetCache);
this.targetCache = targetCache;
}
@Override
@@ -45,19 +45,15 @@ public abstract class AbstractCFHintsProvider implements Provider<Collection<YVa
// CF errors
// in the CA UI, as well as cases where there are no targets
try {
List<CFTarget> targets = targetsFactory.getTargets();
if (targets == null || targets.isEmpty()) {
hints.add(new BasicYValueHint(EMPTY_VALUE, targetsFactory.noTargetsMessage()));
} else {
Collection<YValueHint> resolvedHints = getHints(targets);
hints.addAll(resolvedHints);
}
List<CFTarget> targets = targetCache.getOrCreate();
Collection<YValueHint> resolvedHints = getHints(targets);
hints.addAll(resolvedHints);
} catch (Throwable e) {
logger.log(Level.SEVERE, e.getMessage(), e);
// Don't throw exception as to allow the CA to be displayed to the
// user.
if (e instanceof IOException || ExceptionUtil.getDeepestCause(e) instanceof IOException) {
hints.add(new BasicYValueHint(EMPTY_VALUE, "Connection failure. " + targetsFactory.noTargetsMessage()));
hints.add(new BasicYValueHint(EMPTY_VALUE, "Connection failure. " + e.getMessage()));
} else {
hints.add(new BasicYValueHint(EMPTY_VALUE,
"Unable to fetch Cloud Foundry proposals due to: " + e.getMessage()));

View File

@@ -16,14 +16,14 @@ import java.util.List;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetsFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
import org.springframework.ide.vscode.commons.yaml.schema.BasicYValueHint;
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
public class ManifestYamlCFBuildpacksProvider extends AbstractCFHintsProvider {
public ManifestYamlCFBuildpacksProvider(CFTargetsFactory targetsFactory) {
super(targetsFactory);
public ManifestYamlCFBuildpacksProvider(CFTargetCache cache) {
super(cache);
}
@Override
@@ -45,7 +45,7 @@ public class ManifestYamlCFBuildpacksProvider extends AbstractCFHintsProvider {
}
if (hints.isEmpty()) {
hints.add(new BasicYValueHint(EMPTY_VALUE, "No buildpacks found. " + targetsFactory.noTargetsMessage()));
hints.add(new BasicYValueHint(EMPTY_VALUE, "No Cloud Foundry buildpacks found."));
}
return hints;
}

View File

@@ -16,14 +16,14 @@ import java.util.List;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetsFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
import org.springframework.ide.vscode.commons.yaml.schema.BasicYValueHint;
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
public class ManifestYamlCFServicesProvider extends AbstractCFHintsProvider {
public ManifestYamlCFServicesProvider(CFTargetsFactory targetsFactory) {
super(targetsFactory);
public ManifestYamlCFServicesProvider(CFTargetCache cache) {
super(cache);
}
@Override
@@ -31,7 +31,7 @@ public class ManifestYamlCFServicesProvider extends AbstractCFHintsProvider {
List<YValueHint> hints = new ArrayList<>();
for (CFTarget cfTarget : targets) {
List<CFServiceInstance> services = cfTarget.getClientRequests().getServices();
List<CFServiceInstance> services = cfTarget.getServices();
if (services != null) {
for (CFServiceInstance service : services) {
String name = service.getName();

View File

@@ -18,9 +18,9 @@ import javax.inject.Provider;
import org.eclipse.lsp4j.CompletionOptions;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetsFactory;
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.cloudfoundry.client.cftarget.CFTargetCache;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.ClientTimeouts;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.CloudFoundryClientFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
@@ -50,7 +50,7 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
private Yaml yaml = new Yaml();
private YamlSchema schema;
private CFTargetsFactory cfTargetsFactory;
private CFTargetCache cfTargetCache;
private static final ClientTimeouts VSCODE_CF_CLIENT_TIMEOUTS = new ClientTimeouts() {
@@ -103,21 +103,21 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
documents.onHover(hoverEngine ::getHover);
}
private CFTargetsFactory getCFTargetsFactory() {
if (cfTargetsFactory == null) {
private CFTargetCache getCfTargetCache() {
if (cfTargetCache == null) {
ClientParamsProvider paramsProvider = new CfCliParamsProvider();
CloudFoundryClientFactory clientFactory = DefaultCloudFoundryClientFactoryV2.INSTANCE;
cfTargetsFactory = new CFTargetsFactory(paramsProvider, clientFactory, VSCODE_CF_CLIENT_TIMEOUTS);
cfTargetCache = new CFTargetCache(paramsProvider, clientFactory, VSCODE_CF_CLIENT_TIMEOUTS);
}
return cfTargetsFactory;
return cfTargetCache;
}
private Provider<Collection<YValueHint>> getBuildpacksProvider() {
return new ManifestYamlCFBuildpacksProvider(getCFTargetsFactory());
return new ManifestYamlCFBuildpacksProvider(getCfTargetCache());
}
private Provider<Collection<YValueHint>> getServicesProvider() {
return new ManifestYamlCFServicesProvider(getCFTargetsFactory());
return new ManifestYamlCFServicesProvider(getCfTargetCache());
}
@Override