Code cleanup for CF support in vscode

This commit is contained in:
nsingh
2017-01-11 15:51:25 -08:00
parent 4345534492
commit 2cbca3304b
11 changed files with 137 additions and 177 deletions

View File

@@ -1,63 +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 javax.inject.Provider;
/**
* Resolves Cloud Foundry client parameters from params providers (for example,
* a provider would be a cf CLI config parser that parses params from the CLI
* config.json file)
*
*/
public class CFClientParamsFactory {
public static final CFClientParamsFactory INSTANCE = new CFClientParamsFactory();
private List<Provider<List<CFClientParams>>> providers = new ArrayList<>();
private CFClientParamsFactory() {
// For now, only support cf CLI.
// Maybe in the future other ways of retrieving client params can be
// supported
// in addition to the cf CLI config.
addProvider(new CfCliParamsProvider());
}
/**
* Adds provider to the front of the registered providers such that it would
* be called first when a request is made for CF client params
*
* @param provider
*/
public void addProvider(Provider<List<CFClientParams>> provider) {
if (provider != null) {
providers.add(provider);
}
}
public List<CFClientParams> getParams() {
// Start from the last provider, which is the highest priority
for (int i = providers.size() - 1; i >= 0; i--) {
List<CFClientParams> params = providers.get(i).get();
if (params != null && !params.isEmpty()) {
return params;
}
}
return null;
}
}

View File

@@ -14,23 +14,22 @@ 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.CloudFoundryClientFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
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 factory and a client factory.
* Creates targets given a client parameters provider and a client factory.
*
*/
public class CFTargetsFactory {
private final CloudFoundryClientFactory clientFactory;
private final CFClientParamsFactory paramsFactory;
private final ClientParamsProvider paramsProvider;
private final ClientTimeouts timeouts;
public CFTargetsFactory(CFClientParamsFactory paramsFactory, CloudFoundryClientFactory clientFactory, ClientTimeouts timeouts) {
public CFTargetsFactory(ClientParamsProvider paramsProvider, CloudFoundryClientFactory clientFactory, ClientTimeouts timeouts) {
this.clientFactory = clientFactory;
this.paramsFactory = paramsFactory;
this.paramsProvider = paramsProvider;
this.timeouts = timeouts;
}
@@ -40,7 +39,7 @@ public class CFTargetsFactory {
* @throws Exception
*/
public List<CFTarget> getTargets() throws Exception {
List<CFClientParams> allParams = paramsFactory.getParams();
List<CFClientParams> allParams = paramsProvider.getParams();
List<CFTarget> targets = new ArrayList<>();
if (allParams != null) {
for (CFClientParams parameters : allParams) {
@@ -52,6 +51,10 @@ public class CFTargetsFactory {
}
return targets;
}
public String noTargetsMessage() {
return paramsProvider.noParamsAvailableMessage();
}
protected String getTargetName(CFClientParams params) {
return labelFromCfApi(params.getApiUrl());
@@ -66,12 +69,4 @@ public class CFTargetsFactory {
return cfApiUrl;
}
}
public static CFTargetsFactory createDefaultV2TargetsFactory(ClientTimeouts timeouts) {
CloudFoundryClientFactory clientFactory = DefaultCloudFoundryClientFactoryV2.INSTANCE;
CFClientParamsFactory paramsFactory = CFClientParamsFactory.INSTANCE;
return new CFTargetsFactory(paramsFactory, clientFactory, timeouts);
}
}

View File

@@ -18,8 +18,6 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Provider;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.ExternalProcess;
@@ -31,7 +29,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
*
*
*/
public class CfCliParamsProvider implements Provider<List<CFClientParams>> {
public class CfCliParamsProvider implements ClientParamsProvider {
public static final String TARGET = "Target";
public static final String REFRESH_TOKEN = "RefreshToken";
@@ -42,8 +40,14 @@ public class CfCliParamsProvider implements Provider<List<CFClientParams>> {
private static Logger logger = Logger.getLogger(CfCliParamsProvider.class.getName());
/*
* (non-Javadoc)
*
* @see org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.
* ClientParamsProvider#getParams()
*/
@Override
public List<CFClientParams> get() {
public List<CFClientParams> getParams() {
try {
File file = getConfigJsonFile();
if (file != null) {
@@ -76,6 +80,17 @@ public class CfCliParamsProvider implements Provider<List<CFClientParams>> {
return null;
}
/*
* (non-Javadoc)
*
* @see org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.
* ClientParamsProvider#noParamsAvailableMessage()
*/
@Override
public String noParamsAvailableMessage() {
return "No Cloud Foundry targets. Please use cf CLI to configure and login to a Cloud Foundry target.";
}
private File getConfigJsonFile() throws IOException, InterruptedException {
// Support Unix systems for now
if (!System.getProperty("os.name").toLowerCase().startsWith("win")) {

View File

@@ -0,0 +1,21 @@
/*******************************************************************************
* 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.List;
public interface ClientParamsProvider {
List<CFClientParams> getParams();
String noParamsAvailableMessage();
}

View File

@@ -650,7 +650,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
// ? stopApp(appName)
// : restartApp(appName)
// );
throw new Error("Application push not currently supported in CF vscode");
throw ExceptionUtil.notImplemented("Application push not currently supported in CF vscode");
}
// private DefaultClientRequestsV1 v1() throws Exception {

View File

@@ -16,23 +16,29 @@ import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParamsFactory;
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.v2.ClientTimeouts;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.CloudFoundryClientFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
public class CFClientTest {
/*
* Not meant to be run in a build yet as there is no CF harness to read CF
* params. Just keeping this tests for local development.
*/
@Ignore
@Test
public void testGetBuildpacksFromCliParamsTarget() throws Exception {
@Ignore @Test public void testGetBuildpacksFromCliParamsTarget() throws Exception {
CFClientParamsFactory paramsFactory = CFClientParamsFactory.INSTANCE;
ClientParamsProvider cliProvider = new CfCliParamsProvider();
CloudFoundryClientFactory clientFactory = DefaultCloudFoundryClientFactoryV2.INSTANCE;
ClientTimeouts timeouts = ClientTimeouts.DEFAULT_TIMEOUTS;
CFTargetsFactory targets = new CFTargetsFactory(paramsFactory, clientFactory, ClientTimeouts.DEFAULT_TIMEOUTS);
CFTargetsFactory targets = new CFTargetsFactory(cliProvider, clientFactory, timeouts);
CFTarget target = targets.getTargets().get(0);
List<CFBuildpack> buildPacks = target.getBuildpacks();

View File

@@ -76,7 +76,7 @@ public class ExceptionUtil {
return new ExecutionException(cause);
}
public static Object exception(String message, Throwable error) {
public static Exception exception(String message, Throwable error) {
if (message != null) {
// Wrap only if there is an additional message
return new ExecutionException(message, error);
@@ -84,5 +84,4 @@ public class ExceptionUtil {
return exception(error);
}
}
}

View File

@@ -10,50 +10,67 @@
*******************************************************************************/
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.logging.Level;
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.util.Assert;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import org.springframework.ide.vscode.commons.yaml.schema.BasicYValueHint;
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
import com.google.common.collect.Lists;
public abstract class AbstractCFHintsProvider implements Provider<Collection<YValueHint>> {
private final CFTargetsFactory targetsFactory;
public static final String EMPTY_VALUE = "";
protected final CFTargetsFactory targetsFactory;
/*
* TODO: This is probably a very wrong way of handling "No connections available"
*/
public static final YValueHint NO_CF_TARGET_HINT = new BasicYValueHint("",
"No valid Cloud Foundry target found. Please ensure that you are connected to Cloud Foundry and try again.");
private static final Logger logger = Logger.getLogger(AbstractCFHintsProvider.class.getName());
public AbstractCFHintsProvider(CFTargetsFactory targetsFactory) {
Assert.isNotNull(targetsFactory);
this.targetsFactory = targetsFactory;
}
@Override
public Collection<YValueHint> get() {
Collection<YValueHint> hints = new ArrayList<>();
List<CFTarget> targets = null;
try {
targets = targetsFactory.getTargets();
} catch (Throwable e) {
// Don't throw exception. Just log, and instead show a "no targets"
// hint below
logger.log(Level.SEVERE, e.getMessage(), e);
}
if (targets == null || targets.isEmpty()) {
// TODO: Probably a wrong thing to do, but for now show that
// there are
// no targets as a "hint" so that it appears
// in CA UI
hints.add(new BasicYValueHint(EMPTY_VALUE, targetsFactory.noTargetsMessage()));
} else {
try {
Collection<YValueHint> resolvedHints = getHints(targets);
hints.addAll(resolvedHints);
} catch (Exception e) {
throw ExceptionUtil.unchecked(e);
}
}
return hints;
}
/**
*
* @return non-null list of targets. May be empty if no targets available.
* @throws Exception
* if error when creating the targets
* @return non-null list of hints. Return empty if no hints available
*/
protected List<CFTarget> getUpdatedCFTargets() throws Exception {
if (targetsFactory != null) {
// Do not cache the targets. They may change (e.g. if using cf
// CLI config, if CLI targets another API or org/space, the list
// of targets fetched from the factory also
// needs to be up-to-date)
List<CFTarget> updatedTargets = targetsFactory.getTargets();
if (updatedTargets != null) {
return Lists.newArrayList(updatedTargets.iterator());
}
}
return Collections.emptyList();
}
abstract protected Collection<YValueHint> getHints(List<CFTarget> targets) throws Exception;
}

View File

@@ -13,8 +13,6 @@ package org.springframework.ide.vscode.manifest.yaml;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
@@ -24,43 +22,26 @@ import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
public class ManifestYamlCFBuildpacksProvider extends AbstractCFHintsProvider {
private static final Logger logger = Logger.getLogger(ManifestYamlCFBuildpacksProvider.class.getName());
public ManifestYamlCFBuildpacksProvider(CFTargetsFactory targetsFactory) {
super(targetsFactory);
}
@Override
public Collection<YValueHint> get() {
public Collection<YValueHint> getHints(List<CFTarget> targets) throws Exception {
List<YValueHint> hints = new ArrayList<>();
try {
// Do not cache the targets. They may change (e.g. if using cf
// CLI config, if CLI targets another API or org/space, the list
// of targets fetched from the factory also
// needs to be up-to-date)
List<CFTarget> targets = getUpdatedCFTargets();
for (CFTarget cfTarget : targets) {
for (CFTarget cfTarget : targets) {
List<CFBuildpack> buildpacks = cfTarget.getBuildpacks();
if (buildpacks != null) {
for (CFBuildpack buildpack : buildpacks) {
String name = buildpack.getName();
String label = getBuildpackLabel(cfTarget, buildpack);
YValueHint hint = new BasicYValueHint(name, label);
if (!hints.contains(hint)) {
hints.add(hint);
}
List<CFBuildpack> buildpacks = cfTarget.getBuildpacks();
if (buildpacks != null) {
for (CFBuildpack buildpack : buildpacks) {
String name = buildpack.getName();
String label = getBuildpackLabel(cfTarget, buildpack);
YValueHint hint = new BasicYValueHint(name, label);
if (!hints.contains(hint)) {
hints.add(hint);
}
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
// TODO: probably a very bad thing to do, but for now a workaround to notify the user via the CA UI that there are no
// CF targets available.
if (hints.isEmpty()) {
hints.add(NO_CF_TARGET_HINT);
}
return hints;
}
@@ -68,5 +49,4 @@ public class ManifestYamlCFBuildpacksProvider extends AbstractCFHintsProvider {
protected String getBuildpackLabel(CFTarget target, CFBuildpack buildpack) {
return buildpack.getName() + " (" + target.getName() + ")";
}
}

View File

@@ -13,8 +13,6 @@ package org.springframework.ide.vscode.manifest.yaml;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
@@ -22,47 +20,33 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTar
import org.springframework.ide.vscode.commons.yaml.schema.BasicYValueHint;
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
public class ManifestYamlCFServicesProvider extends AbstractCFHintsProvider {
private static final Logger logger = Logger.getLogger(ManifestYamlCFServicesProvider.class.getName());
public class ManifestYamlCFServicesProvider extends AbstractCFHintsProvider {
public ManifestYamlCFServicesProvider(CFTargetsFactory targetsFactory) {
super(targetsFactory);
}
@Override
public Collection<YValueHint> get() {
public Collection<YValueHint> getHints(List<CFTarget> targets) throws Exception {
List<YValueHint> hints = new ArrayList<>();
try {
List<CFTarget> targets = getUpdatedCFTargets();
for (CFTarget cfTarget : targets) {
List<CFServiceInstance> services = cfTarget.getClientRequests().getServices();
if (services != null) {
for (CFServiceInstance service : services) {
String name = service.getName();
String label = getServiceLabel(cfTarget, service);
YValueHint hint = new BasicYValueHint(name, label);
if (!hints.contains(hint)) {
hints.add(hint);
}
for (CFTarget cfTarget : targets) {
List<CFServiceInstance> services = cfTarget.getClientRequests().getServices();
if (services != null) {
for (CFServiceInstance service : services) {
String name = service.getName();
String label = getServiceLabel(cfTarget, service);
YValueHint hint = new BasicYValueHint(name, label);
if (!hints.contains(hint)) {
hints.add(hint);
}
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
// TODO: probably a very bad thing to do, but for now a workaround to notify the user via the CA UI that there are no
// CF targets available.
if (hints.isEmpty()) {
hints.add(NO_CF_TARGET_HINT);
}
if (hints.isEmpty()) {
hints.add(new BasicYValueHint(EMPTY_VALUE, "No Cloud Foundry service instances available"));
}
return hints;
}

View File

@@ -19,7 +19,11 @@ 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.v2.ClientTimeouts;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.CloudFoundryClientFactory;
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProvider;
@@ -101,7 +105,9 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
private CFTargetsFactory getCFTargetsFactory() {
if (cfTargetsFactory == null) {
cfTargetsFactory = CFTargetsFactory.createDefaultV2TargetsFactory(VSCODE_CF_CLIENT_TIMEOUTS);
ClientParamsProvider paramsProvider = new CfCliParamsProvider();
CloudFoundryClientFactory clientFactory = DefaultCloudFoundryClientFactoryV2.INSTANCE;
cfTargetsFactory = new CFTargetsFactory(paramsProvider, clientFactory, VSCODE_CF_CLIENT_TIMEOUTS);
}
return cfTargetsFactory;
}