Dynamic CA and reconcile for stemcells definition attributes
This commit is contained in:
@@ -19,14 +19,20 @@ import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.ide.vscode.bosh.models.CachingModelProvider;
|
||||
import org.springframework.ide.vscode.bosh.models.CloudConfigModel;
|
||||
import org.springframework.ide.vscode.bosh.models.DynamicModelProvider;
|
||||
import org.springframework.ide.vscode.bosh.models.StemcellModel;
|
||||
import org.springframework.ide.vscode.bosh.models.StemcellsModel;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.CollectorUtil;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.ValueParsers;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlAstCache;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.ASTTypeCache;
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.AbstractType;
|
||||
@@ -83,16 +89,18 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
|
||||
private YType t_release_name_ref;
|
||||
private YType t_instance_group_name_def;
|
||||
private YType t_var_name_def;
|
||||
private final YamlAstCache asts;
|
||||
private final ASTTypeCache astTypes;
|
||||
private DynamicModelProvider<CloudConfigModel> cloudConfigProvider;
|
||||
private DynamicModelProvider<StemcellsModel> stemcellsProvider;
|
||||
private List<Pair<YType, YType>> defAndRefTypes;
|
||||
|
||||
public BoshDeploymentManifestSchema(
|
||||
ASTTypeCache astTypes,
|
||||
YamlAstCache asts, ASTTypeCache astTypes,
|
||||
DynamicModelProvider<CloudConfigModel> cloudConfigProvider,
|
||||
DynamicModelProvider<StemcellsModel> stemcellsProvider
|
||||
) {
|
||||
this.asts = asts;
|
||||
this.astTypes = astTypes;
|
||||
this.cloudConfigProvider = new CachingModelProvider<>(cloudConfigProvider);
|
||||
this.stemcellsProvider = new CachingModelProvider<>(stemcellsProvider);
|
||||
@@ -144,9 +152,6 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
|
||||
.parseWith(ValueParsers.NE_STRING);
|
||||
|
||||
|
||||
YType t_stemcell_name_ref = f.yenumFromDynamicValues("StemcellName", (dc) -> stemcellsProvider.getModel(dc).getStemcellNames());
|
||||
YType t_stemcell_os_ref = f.yenumFromDynamicValues("StemcellOs", (dc) -> stemcellsProvider.getModel(dc).getStemcellOss());
|
||||
|
||||
YAtomicType t_ip_address = f.yatomic("IPAddress"); //TODO: some kind of checking?
|
||||
t_ip_address.parseWith(ValueParsers.NE_STRING);
|
||||
|
||||
@@ -187,8 +192,24 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
|
||||
t_release.require(BoshConstraints.SHA1_REQUIRED_FOR_HTTP_URL);
|
||||
|
||||
YBeanType t_stemcell = f.ybean("Stemcell");
|
||||
|
||||
YType t_stemcell_name_ref = f.yenumFromDynamicValues("StemcellName", (dc) -> stemcellsProvider.getModel(dc).getStemcellNames());
|
||||
YType t_stemcell_os_ref = f.yenumFromDynamicValues("StemcellOs", (dc) -> stemcellsProvider.getModel(dc).getStemcellOss());
|
||||
YType t_stemcell_version_ref = f.yenumFromDynamicValues("StemcellVersion", (dc) -> {
|
||||
StemcellModel currentStemcell = getCurrentStemcell(dc);
|
||||
if (currentStemcell!=null) {
|
||||
return stemcellsProvider.getModel(dc).getStemcells().stream()
|
||||
.filter(sc -> StringUtil.hasText(sc.getVersion()))
|
||||
.filter(currentStemcell.createVersionFilter())
|
||||
.map(sc -> sc.getVersion())
|
||||
.collect(CollectorUtil.toImmutableSet());
|
||||
}
|
||||
//Troubles determining the filter. So return all stemcells.
|
||||
return stemcellsProvider.getModel(dc).getVersions();
|
||||
});
|
||||
|
||||
addProp(t_stemcell, "alias", t_stemcell_alias_def).isRequired(true);
|
||||
addProp(t_stemcell, "version", t_ne_string).isRequired(true);
|
||||
addProp(t_stemcell, "version", t_stemcell_version_ref).isRequired(true);
|
||||
addProp(t_stemcell, "name", t_stemcell_name_ref);
|
||||
addProp(t_stemcell, "os", t_stemcell_os_ref);
|
||||
t_stemcell.requireOneOf("name", "os");
|
||||
@@ -256,6 +277,12 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
|
||||
return v2Schema;
|
||||
}
|
||||
|
||||
private StemcellModel getCurrentStemcell(DynamicSchemaContext dc) throws Exception {
|
||||
YamlPath path = dc.getPath();
|
||||
YamlFileAST ast = asts.getAst(dc.getDocument(), true);
|
||||
return new StemcellModel(path.dropLast().traverseToNode(ast));
|
||||
}
|
||||
|
||||
@Override
|
||||
public YType getTopLevelType() {
|
||||
return TOPLEVEL_TYPE;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class BoshLanguageServer extends SimpleLanguageServer {
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
|
||||
ASTTypeCache astTypeCache = new ASTTypeCache();
|
||||
BoshDeploymentManifestSchema schema = new BoshDeploymentManifestSchema(astTypeCache, cloudConfigProvider, stemcellsProvider);
|
||||
BoshDeploymentManifestSchema schema = new BoshDeploymentManifestSchema(asts, astTypeCache, cloudConfigProvider, stemcellsProvider);
|
||||
|
||||
YamlStructureProvider structureProvider = YamlStructureProvider.DEFAULT;
|
||||
YamlAssistContextProvider contextProvider = new SchemaBasedYamlAssistContextProvider(schema);
|
||||
@@ -66,7 +66,6 @@ public class BoshLanguageServer extends SimpleLanguageServer {
|
||||
documents.onDefinition(new BoshDefintionFinder(this, schema, asts, astTypeCache));
|
||||
}
|
||||
|
||||
|
||||
private void validateOnDocumentChange(IReconcileEngine engine, TextDocument doc) {
|
||||
if (LanguageId.BOSH_DEPLOYMENT.equals(doc.getLanguageId())) {
|
||||
validateWith(doc.getId(), engine);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*******************************************************************************
|
||||
* 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.bosh.models;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
|
||||
/**
|
||||
* A 'view' on a Yaml AST node interpreting it as a Stemcell declaration.
|
||||
*/
|
||||
public class StemcellModel {
|
||||
|
||||
private Node node;
|
||||
|
||||
public StemcellModel(Node node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return NodeUtil.getScalarProperty(node, "name");
|
||||
}
|
||||
|
||||
public String getOs() {
|
||||
return NodeUtil.getScalarProperty(node, "os");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an appropriate filter to limit the candidate stemcells for
|
||||
* providing a version based on 'name' or 'os' values already defined in this stemcell.
|
||||
*/
|
||||
public Predicate<StemcellData> createVersionFilter() {
|
||||
String name = getName();
|
||||
String os = getOs();
|
||||
if (StringUtil.hasText(name) && StringUtil.hasText(os)) {
|
||||
//User shouldn't really specify both of these... but if they do... then
|
||||
// let's do our best to generate proposals for the both of them.
|
||||
return (sc) ->
|
||||
name.equals(sc.getName()) || os.equals(sc.getOs());
|
||||
} else if (StringUtil.hasText(name)) {
|
||||
return (sc) ->
|
||||
name.equals(sc.getName());
|
||||
} else if (StringUtil.hasText(os)) {
|
||||
return (sc) ->
|
||||
os.equals(sc.getOs());
|
||||
} else {
|
||||
return (sc) ->
|
||||
true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,8 +16,11 @@ import static org.springframework.ide.vscode.languageserver.testharness.TestAsse
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionItem;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DiagnosticSeverity;
|
||||
@@ -27,12 +30,17 @@ import org.mockito.Mockito;
|
||||
import org.springframework.ide.vscode.bosh.mocks.MockCloudConfigProvider;
|
||||
import org.springframework.ide.vscode.bosh.models.BoshCommandStemcellsProvider;
|
||||
import org.springframework.ide.vscode.bosh.models.DynamicModelProvider;
|
||||
import org.springframework.ide.vscode.bosh.models.StemcellData;
|
||||
import org.springframework.ide.vscode.bosh.models.StemcellsModel;
|
||||
import org.springframework.ide.vscode.commons.util.ExternalCommand;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.Editor;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
@@ -45,7 +53,7 @@ public class BoshEditorTest {
|
||||
|
||||
@Before public void setup() throws Exception {
|
||||
harness = new LanguageServerHarness(() -> {
|
||||
return new BoshLanguageServer(cloudConfigProvider, stemcellsProvider)
|
||||
return new BoshLanguageServer(cloudConfigProvider, (dc) -> stemcellsProvider.getModel(dc))
|
||||
.setMaxCompletions(100);
|
||||
},
|
||||
LanguageId.BOSH_DEPLOYMENT
|
||||
@@ -946,6 +954,124 @@ public class BoshEditorTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void contentAssistStemcellVersionFromDirector() throws Exception {
|
||||
Editor editor;
|
||||
stemcellsProvider = provideStemcellsFrom(
|
||||
new StemcellData("ubuntu-agent", "123.4", "ubuntu"),
|
||||
new StemcellData("ubuntu-agent", "222.2", "ubuntu"),
|
||||
new StemcellData("centos-agent", "222.2", "centos"),
|
||||
new StemcellData("centos-agent", "333.3", "centos")
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"stemcells:\n" +
|
||||
"- alias: good\n" +
|
||||
" name: centos-agent\n" +
|
||||
" version: <*>\n"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"222.2<*>", "333.3<*>"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"stemcells:\n" +
|
||||
"- alias: good\n" +
|
||||
" os: ubuntu\n" +
|
||||
" version: <*>\n"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"123.4<*>", "222.2<*>"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"stemcells:\n" +
|
||||
"- alias: good\n" +
|
||||
" version: <*>\n"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"123.4<*>", "222.2<*>", "333.3<*>"
|
||||
);
|
||||
|
||||
//when os or name are 'bogus' at least suggest proposals based on other prop
|
||||
editor = harness.newEditor(
|
||||
"stemcells:\n" +
|
||||
"- alias: good\n" +
|
||||
" name: centos-agent\n" +
|
||||
" os: bogus\n" +
|
||||
" version: <*>\n"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"222.2<*>", "333.3<*>"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"stemcells:\n" +
|
||||
"- alias: good\n" +
|
||||
" os: centos\n" +
|
||||
" name: bogus\n" +
|
||||
" version: <*>\n"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"222.2<*>", "333.3<*>"
|
||||
);
|
||||
|
||||
//when the os and name disagree, merge the proposals for both:
|
||||
editor = harness.newEditor(
|
||||
"stemcells:\n" +
|
||||
"- alias: good\n" +
|
||||
" os: centos\n" + //Contradicts the name
|
||||
" name: ubuntu-agent\n" + //Contradicts the os
|
||||
" version: <*>\n"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"123.4<*>", "222.2<*>", "333.3<*>"
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void reconcileStemcellVersionFromDirector() throws Exception {
|
||||
Editor editor;
|
||||
stemcellsProvider = provideStemcellsFrom(
|
||||
new StemcellData("ubuntu-agent", "123.4", "ubuntu"),
|
||||
new StemcellData("ubuntu-agent", "222.2", "ubuntu"),
|
||||
new StemcellData("centos-agent", "222.2", "centos"),
|
||||
new StemcellData("centos-agent", "333.3", "centos")
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"stemcells:\n" +
|
||||
"- alias: aaa\n" +
|
||||
" name: centos-agent\n" +
|
||||
" version: 222.2\n" +
|
||||
"- alias: bbb\n" +
|
||||
" name: centos-agent\n" +
|
||||
" version: 123.4\n" +
|
||||
"- alias: ddd\n" +
|
||||
" os: ubuntu\n" +
|
||||
" version: 333.3\n"
|
||||
);
|
||||
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
|
||||
editor.assertProblems(
|
||||
"123.4|unknown 'StemcellVersion'. Valid values are: [222.2, 333.3]",
|
||||
"333.3|unknown 'StemcellVersion'. Valid values are: [123.4, 222.2]"
|
||||
);
|
||||
}
|
||||
|
||||
private DynamicModelProvider<StemcellsModel> provideStemcellsFrom(StemcellData... stemcellData) {
|
||||
return new BoshCommandStemcellsProvider() {
|
||||
@Override
|
||||
protected String executeCommand(ExternalCommand command) throws Exception {
|
||||
String rows = mapper.writeValueAsString(stemcellData);
|
||||
return "{\n" +
|
||||
" \"Tables\": [\n" +
|
||||
" {\n" +
|
||||
" \"Rows\": " + rows +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test public void contentAssistVMtype() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"name: foo\n" +
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.yaml.reconcile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -30,9 +29,7 @@ import org.yaml.snakeyaml.nodes.Node;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user