Basic support for vm_types block in cloudconfig editor

This commit is contained in:
Kris De Volder
2017-08-08 13:56:49 -07:00
parent caa8d180a3
commit d607902492
4 changed files with 134 additions and 8 deletions

View File

@@ -10,13 +10,23 @@
*******************************************************************************/
package org.springframework.ide.vscode.bosh;
import java.util.Collection;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.ide.vscode.bosh.models.BoshModels;
import org.springframework.ide.vscode.commons.util.CollectorUtil;
import org.springframework.ide.vscode.commons.util.ValueParsers;
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.YType;
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory;
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.AbstractType;
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.YAtomicType;
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.YBeanType;
import org.springframework.ide.vscode.commons.yaml.schema.constraints.Constraints;
import com.google.common.collect.ImmutableList;
import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil;
import org.springframework.ide.vscode.commons.yaml.schema.YamlSchema;
@@ -25,7 +35,10 @@ public class BoshCloudConfigSchema extends SchemaSupport implements YamlSchema {
private final YBeanType toplevelType;
private final YType t_az_ref;
private final YType t_vm_type_ref;
private final YType t_vm_type_def;
private final YType t_network_ref;
private Collection<YType> definitionTypes;
private Collection<Pair<YType, YType>> defAndRefTypes;
public BoshCloudConfigSchema(YTypeFactory f, BoshModels models) {
super(f);
@@ -34,14 +47,15 @@ public class BoshCloudConfigSchema extends SchemaSupport implements YamlSchema {
AbstractType t_ne_string = f.yatomic("String")
.parseWith(ValueParsers.NE_STRING);
YAtomicType t_boolean = f.yenum("boolean", "true", "false");
AbstractType t_pos_integer = f.yatomic("Positive Integer")
.parseWith(ValueParsers.POS_INTEGER);
YType t_params = f.ymap(t_ne_string, t_any);
t_az_ref = t_ne_string;
t_vm_type_ref = t_ne_string;
t_vm_type_def = f.yatomic("VMTypeName").parseWith(ValueParsers.NE_STRING);
t_network_ref = t_ne_string;
AbstractType t_pos_integer = f.yatomic("Positive Integer")
.parseWith(ValueParsers.POS_INTEGER);
YBeanType t_compilation = f.ybean("Compilation");
addProp(t_compilation, "workers", t_pos_integer).isRequired(true);
addProp(t_compilation, "reuse_compilation_vms", t_boolean);
@@ -49,13 +63,46 @@ public class BoshCloudConfigSchema extends SchemaSupport implements YamlSchema {
addProp(t_compilation, "vm_type", t_vm_type_ref).isRequired(true);
addProp(t_compilation, "network", t_network_ref).isRequired(true);
YBeanType t_vm_type = f.ybean("VMType");
addProp(t_vm_type, "name", t_vm_type_def).isPrimary(true);
addProp(t_vm_type, "cloud_properties", t_params);
this.toplevelType = f.ybean("CloudConfig");
addProp(toplevelType, "azs", t_any).isRequired(true);
addProp(toplevelType, "networks", t_any).isRequired(true);
addProp(toplevelType, "vm_types", t_any).isRequired(true);
addProp(toplevelType, "vm_types", f.yseq(t_vm_type)).isRequired(true);
addProp(toplevelType, "vm_extensions", t_any);
addProp(toplevelType, "disk_types", t_any).isRequired(true);
addProp(toplevelType, "compilation", t_compilation).isRequired(true);
ASTTypeCache astTypes = models.astTypes;
for (YType defType : getDefinitionTypes()) {
toplevelType.require(Constraints.uniqueDefinition(astTypes, defType, YamlSchemaProblems.problemType("BOSH_CC_DUPLICATE_"+defType)));
}
}
/**
* @return Pairs of types. Each pair contains a 'def' type and a 'ref' type. Nodes with the ref-type
* shall be interpreted as reference to a corresponding node with the 'def' type if the def and ref node
* contain the same scalar value.
*/
public Collection<Pair<YType, YType>> getDefAndRefTypes() {
if (defAndRefTypes==null) {
defAndRefTypes = ImmutableList.of(
Pair.of(t_vm_type_def, t_vm_type_ref)
);
}
return defAndRefTypes;
}
public Collection<YType> getDefinitionTypes() {
if (definitionTypes==null) {
definitionTypes = getDefAndRefTypes().stream()
.map(pair -> pair.getLeft())
.collect(CollectorUtil.toImmutableList());
}
return definitionTypes;
}
@Override

View File

@@ -14,12 +14,16 @@ import java.util.Collection;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.ide.vscode.bosh.models.BoshModels;
import org.springframework.ide.vscode.commons.util.Lazy;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
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.YTypeUtil;
import org.springframework.ide.vscode.commons.yaml.schema.YamlSchema;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
public class BoshSchemas implements YamlSchema {
public final YTypeFactory f = new YTypeFactory()
@@ -29,14 +33,16 @@ public class BoshSchemas implements YamlSchema {
return deploymentSchema;
}
private final Lazy<Collection<YType>> defTypes = new Lazy<>();
private final Lazy<Collection<Pair<YType,YType>>> defAndRefTypes = new Lazy<>();
private final BoshDeploymentManifestSchema deploymentSchema;
private YTypeUtil typeUtil;
private final YType toplevelType;
private BoshCloudConfigSchema cloudConfigSchema;
public BoshSchemas(BoshModels models) {
this.typeUtil = f.TYPE_UTIL;
this.deploymentSchema = new BoshDeploymentManifestSchema(f, models);
this.cloudConfigSchema = new BoshCloudConfigSchema(f, models);
toplevelType = f.contextAware("BoshSchemas", dc -> {
@@ -57,11 +63,21 @@ public class BoshSchemas implements YamlSchema {
}
public Collection<Pair<YType,YType>> getDefAndRefTypes() {
return deploymentSchema.getDefAndRefTypes();
return defAndRefTypes.load(() -> {
Builder<Pair<YType, YType>> builder = ImmutableList.builder();
builder.addAll(cloudConfigSchema.getDefAndRefTypes());
builder.addAll(deploymentSchema.getDefAndRefTypes());
return builder.build();
});
}
public Collection<YType> getDefinitionTypes() {
return deploymentSchema.getDefinitionTypes();
return defTypes.load(() -> {
Builder<YType> builder = ImmutableList.builder();
builder.addAll(cloudConfigSchema.getDefinitionTypes());
builder.addAll(deploymentSchema.getDefinitionTypes());
return builder.build();
});
}
}

View File

@@ -1954,4 +1954,37 @@ public class BoshEditorTest {
editor.assertHoverContains("network", "References a valid network name defined in the Networks block");
}
@Test public void cloudconfig_vm_types_subproperties() throws Exception {
Editor editor;
editor = harness.newEditor(LanguageId.BOSH_CLOUD_CONFIG,
"vm_types:\n" +
"- name: nice-vm\n" +
" <*>"
);
editor.assertContextualCompletions(PLAIN_COMPLETION, "<*>",
"cloud_properties:\n <*>"
);
editor = harness.newEditor(LanguageId.BOSH_CLOUD_CONFIG,
"vm_types:\n" +
"- <*>"
);
editor.assertContextualCompletions("<*>",
"name: <*>"
);
editor = harness.newEditor(LanguageId.BOSH_CLOUD_CONFIG,
"vm_types:\n" +
"- name: nice-vm\n" +
"- name: dup\n" +
"- name: dup\n"
);
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
editor.assertProblems(
"dup|Duplicate 'VMTypeName'",
"dup|Duplicate 'VMTypeName'"
);
}
}

View File

@@ -0,0 +1,30 @@
/*******************************************************************************
* 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.util;
import java.util.function.Supplier;
/**
* Utility class to simplify creation of lazy-initialized fields.
*/
public class Lazy<T> {
private T value;
public synchronized T load(Supplier<T> loader) {
if (value==null) {
value = loader.get();
Assert.isNotNull(value);
}
return value;
}
}