From 78743103a9fa4cb2477e4330456612674ce197ea Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Thu, 20 Jul 2017 10:24:49 -0700 Subject: [PATCH] Dynamic CA and reconcile for network names --- .../bosh/BoshDeploymentManifestSchema.java | 3 +- .../BoshCommandCloudConfigProvider.java | 35 ++++++++-- .../vscode/bosh/models/CloudConfigModel.java | 1 + .../ide/vscode/bosh/BoshEditorTest.java | 66 +++++++++++++++++-- .../bosh/mocks/MockCloudConfigProvider.java | 24 ++++++- 5 files changed, 110 insertions(+), 19 deletions(-) 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 560967604..af405fc7d 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 @@ -143,8 +143,7 @@ public class BoshDeploymentManifestSchema implements YamlSchema { YAtomicType t_url = f.yatomic("URL"); t_url.parseWith(BoshValueParsers.url("http", "https", "file")); - YAtomicType t_network_name = f.yatomic("NetworkName"); //TODO: resolve from 'cloud config' https://www.pivotaltracker.com/story/show/148712155 - t_network_name.parseWith(ValueParsers.NE_STRING); + YAtomicType t_network_name = f.yenumFromDynamicValues("NetworkName", (dc) -> cloudConfigProvider.getModel(dc).getNetworkNames()); YAtomicType t_disk_type = f.yatomic("DiskType"); //TODO: resolve from 'cloud config' https://www.pivotaltracker.com/story/show/148704001 t_disk_type.parseWith(ValueParsers.NE_STRING); diff --git a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandCloudConfigProvider.java b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandCloudConfigProvider.java index cf75725d6..02bbaa147 100644 --- a/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandCloudConfigProvider.java +++ b/headless-services/bosh-language-server/src/main/java/org/springframework/ide/vscode/bosh/models/BoshCommandCloudConfigProvider.java @@ -76,20 +76,31 @@ public class BoshCommandCloudConfigProvider implements DynamicModelProvider getVMTypes() { - return VM_TYPE_NAMES.traverseAmbiguously(ast) + return getNames(VM_TYPE_NAMES); + } + + @Override + public Collection getNetworkNames() { + return getNames(NETWORK_NAMES); + } + + private Collection getNames(YamlTraversal namesPath) { + return namesPath.traverseAmbiguously(ast) .flatMap(nameNode -> { String name = NodeUtil.asScalar(nameNode); return StringUtil.hasText(name) @@ -98,9 +109,19 @@ public class BoshCommandCloudConfigProvider implements DynamicModelProvider getVMTypes(); + Collection getNetworkNames(); } 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 40f67f88a..e8127d272 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 @@ -125,7 +125,7 @@ public class BoshEditorTest { //@Ignore //For now... because not passing yet. @Test public void reconcileCfManifest() throws Exception { Editor editor = harness.newEditorFromClasspath("/workspace/cf-deployment-manifest.yml"); - cloudConfigProvider.readWith(() -> { + cloudConfigProvider.executeCommandWith(() -> { throw new IOException("Couldn't contact the director"); }); editor.assertProblems(/*NONE*/); @@ -718,17 +718,17 @@ public class BoshEditorTest { "instance_groups:\n" + "- name: foo-group\n" + " networks:\n" + - " - name: the-network\n" + + " - name: default\n" + " static_ips: []\n" + " default: []\n" + "- name: bar-group\n" + " networks:\n" + - " - name: the-network\n" + + " - name: default\n" + " static_ips: []\n" + " default: []\n" + "- name: bar-group\n" + " networks:\n" + - " - name: the-network\n" + + " - name: default\n" + " static_ips: []\n" + " default: []\n" + "releases:\n" + @@ -877,7 +877,7 @@ public class BoshEditorTest { } @Test public void reconcileVMTypeWhenCloudConfigUnavailable() throws Exception { - cloudConfigProvider.readWith(() -> null); + cloudConfigProvider.executeCommandWith(() -> null); Editor editor = harness.newEditor( "name: foo\n" + "instance_groups: \n" + @@ -891,7 +891,7 @@ public class BoshEditorTest { } @Test public void reconcileVMTypeWhenCloudConfigThrows() throws Exception { - cloudConfigProvider.readWith(() -> { throw new TimeoutException("Reading cloud config timed out"); }); + cloudConfigProvider.executeCommandWith(() -> { throw new TimeoutException("Reading cloud config timed out"); }); Editor editor = harness.newEditor( "name: foo\n" + "instance_groups: \n" + @@ -905,7 +905,7 @@ public class BoshEditorTest { } @Test public void contentAssistShowsWarningWhenCloudConfigThrows() throws Exception { - cloudConfigProvider.readWith(() -> { + cloudConfigProvider.executeCommandWith(() -> { throw new TimeoutException("Reading cloud config timed out"); }); Editor editor = harness.newEditor( @@ -919,6 +919,58 @@ public class BoshEditorTest { assertContains("Reading cloud config timed out", completion.getDocumentation()); } + @Test public void reconcileNetworkName() throws Exception { + Editor editor = harness.newEditor( + "name: my-first-deployment\n" + + "instance_groups:\n" + + "- name: my-server\n" + + " networks:\n" + + " - name: default\n" + + " - name: bogus-nw\n" + ); + editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY); + editor.assertProblems("bogus-nw|unknown 'NetworkName'. Valid values are: [default]"); + } + + @Test public void reconcileNetworkName2() throws Exception { + cloudConfigProvider.readWith(() -> + "networks:\n" + + "- name: public-nw\n" + + "- name: local-nw" + ); + + Editor editor = harness.newEditor( + "name: my-first-deployment\n" + + "instance_groups:\n" + + "- name: my-server\n" + + " networks:\n" + + " - name: public-nw\n" + + " - name: local-nw\n" + + " - name: bogus-nw\n" + ); + editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY); + editor.assertProblems("bogus-nw|unknown 'NetworkName'. Valid values are: [public-nw, local-nw]"); + } + + @Test public void contentAssistNetworkName() throws Exception { + cloudConfigProvider.readWith(() -> + "networks:\n" + + "- name: public-nw\n" + + "- name: local-nw" + ); + + Editor editor = harness.newEditor( + "name: my-first-deployment\n" + + "instance_groups:\n" + + "- name: my-server\n" + + " networks:\n" + + " - name: <*>" + ); + editor.assertContextualCompletions("<*>", + "local-nw<*>", "public-nw<*>" + ); + } + @Test public void gotoReleaseDefinition() 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/mocks/MockCloudConfigProvider.java b/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/mocks/MockCloudConfigProvider.java index 542cf4fdf..99a28b3a0 100644 --- a/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/mocks/MockCloudConfigProvider.java +++ b/headless-services/bosh-language-server/src/test/java/org/springframework/ide/vscode/bosh/mocks/MockCloudConfigProvider.java @@ -18,12 +18,16 @@ import org.springframework.ide.vscode.commons.util.IOUtil; public final class MockCloudConfigProvider extends BoshCommandCloudConfigProvider { + //TODO: use mockito to create this mock instead of a subclass? + static final String MOCK_DATA_RSRC = "/cmd-out/cloud-config.json"; - private Callable cloudConfigReader = () -> IOUtil.toString(BoshCommandCloudConfigProviderTest.class.getResourceAsStream(MOCK_DATA_RSRC)); + private Callable cloudConfigCmdExecutor = () -> IOUtil.toString(BoshCommandCloudConfigProviderTest.class.getResourceAsStream(MOCK_DATA_RSRC)); private int readCount = 0; + private Callable reader = null; + /** * Override with a 'fake' which just returns some mock data. That way we can unit-test * without requiring a real bosh setup. @@ -31,11 +35,25 @@ public final class MockCloudConfigProvider extends BoshCommandCloudConfigProvide @Override protected String executeBoshCloudConfigCommand() throws Exception { readCount++; - return cloudConfigReader.call(); + return cloudConfigCmdExecutor.call(); + } + + @Override + protected String getCloudConfigBlock() throws Exception { + if (reader==null) { + return super.getCloudConfigBlock(); + } + readCount++; + return reader.call(); + } + + public MockCloudConfigProvider executeCommandWith(Callable executor) { + this.cloudConfigCmdExecutor = executor; + return this; } public MockCloudConfigProvider readWith(Callable reader) { - this.cloudConfigReader = reader; + this.reader = reader; return this; }