Reconcile and CA for 'stack' property in manifest.yml
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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;
|
||||
|
||||
public interface CFStack extends CFEntity {
|
||||
|
||||
}
|
||||
@@ -18,5 +18,6 @@ public interface ClientRequests {
|
||||
List<CFBuildpack> getBuildpacks() throws Exception;
|
||||
List<CFServiceInstance> getServices() throws Exception;
|
||||
List<CFDomain> getDomains() throws Exception;
|
||||
|
||||
List<CFStack> getStacks() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFDomain;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFStack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
@@ -41,6 +42,7 @@ public class CFTarget {
|
||||
private LoadingCache<String, List<CFBuildpack>> buildpacksCache;
|
||||
private LoadingCache<String, List<CFServiceInstance>> servicesCache;
|
||||
private LoadingCache<String, List<CFDomain>> domainCache;
|
||||
private LoadingCache<String, List<CFStack>> stacksCache;
|
||||
private CFCallableContext callableContext;
|
||||
|
||||
public CFTarget(String targetName, CFClientParams params, ClientRequests requests,
|
||||
@@ -53,6 +55,20 @@ public class CFTarget {
|
||||
}
|
||||
|
||||
private void initCache(ClientRequests requests) {
|
||||
CacheLoader<String, List<CFStack>> stacksLoader = new CacheLoader<String, List<CFStack>>() {
|
||||
|
||||
@Override
|
||||
public List<CFStack> load(String key) throws Exception {
|
||||
/* Cache of services does not use keys, as the whole cache
|
||||
* gets wiped clean on any new call to CF.
|
||||
*/
|
||||
return runAndCheckForFailure(() -> requests.getStacks());
|
||||
}
|
||||
};
|
||||
this.stacksCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(CFTargetCache.SERVICES_EXPIRATION.toMillis(), TimeUnit.MILLISECONDS).build(stacksLoader);
|
||||
|
||||
|
||||
CacheLoader<String, List<CFServiceInstance>> servicesLoader = new CacheLoader<String, List<CFServiceInstance>>() {
|
||||
|
||||
@Override
|
||||
@@ -64,7 +80,7 @@ public class CFTarget {
|
||||
}
|
||||
};
|
||||
this.servicesCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(CFTargetCache.SERVICES_EXPIRATION, TimeUnit.SECONDS).build(servicesLoader);
|
||||
.expireAfterAccess(CFTargetCache.SERVICES_EXPIRATION.toMillis(), TimeUnit.MILLISECONDS).build(servicesLoader);
|
||||
|
||||
CacheLoader<String, List<CFBuildpack>> buildpacksLoader = new CacheLoader<String, List<CFBuildpack>>() {
|
||||
|
||||
@@ -77,7 +93,7 @@ public class CFTarget {
|
||||
}
|
||||
};
|
||||
this.buildpacksCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(CFTargetCache.TARGET_EXPIRATION, TimeUnit.HOURS).build(buildpacksLoader);
|
||||
.expireAfterAccess(CFTargetCache.TARGET_EXPIRATION.toMillis(), TimeUnit.MILLISECONDS).build(buildpacksLoader);
|
||||
|
||||
CacheLoader<String, List<CFDomain>> domainLoader = new CacheLoader<String, List<CFDomain>>() {
|
||||
|
||||
@@ -88,7 +104,7 @@ public class CFTarget {
|
||||
|
||||
};
|
||||
this.domainCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(CFTargetCache.TARGET_EXPIRATION, TimeUnit.HOURS).build(domainLoader);
|
||||
.expireAfterAccess(CFTargetCache.TARGET_EXPIRATION.toMillis(), TimeUnit.MILLISECONDS).build(domainLoader);
|
||||
}
|
||||
|
||||
protected <T> T runAndCheckForFailure(Callable<T> callable) throws Exception {
|
||||
@@ -103,6 +119,15 @@ public class CFTarget {
|
||||
return params;
|
||||
}
|
||||
|
||||
public List<CFStack> getStacks() throws Exception {
|
||||
// Use the target name as the "key" , since Guava cache doesn't allow null keys
|
||||
// However, the key is not really used when fetching buildpacks, as we are not caching
|
||||
// buildpacks per target here. This class only represents ONE target, so it will only
|
||||
// ever have one key
|
||||
String key = getName();
|
||||
return this.stacksCache.get(key);
|
||||
}
|
||||
|
||||
public List<CFBuildpack> getBuildpacks() throws Exception {
|
||||
// Use the target name as the "key" , since Guava cache doesn't allow null keys
|
||||
// However, the key is not really used when fetching buildpacks, as we are not caching
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -30,8 +31,8 @@ public class CFTargetCache {
|
||||
private final LoadingCache<ClientParamsCacheKey, CFTarget> cache;
|
||||
private final CFCallableContext cacheCallableContext;
|
||||
|
||||
public static final long SERVICES_EXPIRATION = 10;
|
||||
public static final long TARGET_EXPIRATION = 1;
|
||||
public static final Duration SERVICES_EXPIRATION = Duration.ofSeconds(10);
|
||||
public static final Duration TARGET_EXPIRATION = Duration.ofHours(1);
|
||||
|
||||
public CFTargetCache(ClientParamsProvider paramsProvider, CloudFoundryClientFactory clientFactory,
|
||||
ClientTimeouts timeouts) {
|
||||
@@ -49,7 +50,7 @@ public class CFTargetCache {
|
||||
}
|
||||
|
||||
};
|
||||
cache = CacheBuilder.newBuilder().maximumSize(1).expireAfterAccess(TARGET_EXPIRATION, TimeUnit.HOURS)
|
||||
cache = CacheBuilder.newBuilder().maximumSize(1).expireAfterAccess(TARGET_EXPIRATION.toMillis(), TimeUnit.MILLISECONDS)
|
||||
.build(loader);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,12 @@ import org.cloudfoundry.operations.buildpacks.Buildpack;
|
||||
import org.cloudfoundry.operations.domains.Domain;
|
||||
import org.cloudfoundry.operations.services.ServiceInstanceSummary;
|
||||
import org.cloudfoundry.operations.services.ServiceInstanceType;
|
||||
import org.cloudfoundry.operations.stacks.Stack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFDomain;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFEntities;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFStack;
|
||||
|
||||
/**
|
||||
* Various helper methods to 'wrap' objects returned by CF client into our own
|
||||
@@ -27,17 +29,16 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInsta
|
||||
*/
|
||||
public class CFWrappingV2 {
|
||||
|
||||
|
||||
public static CFBuildpack wrap(Buildpack buildpack) {
|
||||
String name = buildpack.getName();
|
||||
return CFEntities.createBuildpack(name);
|
||||
}
|
||||
|
||||
|
||||
public static CFDomain wrap(Domain domain) {
|
||||
String name = domain.getName();
|
||||
return CFEntities.createDomain(name);
|
||||
}
|
||||
|
||||
|
||||
public static CFServiceInstance wrap(ServiceInstanceSummary serviceInstance) {
|
||||
String name = serviceInstance.getName();
|
||||
String plan = serviceInstance.getPlan();
|
||||
@@ -47,4 +48,22 @@ public class CFWrappingV2 {
|
||||
return CFEntities.createServiceInstance(name, service, plan);
|
||||
}
|
||||
|
||||
public static CFStack wrap(Stack stack) {
|
||||
if (stack!=null) {
|
||||
String name = stack.getName();
|
||||
return new CFStack() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CFStack("+name+")";
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFDomain;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFStack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientTimeouts;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
|
||||
@@ -83,7 +84,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<CFDomain> getDomains() throws Exception {
|
||||
|
||||
@@ -98,7 +99,7 @@ public class DefaultClientRequestsV2 implements ClientRequests {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<CFBuildpack> getBuildpacks() throws Exception {
|
||||
return ReactorUtils.get(timeouts.getBuildpacksTimeout(), CancelationTokens.NULL,
|
||||
@@ -112,6 +113,18 @@ public class DefaultClientRequestsV2 implements ClientRequests {
|
||||
)
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public List<CFStack> getStacks() throws Exception {
|
||||
return ReactorUtils.get(
|
||||
log("operations.stacks().list()",
|
||||
_operations.stacks()
|
||||
.list()
|
||||
.map(CFWrappingV2::wrap)
|
||||
.collectList()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//// calls to client and operations with 'logging'.
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.yaml.completion;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_EXISTS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -29,6 +30,7 @@ import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.ValueParseException;
|
||||
import org.springframework.ide.vscode.commons.yaml.completion.DefaultCompletionFactory.ValueProposal;
|
||||
import org.springframework.ide.vscode.commons.yaml.hover.YPropertyInfoTemplates;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
|
||||
@@ -42,16 +44,11 @@ import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SChildBearingNode;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SNode;
|
||||
import org.springframework.ide.vscode.commons.yaml.util.Streams;
|
||||
import org.springframework.ide.vscode.commons.yaml.util.YamlIndentUtil;
|
||||
|
||||
import org.springframework.ide.vscode.commons.yaml.completion.DefaultCompletionFactory.ValueProposal;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.*;
|
||||
|
||||
public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
|
||||
final static Logger logger = LoggerFactory.getLogger(YTypeAssistContext.class);
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.concurrent.Callable;
|
||||
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;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ConnectionException;
|
||||
@@ -78,7 +79,7 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param e
|
||||
* @return an error that requires no additional information when showing its
|
||||
* message, or null if no such error is found
|
||||
@@ -87,7 +88,7 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
return ExceptionUtil.findThrowable(e,
|
||||
ImmutableList.of(NoTargetsException.class, ConnectionException.class));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return non-null list of hints. Return empty if no hints available
|
||||
|
||||
@@ -29,16 +29,13 @@ public class CFServicesValueParser extends EnumValueParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createBlankTextErrorMessage() {
|
||||
return "At least one service instance name must be specified";
|
||||
}
|
||||
|
||||
protected Exception errorOnParse(String message) {
|
||||
// Parse errors should be indicated differently than regular schema
|
||||
// problems (e.g. unknown service may be a warning)
|
||||
return new ReconcileException(message, ManifestYamlSchemaProblemsTypes.UNKNOWN_SERVICES_PROBLEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Exception errorOnBlank(String message) {
|
||||
// Blank errors should be regular schema problems
|
||||
return new ReconcileException(message, YamlSchemaProblems.SCHEMA_PROBLEM);
|
||||
|
||||
@@ -59,12 +59,12 @@ public class ManifestYamlCFServicesProvider extends AbstractCFHintsProvider {
|
||||
return hints;
|
||||
}
|
||||
|
||||
private String getServiceLabel(CFTarget cfClientTarget, CFServiceInstance service) {
|
||||
return service.getName() + " - " + service.getPlan();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTypeName() {
|
||||
return "Service";
|
||||
}
|
||||
|
||||
protected final String getServiceLabel(CFTarget cfClientTarget, CFServiceInstance service) {
|
||||
return service.getName() + " - " + service.getPlan();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,9 +95,10 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
}
|
||||
|
||||
protected ManifestYmlHintProviders getHintProviders() {
|
||||
Callable<Collection<YValueHint>> buildPacksProvider = getBuildpacksProvider();
|
||||
Callable<Collection<YValueHint>> servicesProvider = getServicesProvider();
|
||||
Callable<Collection<YValueHint>> domainsProvider = getDomainsProvider();
|
||||
Callable<Collection<YValueHint>> buildPacksProvider = new ManifestYamlCFBuildpacksProvider(getCfTargetCache());
|
||||
Callable<Collection<YValueHint>> servicesProvider = new ManifestYamlCFServicesProvider(getCfTargetCache());
|
||||
Callable<Collection<YValueHint>> domainsProvider = new ManifestYamlCFDomainsProvider(getCfTargetCache());
|
||||
Callable<Collection<YValueHint>> stacksProvider = new ManifestYamlStacksProvider(getCfTargetCache());
|
||||
|
||||
return new ManifestYmlHintProviders() {
|
||||
|
||||
@@ -115,6 +116,11 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
public Callable<Collection<YValueHint>> getBuildpackProviders() {
|
||||
return buildPacksProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Callable<Collection<YValueHint>> getStacksProvider() {
|
||||
return stacksProvider;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -127,16 +133,4 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
return cfTargetCache;
|
||||
}
|
||||
|
||||
private Callable<Collection<YValueHint>> getBuildpacksProvider() {
|
||||
return new ManifestYamlCFBuildpacksProvider(getCfTargetCache());
|
||||
}
|
||||
|
||||
private Callable<Collection<YValueHint>> getServicesProvider() {
|
||||
return new ManifestYamlCFServicesProvider(getCfTargetCache());
|
||||
}
|
||||
|
||||
private Callable<Collection<YValueHint>> getDomainsProvider() {
|
||||
return new ManifestYamlCFDomainsProvider(getCfTargetCache());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,9 +15,6 @@ import static org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaPr
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ManifestYamlSchemaProblemsTypes {
|
||||
|
||||
public static final ProblemType UNKNOWN_SERVICES_PROBLEM = problemType("UnknownServicesProblem",
|
||||
@@ -25,5 +22,8 @@ public class ManifestYamlSchemaProblemsTypes {
|
||||
|
||||
public static final ProblemType UNKNOWN_DOMAIN_PROBLEM = problemType("UnknownDomainProblem",
|
||||
ProblemSeverity.WARNING);
|
||||
|
||||
|
||||
public static final ProblemType UNKNOWN_STACK_PROBLEM = problemType("UnknownStackProblem",
|
||||
ProblemSeverity.WARNING);;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*******************************************************************************
|
||||
* 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.manifest.yaml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFStack;
|
||||
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.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.BasicYValueHint;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
|
||||
|
||||
public class ManifestYamlStacksProvider extends AbstractCFHintsProvider {
|
||||
|
||||
public ManifestYamlStacksProvider(CFTargetCache targetCache) {
|
||||
super(targetCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTypeName() {
|
||||
return "Stack";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<YValueHint> getHints(List<CFTarget> targets) throws Exception {
|
||||
// NOTE: empty list of services is a VALID result. A CF target may have
|
||||
// no service instances
|
||||
// created, so if empty list is returned from the client, then RETURN empty list. don't
|
||||
// return null
|
||||
// for empty services cases
|
||||
List<YValueHint> hints = new ArrayList<>();
|
||||
|
||||
for (CFTarget cfTarget : targets) {
|
||||
List<CFStack> stacks = cfTarget.getStacks();
|
||||
Renderable targetLabel = Renderables.text(cfTarget.getLabel());
|
||||
if (stacks != null && !stacks.isEmpty()) {
|
||||
for (CFStack s : stacks) {
|
||||
String name = s.getName();
|
||||
String label = name;
|
||||
YValueHint hint = new BasicYValueHint(name, label)
|
||||
.setDocumentation(targetLabel);
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint);
|
||||
}
|
||||
}
|
||||
return hints;
|
||||
}
|
||||
}
|
||||
|
||||
return hints;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -23,4 +23,6 @@ public interface ManifestYmlHintProviders {
|
||||
|
||||
Callable<Collection<YValueHint>> getDomainsProvider();
|
||||
|
||||
Callable<Collection<YValueHint>> getStacksProvider();
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileException;
|
||||
import org.springframework.ide.vscode.commons.util.EnumValueParser;
|
||||
import org.springframework.ide.vscode.commons.util.IntegerRange;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
@@ -37,7 +39,6 @@ public class ManifestYmlSchema implements YamlSchema {
|
||||
|
||||
private final AbstractType TOPLEVEL_TYPE;
|
||||
private final YTypeUtil TYPE_UTIL;
|
||||
private final Callable<Collection<YValueHint>> buildpackProvider;
|
||||
|
||||
private static final Set<String> TOPLEVEL_EXCLUDED = ImmutableSet.of(
|
||||
"name", "host", "hosts"
|
||||
@@ -50,9 +51,10 @@ public class ManifestYmlSchema implements YamlSchema {
|
||||
|
||||
|
||||
public ManifestYmlSchema(ManifestYmlHintProviders providers) {
|
||||
this.buildpackProvider = providers.getBuildpackProviders();
|
||||
Callable<Collection<YValueHint>> buildpackProvider = providers.getBuildpackProviders();
|
||||
Callable<Collection<YValueHint>> servicesProvider = providers.getServicesProvider();
|
||||
Callable<Collection<YValueHint>> domainsProvider = providers.getDomainsProvider();
|
||||
Callable<Collection<YValueHint>> stacksProvider = providers.getStacksProvider();
|
||||
|
||||
|
||||
YTypeFactory f = new YTypeFactory();
|
||||
@@ -65,11 +67,20 @@ public class ManifestYmlSchema implements YamlSchema {
|
||||
YAtomicType t_path = f.yatomic("Path");
|
||||
|
||||
YAtomicType t_buildpack = f.yatomic("Buildpack");
|
||||
if (this.buildpackProvider != null) {
|
||||
t_buildpack.addHintProvider(this.buildpackProvider);
|
||||
if (buildpackProvider != null) {
|
||||
t_buildpack.addHintProvider(buildpackProvider);
|
||||
// t_buildpack.parseWith(ManifestYmlValueParsers.fromHints(t_buildpack.toString(), buildpackProvider));
|
||||
}
|
||||
|
||||
YAtomicType t_stack = f.yatomic("Stack");
|
||||
t_stack.addHintProvider(stacksProvider);
|
||||
t_stack.parseWith(new EnumValueParser(t_stack.toString(), YTypeFactory.valuesFromHintProvider(stacksProvider)) {
|
||||
@Override
|
||||
protected Exception errorOnParse(String message) {
|
||||
return new ReconcileException(message, ManifestYamlSchemaProblemsTypes.UNKNOWN_STACK_PROBLEM);
|
||||
}
|
||||
});
|
||||
|
||||
YAtomicType t_domain = f.yatomic("Domain");
|
||||
|
||||
if (domainsProvider != null) {
|
||||
@@ -136,7 +147,7 @@ public class ManifestYmlSchema implements YamlSchema {
|
||||
f.yprop("random-route", t_boolean),
|
||||
f.yprop("routes", f.yseq(route)),
|
||||
f.yprop("services", f.yseq(t_service)),
|
||||
f.yprop("stack", t_string),
|
||||
f.yprop("stack", t_stack),
|
||||
f.yprop("timeout", t_pos_integer),
|
||||
f.yprop("health-check-type", t_health_check_type),
|
||||
f.yprop("health-check-http-endpoint", t_ne_string)
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.mockito.Mockito;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFDomain;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFStack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.CodeAction;
|
||||
@@ -589,6 +590,51 @@ public class ManifestYamlEditorTest {
|
||||
editor.assertNoHover("otherdomain.org");
|
||||
}
|
||||
|
||||
@Test public void stacksCompletion() throws Exception {
|
||||
List<CFStack> stacks = ImmutableList.of(
|
||||
mockStack("linux"), mockStack("windows")
|
||||
);
|
||||
when(cloudfoundry.client.getStacks()).thenReturn(stacks);
|
||||
Editor editor = harness.newEditor(
|
||||
"stack: <*>"
|
||||
);
|
||||
CompletionItem c = editor.assertCompletions(
|
||||
"stack: linux<*>",
|
||||
"stack: windows<*>"
|
||||
).get(0);
|
||||
|
||||
assertEquals("an-org : a-space [test.io]", c.getDocumentation());
|
||||
}
|
||||
|
||||
@Test public void stacksReconcile() throws Exception {
|
||||
List<CFStack> stacks = ImmutableList.of(
|
||||
mockStack("linux"), mockStack("windows")
|
||||
);
|
||||
when(cloudfoundry.client.getStacks()).thenReturn(stacks);
|
||||
{
|
||||
Editor editor = harness.newEditor(
|
||||
"stack: android<*>"
|
||||
);
|
||||
Diagnostic p = editor.assertProblems("android|'android' is an unknown 'Stack'. Valid values are: [linux, windows]").get(0);
|
||||
assertEquals(DiagnosticSeverity.Warning, p.getSeverity());
|
||||
}
|
||||
|
||||
{
|
||||
Editor editor = harness.newEditor(
|
||||
"stack: <*>"
|
||||
);
|
||||
Diagnostic p = editor.assertProblems("|'Stack' cannot be blank").get(0);
|
||||
assertEquals(DiagnosticSeverity.Error, p.getSeverity());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private CFStack mockStack(String name) {
|
||||
CFStack stack = Mockito.mock(CFStack.class);
|
||||
when(stack.getName()).thenReturn(name);
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reconcileDuplicateKeys() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
@@ -882,10 +928,12 @@ public class ManifestYamlEditorTest {
|
||||
ClientRequests cfClient = cloudfoundry.client;
|
||||
when(cfClient.getBuildpacks()).thenThrow(new IOException("Can't get buildpacks"));
|
||||
when(cfClient.getServices()).thenThrow(new IOException("Can't get services"));
|
||||
when(cfClient.getStacks()).thenThrow(new IOException("Can't get stacks"));
|
||||
Editor editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: foo\n" +
|
||||
" buildpack: bad-buildpack\n" +
|
||||
" stack: bad-stack\n" +
|
||||
" services:\n" +
|
||||
" - bad-service\n" +
|
||||
" bogus: bad" //a token error to make sure reconciler is actually running!
|
||||
|
||||
@@ -174,5 +174,10 @@ public class ManifestYmlSchemaTest {
|
||||
public Callable<Collection<YValueHint>> getBuildpackProviders() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Callable<Collection<YValueHint>> getStacksProvider() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user