diff --git a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/BoshDeploymentManifestSchema.java b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/BoshDeploymentManifestSchema.java index 8fd353ebc..e6bf358ec 100644 --- a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/BoshDeploymentManifestSchema.java +++ b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/BoshDeploymentManifestSchema.java @@ -136,7 +136,6 @@ public class BoshDeploymentManifestSchema implements YamlSchema { t_stemcell_alias_def = f.yatomic("StemcellAlias") .parseWith(ValueParsers.NE_STRING); t_stemcell_alias_ref = f.yenumFromDynamicValues("StemcellAlias", (dc) -> astTypes.getDefinedNames(dc, t_stemcell_alias_def)); - YType t_stemcell_name_ref = f.yenumFromDynamicValues("StemcellName", (dc) -> stemcellsProvider.getModel(dc).getStemcellNames()); t_release_name_def = f.yatomic("ReleaseName") .parseWith(ValueParsers.NE_STRING); t_release_name_ref = f.yenumFromDynamicValues("ReleaseName", (dc) -> astTypes.getDefinedNames(dc, t_release_name_def)); @@ -144,6 +143,10 @@ public class BoshDeploymentManifestSchema implements YamlSchema { t_var_name_def = f.yatomic("VariableName") .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,7 +190,7 @@ public class BoshDeploymentManifestSchema implements YamlSchema { addProp(t_stemcell, "alias", t_stemcell_alias_def).isRequired(true); addProp(t_stemcell, "version", t_ne_string).isRequired(true); addProp(t_stemcell, "name", t_stemcell_name_ref); - addProp(t_stemcell, "os", t_ne_string); + addProp(t_stemcell, "os", t_stemcell_os_ref); t_stemcell.requireOneOf("name", "os"); addProp(v2Schema, "stemcells", f.yseq(t_stemcell)).isRequired(true); diff --git a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProvider.java b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProvider.java index 5bc3a6fee..aa5df4b17 100644 --- a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProvider.java +++ b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProvider.java @@ -22,13 +22,18 @@ import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext; public class BoshCommandStemcellsProvider extends BoshCommandBasedModelProvider { - YamlTraversal STEMCELL_NAMES = YamlPath.EMPTY + private static final YamlTraversal STEMCELLS = YamlPath.EMPTY .thenValAt("Tables") .thenAnyChild() .thenValAt("Rows") - .thenAnyChild() + .thenAnyChild(); + + private static final YamlTraversal STEMCELL_NAMES = STEMCELLS .thenValAt("name"); + private static final YamlTraversal STEMCELL_OSS = STEMCELLS + .thenValAt("os"); + @Override public StemcellsModel getModel(DynamicSchemaContext dc) throws Exception { JSONCursor cursor = new JSONCursor(getJsonTree()); @@ -51,6 +56,30 @@ public class BoshCommandStemcellsProvider extends BoshCommandBasedModelProvider< }) .collect(CollectorUtil.toImmutableSet()); } + + @Override + public Collection getStemcells() { + return STEMCELLS.traverseAmbiguously(cursor) + .map(c -> new StemcellData( + getStringProperty(c, "name"), + getStringProperty(c, "version"), + getStringProperty(c, "os") + )) + .collect(CollectorUtil.toImmutableList()); + } + + private String getStringProperty(JSONCursor c, String prop) { + c = YamlPath.EMPTY.thenValAt(prop).traverse(c); + if (c!=null) { + return c.target.asText(); + } + return null; + } + + @Override + public Collection getStemcellOss() { + return getNames(STEMCELL_OSS); + } }; } diff --git a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/StemcellData.java b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/StemcellData.java new file mode 100644 index 000000000..35c3ccc4a --- /dev/null +++ b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/StemcellData.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * 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; + +/** + * Data object representing info about a stemcell obtained from exeuting command + * `bosh stemcells --json`. + */ +public class StemcellData { + + private String name; + private String version; + private String os; + + public StemcellData() { + } + + public StemcellData(String name, String version, String os) { + super(); + this.name = name; + this.version = version; + this.os = os; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public String getVersion() { + return version; + } + public void setVersion(String version) { + this.version = version; + } + public String getOs() { + return os; + } + public void setOs(String os) { + this.os = os; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((os == null) ? 0 : os.hashCode()); + result = prime * result + ((version == null) ? 0 : version.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; + StemcellData other = (StemcellData) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (os == null) { + if (other.os != null) + return false; + } else if (!os.equals(other.os)) + return false; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } +} diff --git a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/StemcellsModel.java b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/StemcellsModel.java index 22ed422b1..0b92eeb7e 100644 --- a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/StemcellsModel.java +++ b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/StemcellsModel.java @@ -16,7 +16,7 @@ import java.util.Collection; * Represents Stemcells information as might be retrieved from bosh director. */ public interface StemcellsModel { - Collection getStemcellNames(); - + Collection getStemcellOss(); + Collection getStemcells(); } diff --git a/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/BoshEditorTest.java b/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/BoshEditorTest.java index ab69299dd..004a9fa69 100644 --- a/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/BoshEditorTest.java +++ b/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/BoshEditorTest.java @@ -25,6 +25,7 @@ import org.junit.Before; import org.junit.Test; 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.StemcellsModel; import org.springframework.ide.vscode.commons.util.text.LanguageId; @@ -33,6 +34,7 @@ import org.springframework.ide.vscode.languageserver.testharness.Editor; import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness; import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSet; public class BoshEditorTest { @@ -915,6 +917,35 @@ public class BoshEditorTest { ); } + @Test public void dynamicStemcellOssFromDirector() throws Exception { + StemcellsModel stemcellsModel = mock(StemcellsModel.class); + when(stemcellsProvider.getModel(any())).thenReturn(stemcellsModel); + when(stemcellsModel.getStemcellOss()).thenReturn(ImmutableSet.of("ubuntu", "centos")); + + //content assist + Editor editor = harness.newEditor( + "stemcells:\n" + + "- os: <*>" + ); + editor.assertContextualCompletions("<*>", + "centos<*>", + "ubuntu<*>" + ); + + //reconcile + editor = harness.newEditor( + "stemcells:\n" + + "- alias: good\n" + + " os: ubuntu-trusty\n" + + "- alias: not-so-good\n" + + " os: bogus<*>" + ); + editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY); + editor.assertProblems( + "bogus|unknown 'StemcellOs'. Valid values are: [centos-7, ubuntu-trusty]" + ); + } + @Test public void contentAssistVMtype() throws Exception { Editor editor = harness.newEditor( "name: foo\n" + diff --git a/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProviderTest.java b/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProviderTest.java index 5d0b48a17..f255ef18a 100644 --- a/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProviderTest.java +++ b/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/models/BoshCommandStemcellsProviderTest.java @@ -11,6 +11,7 @@ package org.springframework.ide.vscode.bosh.models; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; import org.junit.Before; import org.junit.Test; @@ -18,6 +19,7 @@ import org.mockito.Mockito; import org.springframework.ide.vscode.commons.util.IOUtil; import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; public class BoshCommandStemcellsProviderTest { @@ -36,9 +38,23 @@ public class BoshCommandStemcellsProviderTest { "bosh-vsphere-esxi-centos-7-go_agent", "bosh-vsphere-esxi-ubuntu-trusty-go_agent" ), - provider.getModel(Mockito.mock(DynamicSchemaContext.class)) + provider.getModel(mock(DynamicSchemaContext.class)) .getStemcellNames() ); } + @Test public void getStemcells() throws Exception { + assertEquals(ImmutableList.of( + new StemcellData("bosh-vsphere-esxi-centos-7-go_agent", "3421.11", "centos-7"), + new StemcellData("bosh-vsphere-esxi-ubuntu-trusty-go_agent", "3421.11", "ubuntu-trusty") + ), + provider.getModel(mock(DynamicSchemaContext.class)).getStemcells() + ); + } + + @Test public void getOss() throws Exception { + assertEquals(ImmutableSet.of("centos-7", "ubuntu-trusty"), + provider.getModel(mock(DynamicSchemaContext.class)).getStemcellOss()); + } + }