Add a Dynamic 'Stemcells' model information provider

In preparation of implementing dynamic CA and checking of stemcells block.
This commit is contained in:
Kris De Volder
2017-07-21 10:51:53 -07:00
parent 4342b237ed
commit da37474d2e
17 changed files with 423 additions and 73 deletions

View File

@@ -19,6 +19,7 @@ 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.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;
@@ -84,11 +85,17 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
private YType t_var_name_def;
private final ASTTypeCache astTypes;
private DynamicModelProvider<CloudConfigModel> cloudConfigProvider;
private DynamicModelProvider<StemcellsModel> stemcellsProvider;
private List<Pair<YType, YType>> defAndRefTypes;
public BoshDeploymentManifestSchema(ASTTypeCache astTypes, DynamicModelProvider<CloudConfigModel> cloudConfigProvider) {
public BoshDeploymentManifestSchema(
ASTTypeCache astTypes,
DynamicModelProvider<CloudConfigModel> cloudConfigProvider,
DynamicModelProvider<StemcellsModel> stemcellsProvider
) {
this.astTypes = astTypes;
this.cloudConfigProvider = new CachingModelProvider<>(cloudConfigProvider);
this.stemcellsProvider = new CachingModelProvider<>(stemcellsProvider);
TYPE_UTIL = f.TYPE_UTIL;
V2_TOPLEVEL_TYPE = createV2Schema();
@@ -228,7 +235,9 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
YBeanType t_variable = f.ybean("Variable");
addProp(t_variable, "name", t_var_name_def).isPrimary(true);
addProp(t_variable, "type", f.yenum("VariableType", "certificate", "password", "rsa", "ssh")).isRequired(true);
YType t_variable_type = f.yenum("VariableType", "certificate", "password", "rsa", "ssh")
.parseWith(ValueParsers.NE_STRING); //Overrid the parser -> no errors / warnings... in theory there could be other valid values.
addProp(t_variable, "type", t_variable_type).isRequired(true);
addProp(t_variable, "options", t_params);
addProp(v2Schema, "variables", f.yseq(t_variable));

View File

@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.bosh;
import org.springframework.ide.vscode.bosh.models.CloudConfigModel;
import org.springframework.ide.vscode.bosh.models.DynamicModelProvider;
import org.springframework.ide.vscode.bosh.models.StemcellsModel;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProvider;
import org.springframework.ide.vscode.commons.languageserver.hover.VscodeHoverEngine;
@@ -37,13 +38,13 @@ public class BoshLanguageServer extends SimpleLanguageServer {
private final VscodeCompletionEngineAdapter completionEngine;
public BoshLanguageServer(DynamicModelProvider<CloudConfigModel> cloudConfigProvider) {
public BoshLanguageServer(DynamicModelProvider<CloudConfigModel> cloudConfigProvider, DynamicModelProvider<StemcellsModel> stemcellsProvider) {
super("vscode-bosh");
YamlAstCache asts = new YamlAstCache();
SimpleTextDocumentService documents = getTextDocumentService();
ASTTypeCache astTypeCache = new ASTTypeCache();
BoshDeploymentManifestSchema schema = new BoshDeploymentManifestSchema(astTypeCache, cloudConfigProvider);
BoshDeploymentManifestSchema schema = new BoshDeploymentManifestSchema(astTypeCache, cloudConfigProvider, stemcellsProvider);
YamlStructureProvider structureProvider = YamlStructureProvider.DEFAULT;
YamlAssistContextProvider contextProvider = new SchemaBasedYamlAssistContextProvider(schema);

View File

@@ -17,6 +17,9 @@ import org.springframework.ide.vscode.commons.languageserver.LaunguageServerApp;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
LaunguageServerApp.start(() -> new BoshLanguageServer(new BoshCommandCloudConfigProvider()));
LaunguageServerApp.start(() -> new BoshLanguageServer(
new BoshCommandCloudConfigProvider(),
(dc) -> null //TODO: real model provider here!
));
}
}

View File

@@ -0,0 +1,94 @@
/*******************************************************************************
* 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.io.File;
import java.time.Duration;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.ExternalProcess;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
import org.springframework.ide.vscode.commons.yaml.ast.YamlParser;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.representer.Representer;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Abstract base class to aid in implementing a Dynamic model provider that executes a bosh
* command (with `--json`) swtich and then extracts information from its json output.
*/
public abstract class BoshCommandBasedModelProvider<T> implements DynamicModelProvider<T> {
private final YamlParser yamlParser;
protected final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
protected Duration CMD_TIMEOUT = Duration.ofSeconds(10);
protected BoshCommandBasedModelProvider() {
Representer representer = new Representer();
representer.getPropertyUtils().setSkipMissingProperties(true);
yamlParser = new YamlParser(new Yaml());
}
/**
* For deserializing the output from bosh cloud-config command.
*/
public static class BoshCommandResponse {
private String[] blocks;
@JsonProperty("Blocks")
public String[] getBlocks() {
return blocks;
}
public void setBlocks(String[] blocks) {
this.blocks = blocks;
}
}
protected String getBlock() throws Exception {
String out = executeCommand(getCommand());
BoshCommandResponse response = mapper.readValue(out, BoshCommandResponse.class);
String[] blocks = response.getBlocks();
Assert.isLegal(blocks!=null);
Assert.isLegal(blocks.length==1);
return blocks[0];
}
protected JsonNode getJsonTree() throws Exception {
String out = executeCommand(getCommand());
return mapper.readTree(out);
}
protected String executeCommand(ExternalCommand command) throws Exception {
ExternalProcess process = new ExternalProcess(getWorkingDir(), command, true, CMD_TIMEOUT);
String out = process.getOut();
return out;
}
protected File getWorkingDir() {
return new File(".").getAbsoluteFile();
}
protected abstract ExternalCommand getCommand();
protected YamlFileAST parseYaml(String block) throws Exception {
TextDocument doc = new TextDocument(null, LanguageId.BOSH_CLOUD_CONFIG);
doc.setText(block);
YamlFileAST ast = yamlParser.getAST(doc);
return ast;
}
}

View File

@@ -10,30 +10,18 @@
*******************************************************************************/
package org.springframework.ide.vscode.bosh.models;
import java.io.File;
import java.time.Duration;
import java.util.Collection;
import java.util.stream.Stream;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.CollectorUtil;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.ExternalProcess;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
import org.springframework.ide.vscode.commons.yaml.ast.YamlParser;
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
import org.springframework.ide.vscode.commons.yaml.path.YamlTraversal;
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.representer.Representer;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Concrete implementation of {@link CloudConfigProvider} that runs `bosh cloud-config` command
@@ -41,33 +29,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
*
* @author Kris De Volder
*/
public class BoshCommandCloudConfigProvider implements DynamicModelProvider<CloudConfigModel> {
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final YamlParser yamlParser;
private Duration CMD_TIMEOUT = Duration.ofSeconds(10);
public class BoshCommandCloudConfigProvider extends BoshCommandBasedModelProvider<CloudConfigModel> {
public BoshCommandCloudConfigProvider() {
Representer representer = new Representer();
representer.getPropertyUtils().setSkipMissingProperties(true);
yamlParser = new YamlParser(new Yaml());
}
/**
* For deserializing the output from bosh cloud-config command.
*/
public static class CloudConfigResponse {
private String[] blocks;
@JsonProperty("Blocks")
public String[] getBlocks() {
return blocks;
}
public void setBlocks(String[] blocks) {
this.blocks = blocks;
}
}
private static final YamlTraversal VM_TYPE_NAMES = YamlPath.EMPTY
@@ -98,10 +62,8 @@ public class BoshCommandCloudConfigProvider implements DynamicModelProvider<Clou
@Override
public CloudConfigModel getModel(DynamicSchemaContext dc) throws Exception {
String block = getCloudConfigBlock();
TextDocument doc = new TextDocument(null, LanguageId.BOSH_CLOUD_CONFIG);
doc.setText(block);
YamlFileAST ast = yamlParser.getAST(doc);
String block = getBlock();
YamlFileAST ast = parseYaml(block);
return new CloudConfigModel() {
@Override
public Collection<String> getVMTypes() {
@@ -141,15 +103,6 @@ public class BoshCommandCloudConfigProvider implements DynamicModelProvider<Clou
};
}
protected String getCloudConfigBlock() throws Exception{
String out = executeBoshCloudConfigCommand();
CloudConfigResponse response = mapper.readValue(out, CloudConfigResponse.class);
String[] blocks = response.getBlocks();
Assert.isLegal(blocks!=null);
Assert.isLegal(blocks.length==1);
return blocks[0];
}
/**
* Configure how long we wait for the command to fetch cloud config before
* raising timeout exception. (The command may block for long amounts of time
@@ -159,12 +112,9 @@ public class BoshCommandCloudConfigProvider implements DynamicModelProvider<Clou
this.CMD_TIMEOUT = duration;
}
protected String executeBoshCloudConfigCommand() throws Exception {
ExternalCommand command = new ExternalCommand("bosh", "cloud-config", "--json");
ExternalProcess process = new ExternalProcess(new File(".").getAbsoluteFile(), command, true, CMD_TIMEOUT);
System.out.println("executeBoshCloudConfigCommand: "+process);
String out = process.getOut();
return out;
@Override
protected ExternalCommand getCommand() {
return new ExternalCommand("bosh", "cloud-config", "--json");
}
}

View File

@@ -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.Collection;
import java.util.stream.Stream;
import org.springframework.ide.vscode.commons.util.CollectorUtil;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
import org.springframework.ide.vscode.commons.yaml.path.YamlTraversal;
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;
public class BoshCommandStemcellsProvider extends BoshCommandBasedModelProvider<StemcellsModel> {
YamlTraversal STEMCELL_NAMES = YamlPath.EMPTY
.thenValAt("Tables")
.thenAnyChild()
.thenValAt("Rows")
.thenAnyChild()
.thenValAt("name");
@Override
public StemcellsModel getModel(DynamicSchemaContext dc) throws Exception {
JSONCursor cursor = new JSONCursor(getJsonTree());
return new StemcellsModel() {
@Override
public Collection<String> getStemcellNames() {
return getNames(STEMCELL_NAMES);
}
private Collection<String> getNames(YamlTraversal path) {
return path.traverseAmbiguously(cursor)
.flatMap((cursor) -> {
String text = cursor.target.asText();
if (StringUtil.hasText(text)) {
return Stream.of(text);
} else {
return Stream.empty();
}
})
.collect(CollectorUtil.toImmutableSet());
}
};
}
@Override
protected ExternalCommand getCommand() {
return new ExternalCommand("bosh", "stemcells", "--json");
}
}

View File

@@ -3,7 +3,8 @@ package org.springframework.ide.vscode.bosh.models;
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;
/**
* Responsible for somehow obtaining {@link CloudConfigModel} relative to a {@link DynamicSchemaContext}
* Responsible for somehow obtaining some type of `dynamic` model information relative
* to a {@link DynamicSchemaContext}
*/
public interface DynamicModelProvider<T> {
T getModel(DynamicSchemaContext dc) throws Exception;

View File

@@ -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.bosh.models;
import java.util.stream.Stream;
import org.springframework.ide.vscode.commons.yaml.path.YamlNavigable;
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
import org.springframework.ide.vscode.commons.yaml.util.Streams;
import com.fasterxml.jackson.databind.JsonNode;
/**
* Allows using {@link YamlPath} / {@link YamlNavigable} on {@link JsonNode}s
*/
public class JSONCursor implements YamlNavigable<JSONCursor> {
public final JsonNode target;
public JSONCursor(JsonNode target) {
super();
this.target = target;
}
@Override
public Stream<JSONCursor> traverseAmbiguously(YamlPathSegment s) {
return oneStep(s).map(JSONCursor::new);
}
private Stream<JsonNode> oneStep(YamlPathSegment s) {
if (target==null) {
return Stream.empty();
}
switch (s.getType()) {
case KEY_AT_KEY: {
return Streams.fromNullable(target.get(s.toPropString()));
}
case ANY_CHILD: {
return Streams.fromIterable(target);
}
case VAL_AT_INDEX: {
return Streams.fromNullable(target.get(s.toIndex()));
}
case VAL_AT_KEY: {
return Streams.fromNullable(target.get(s.toPropString()));
}
default:
throw new IllegalStateException("Missing case for "+s.getType());
}
}
@Override
public String toString() {
return ""+target;
}
}

View File

@@ -0,0 +1,22 @@
/*******************************************************************************
* 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.Collection;
/**
* Represents Stemcells information as might be retrieved from bosh director.
*/
public interface StemcellsModel {
Collection<String> getStemcellNames();
}

View File

@@ -15,6 +15,7 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.ide.vscode.bosh.mocks.MockCloudConfigProvider;
import org.springframework.ide.vscode.bosh.models.BoshCommandBasedModelProvider;
import org.springframework.ide.vscode.bosh.models.BoshCommandCloudConfigProvider;
import org.springframework.ide.vscode.bosh.models.CloudConfigModel;
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;
@@ -23,13 +24,13 @@ import com.google.common.collect.ImmutableMultiset;
public class BoshCommandCloudConfigProviderTest {
public final MockCloudConfigProvider mockProvider = new MockCloudConfigProvider();
public final BoshCommandCloudConfigProvider mockProvider = new MockCloudConfigProvider();
// For local testing only... in CI builds we don't have the means to use a real bosh director and cli.
// private BoshCommandCloudConfigProvider realProvider = new BoshCommandCloudConfigProvider();
@Test public void getVMTypes() throws Exception {
BoshCommandCloudConfigProvider provider = mockProvider;
BoshCommandBasedModelProvider<CloudConfigModel> provider = mockProvider;
DynamicSchemaContext dc = Mockito.mock(DynamicSchemaContext.class);
CloudConfigModel cloudConfig = provider.getModel(dc);

View File

@@ -20,7 +20,10 @@ import java.util.concurrent.TimeoutException;
import org.eclipse.lsp4j.CompletionItem;
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.DynamicModelProvider;
import org.springframework.ide.vscode.bosh.models.StemcellsModel;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
@@ -31,10 +34,11 @@ public class BoshEditorTest {
LanguageServerHarness harness;
private MockCloudConfigProvider cloudConfigProvider = new MockCloudConfigProvider();
private DynamicModelProvider<StemcellsModel> stemcellsProvider = Mockito.mock(DynamicModelProvider.class);
@Before public void setup() throws Exception {
harness = new LanguageServerHarness(() -> {
return new BoshLanguageServer(cloudConfigProvider)
return new BoshLanguageServer(cloudConfigProvider, stemcellsProvider)
.setMaxCompletions(100);
},
LanguageId.BOSH_DEPLOYMENT
@@ -561,6 +565,20 @@ public class BoshEditorTest {
editor.assertCompletionLabels("certificate", "password", "rsa", "ssh");
}
@Test public void variablesBlockReconciling() throws Exception {
Editor editor = harness.newEditor(
"variables:\n" +
"- name: admin-passcode\n" +
" type: something-that-might-work-in-theory\n" + //shouldn't be a warning/error
" bogus-propt: bah\n" +
" options: {}"
);
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
editor.assertProblems(
"bogus-propt|Unknown property"
);
}
@Test public void variablesBlockHovers() throws Exception {
Editor editor = harness.newEditor(
"variables:\n" +

View File

@@ -19,7 +19,9 @@ import java.nio.file.Paths;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.ide.vscode.bosh.mocks.MockCloudConfigProvider;
import org.springframework.ide.vscode.bosh.models.DynamicModelProvider;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
public class BoshLanguageServerTest {
@@ -31,7 +33,7 @@ public class BoshLanguageServerTest {
@Test
public void createAndInitializeServerWithWorkspace() throws Exception {
LanguageServerHarness harness = new LanguageServerHarness(() ->
new BoshLanguageServer(new MockCloudConfigProvider())
new BoshLanguageServer(new MockCloudConfigProvider(), Mockito.mock(DynamicModelProvider.class))
);
File workspaceRoot = getTestResource("/workspace/");
assertExpectedInitResult(harness.intialize(workspaceRoot));
@@ -41,7 +43,7 @@ public class BoshLanguageServerTest {
public void createAndInitializeServerWithoutWorkspace() throws Exception {
File workspaceRoot = null;
LanguageServerHarness harness = new LanguageServerHarness(() ->
new BoshLanguageServer(new MockCloudConfigProvider())
new BoshLanguageServer(new MockCloudConfigProvider(), Mockito.mock(DynamicModelProvider.class))
);
assertExpectedInitResult(harness.intialize(workspaceRoot));
}

View File

@@ -14,6 +14,7 @@ import java.util.concurrent.Callable;
import org.springframework.ide.vscode.bosh.BoshCommandCloudConfigProviderTest;
import org.springframework.ide.vscode.bosh.models.BoshCommandCloudConfigProvider;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.IOUtil;
public final class MockCloudConfigProvider extends BoshCommandCloudConfigProvider {
@@ -33,15 +34,15 @@ public final class MockCloudConfigProvider extends BoshCommandCloudConfigProvide
* without requiring a real bosh setup.
*/
@Override
protected String executeBoshCloudConfigCommand() throws Exception {
protected String executeCommand(ExternalCommand cmd) throws Exception {
readCount++;
return cloudConfigCmdExecutor.call();
}
@Override
protected String getCloudConfigBlock() throws Exception {
protected String getBlock() throws Exception {
if (reader==null) {
return super.getCloudConfigBlock();
return super.getBlock();
}
readCount++;
return reader.call();

View File

@@ -0,0 +1,45 @@
/*******************************************************************************
* 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 static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.ide.vscode.bosh.BoshCommandCloudConfigProviderTest;
import org.springframework.ide.vscode.commons.util.IOUtil;
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;
import com.google.common.collect.ImmutableSet;
public class BoshCommandStemcellsProviderTest {
private static final String MOCK_DATA_RSRC = "/cmd-out/stemcells.json";;
public BoshCommandStemcellsProvider provider = Mockito.spy(BoshCommandStemcellsProvider.class);
@Before
public void settup() throws Exception {
Mockito.doReturn(IOUtil.toString(BoshCommandCloudConfigProviderTest.class.getResourceAsStream(MOCK_DATA_RSRC)))
.when(provider).executeCommand(Mockito.any());
}
@Test public void getStemcellNames() throws Exception {
assertEquals(ImmutableSet.of(
"bosh-vsphere-esxi-centos-7-go_agent",
"bosh-vsphere-esxi-ubuntu-trusty-go_agent"
),
provider.getModel(Mockito.mock(DynamicSchemaContext.class))
.getStemcellNames()
);
}
}

View File

@@ -0,0 +1,38 @@
{
"Tables": [
{
"Content": "stemcells",
"Header": {
"cid": "CID",
"cpi": "CPI",
"name": "Name",
"os": "OS",
"version": "Version"
},
"Rows": [
{
"cid": "sc-cd694110-4b23-4361-b5e7-b817874eadca",
"cpi": "",
"name": "bosh-vsphere-esxi-centos-7-go_agent",
"os": "centos-7",
"version": "3421.11"
},
{
"cid": "sc-3378b7e1-5a80-4351-b521-7e9aeeb417bc",
"cpi": "",
"name": "bosh-vsphere-esxi-ubuntu-trusty-go_agent",
"os": "ubuntu-trusty",
"version": "3421.11"
}
],
"Notes": [
"(*) Currently deployed"
]
}
],
"Blocks": null,
"Lines": [
"Using environment '10.194.4.35' as client 'admin'",
"Succeeded"
]
}

View File

@@ -11,6 +11,7 @@
package org.springframework.ide.vscode.commons.util;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import java.util.function.BiConsumer;
@@ -62,7 +63,7 @@ public class CollectorUtil {
@Override
public Set<Collector.Characteristics> characteristics() {
return ImmutableSet.of(Collector.Characteristics.UNORDERED);
return EnumSet.of(Collector.Characteristics.UNORDERED);
}
};
}
@@ -94,7 +95,39 @@ public class CollectorUtil {
@Override
public Set<Collector.Characteristics> characteristics() {
return ImmutableSet.of(Collector.Characteristics.UNORDERED);
return EnumSet.of(Collector.Characteristics.UNORDERED);
}
};
}
public static <T> Collector<T, ArrayList<T>, ImmutableSet<T>> toImmutableSet() {
return new Collector<T, ArrayList<T>, ImmutableSet<T>>() {
@Override
public Supplier<ArrayList<T>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<ArrayList<T>, T> accumulator() {
return (a, e) -> a.add(e);
}
@Override
public BinaryOperator<ArrayList<T>> combiner() {
return (a1, a2) -> {
a1.addAll(a2);
return a1;
};
}
@Override
public Function<ArrayList<T>, ImmutableSet<T>> finisher() {
return ImmutableSet::copyOf;
}
@Override
public Set<Collector.Characteristics> characteristics() {
return EnumSet.of(Collector.Characteristics.UNORDERED);
}
};
}

View File

@@ -8,12 +8,12 @@
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.yaml.util;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Streams {
@@ -35,4 +35,8 @@ public class Streams {
return e==null ? Stream.empty() : Stream.of(e);
}
public static <T> Stream<T> fromIterable(Iterable<T> target) {
return StreamSupport.stream(target.spliterator(), false);
}
}