Add support for 'docker' attribute to CF editor
This commit is contained in:
@@ -50,6 +50,7 @@ import org.springframework.ide.vscode.commons.yaml.reconcile.ASTTypeCache;
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.TypeBasedYamlSymbolHandler;
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaBasedReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
|
||||
import org.springframework.ide.vscode.commons.yaml.snippet.SchemaBasedSnippetGenerator;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -80,6 +81,7 @@ public class ManifestYamlLanguageServerInitializer implements InitializingBean {
|
||||
YamlASTProvider parser = new YamlParser();
|
||||
|
||||
schema = new ManifestYmlSchema(getHintProviders());
|
||||
enableSnippets(schema, true);
|
||||
|
||||
YamlStructureProvider structureProvider = YamlStructureProvider.DEFAULT;
|
||||
YamlAssistContextProvider contextProvider = new SchemaBasedYamlAssistContextProvider(schema);
|
||||
@@ -194,6 +196,15 @@ public class ManifestYamlLanguageServerInitializer implements InitializingBean {
|
||||
};
|
||||
}
|
||||
|
||||
public void enableSnippets(ManifestYmlSchema schema, boolean enable) {
|
||||
//TODO: move to where schema bean is defined?
|
||||
if (enable) {
|
||||
schema.f.setSnippetProvider(new SchemaBasedSnippetGenerator(schema.getTypeUtil(), server::createSnippetBuilder));
|
||||
} else {
|
||||
schema.f.setSnippetProvider(null);
|
||||
}
|
||||
}
|
||||
|
||||
private CFTargetCache getCfTargetCache() {
|
||||
return this.cfTargetCache;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.YTypedPro
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YamlSchema;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.constraints.Constraints;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -54,9 +55,10 @@ public final class ManifestYmlSchema implements YamlSchema {
|
||||
private final YAtomicType t_application_name;
|
||||
|
||||
private ImmutableList<YType> definitionTypes = null;
|
||||
public final YTypeFactory f;
|
||||
|
||||
private static final Set<String> TOPLEVEL_EXCLUDED = ImmutableSet.of(
|
||||
"name", "host", "hosts", "routes"
|
||||
"name", "host", "hosts", "routes", "docker"
|
||||
);
|
||||
|
||||
@Override
|
||||
@@ -106,7 +108,7 @@ public final class ManifestYmlSchema implements YamlSchema {
|
||||
Callable<Collection<YValueHint>> stacksProvider = providers.getStacksProvider();
|
||||
|
||||
|
||||
YTypeFactory f = new YTypeFactory();
|
||||
f = new YTypeFactory();
|
||||
TYPE_UTIL = f.TYPE_UTIL;
|
||||
|
||||
// define schema types
|
||||
@@ -188,6 +190,10 @@ public final class ManifestYmlSchema implements YamlSchema {
|
||||
|
||||
AbstractType t_host = f.yatomic("Host").parseWith(ValueParsers.NE_STRING);
|
||||
|
||||
YType t_docker = f.ybean("Docker",
|
||||
f.yprop("image", t_ne_string).isRequired(true).setDescriptionProvider(descriptionFor("docker")),
|
||||
f.yprop("username", t_ne_string).setDescriptionProvider(descriptionFor("docker"))
|
||||
);
|
||||
YTypedPropertyImpl[] props = {
|
||||
f.yprop("buildpack", t_buildpack),
|
||||
//TODO: replace the above with the below to make 'buildpack' deprecated once we have proper support for `buildpacks` in cf push.
|
||||
@@ -196,6 +202,7 @@ public final class ManifestYmlSchema implements YamlSchema {
|
||||
f.yprop("buildpacks", f.yseq(t_buildpack)),
|
||||
f.yprop("command", t_string),
|
||||
f.yprop("disk_quota", t_memory),
|
||||
f.yprop("docker", t_docker),
|
||||
f.yprop("domain", t_domain),
|
||||
f.yprop("domains", f.yseq(t_domain)),
|
||||
f.yprop("env", t_env),
|
||||
@@ -226,6 +233,9 @@ public final class ManifestYmlSchema implements YamlSchema {
|
||||
}
|
||||
application.addProperty(prop);
|
||||
}
|
||||
application.require(Constraints.mutuallyExclusive("docker", "path"));
|
||||
application.require(Constraints.mutuallyExclusive("docker", "buildpack"));
|
||||
application.require(Constraints.mutuallyExclusive("docker", "buildpacks"));
|
||||
}
|
||||
|
||||
private Renderable descriptionFor(String propName) {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
If your app is contained in a Docker image, then you may use the `docker` attribute to specify it and an optional Docker `username`.
|
||||
|
||||
This attribute is a combination of `push` options that include `--docker-image` and `--docker-username`.
|
||||
|
||||
```
|
||||
---
|
||||
...
|
||||
docker:
|
||||
image: docker-image-repository/docker-image-name
|
||||
username: docker-user-name
|
||||
```
|
||||
|
||||
The command line option `--docker-image` or `-o` overrides `docker.image`. The command line option `--docker-username` overrides `docker.username`.
|
||||
|
||||
The manifest attribute `docker.username` is optional. If it is used, then the password must be provided in the environment variable `CF_DOCKER_PASSWORD`. Additionally, if a Docker username is specified, then a Docker image must also be specified.
|
||||
|
||||
@@ -442,6 +442,11 @@ public class ManifestYamlEditorTest {
|
||||
// ---------------
|
||||
"applications:\n" +
|
||||
"- name: foo\n" +
|
||||
" docker:\n" +
|
||||
" image: <*>",
|
||||
// ---------------
|
||||
"applications:\n" +
|
||||
"- name: foo\n" +
|
||||
" domain: <*>",
|
||||
// ---------------
|
||||
"applications:\n" +
|
||||
@@ -1787,7 +1792,7 @@ public class ManifestYamlEditorTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void gotoSymbolInPipeline() throws Exception {
|
||||
@Test public void gotoSymbolInDocument() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: my-app\n" +
|
||||
@@ -1979,7 +1984,80 @@ public class ManifestYamlEditorTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dockerAttributesValidation() throws Exception {
|
||||
Editor editor;
|
||||
|
||||
editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: my-app\n" +
|
||||
" docker:\n" +
|
||||
" image: docker-image-repository/docker-image-name\n" +
|
||||
" bogus: bad"
|
||||
);
|
||||
editor.assertProblems("bogus|Unknown");
|
||||
|
||||
editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: my-app\n" +
|
||||
" docker:\n" +
|
||||
" username: myself\n"
|
||||
);
|
||||
editor.assertProblems(
|
||||
"docker|'image' is required"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: my-app\n" +
|
||||
" buildpacks:\n" +
|
||||
" - java-buildpack\n" +
|
||||
" docker:\n" +
|
||||
" image: somewhere/someimage\n"
|
||||
);
|
||||
editor.assertProblems(
|
||||
"buildpacks|Only one of 'docker' and 'buildpacks'",
|
||||
"docker|Only one of 'docker' and 'buildpacks'"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: my-app\n" +
|
||||
" buildpack: java-buildpack\n" +
|
||||
" docker:\n" +
|
||||
" image: somewhere/someimage\n"
|
||||
);
|
||||
editor.assertProblems(
|
||||
"buildpack|Only one of 'docker' and 'buildpack'",
|
||||
"docker|Only one of 'docker' and 'buildpack'"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: my-app\n" +
|
||||
" path: /somehere/in/filesystem\n" +
|
||||
" docker:\n" +
|
||||
" image: somewhere/someimage\n"
|
||||
);
|
||||
editor.assertProblems(
|
||||
"path|Only one of 'docker' and 'path'",
|
||||
"docker|Only one of 'docker' and 'path'"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dockerAttributesHovers() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- name: my-app\n" +
|
||||
" docker:\n" +
|
||||
" image: docker-image-repository/docker-image-name\n" +
|
||||
" username: myself"
|
||||
);
|
||||
editor.assertHoverContains("docker", "If your app is contained in a Docker image");
|
||||
editor.assertHoverContains("image", "Docker image");
|
||||
editor.assertHoverContains("username", "If your app is contained in a Docker image");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ public class ManifestYmlSchemaTest {
|
||||
"buildpacks",
|
||||
"command",
|
||||
"disk_quota",
|
||||
"docker",
|
||||
"domain",
|
||||
"domains",
|
||||
"env",
|
||||
|
||||
@@ -10,19 +10,14 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.editor.harness;
|
||||
|
||||
import org.springframework.ide.vscode.boot.metadata.FuzzyMapPropertyInfo;
|
||||
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
|
||||
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.commons.util.FuzzyMap;
|
||||
|
||||
public class AdHocPropertyHarness {
|
||||
|
||||
private FuzzyMap<PropertyInfo> adHocProperties = new FuzzyMap<PropertyInfo>() {
|
||||
@Override
|
||||
protected String getKey(PropertyInfo entry) {
|
||||
return entry.getId();
|
||||
}
|
||||
};
|
||||
private FuzzyMap<PropertyInfo> adHocProperties = new FuzzyMapPropertyInfo();
|
||||
|
||||
protected final ProjectBasedPropertyIndexProvider adHocIndexProvider = project -> adHocProperties;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
|
||||
*
|
||||
*/
|
||||
public class IndexNavigatorTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimple() throws Exception {
|
||||
PropertyIndexHarness harness = indexHarness();
|
||||
|
||||
@@ -71,6 +71,39 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Ignore //Ignored because this bug is not yet fixed so the test fails.
|
||||
@Test public void bug_GH_327() throws Exception {
|
||||
//See https://github.com/spring-projects/sts4/issues/327
|
||||
data("spring.resources.static-locations", "java.lang.String[]", null, "Blah");
|
||||
data("spring.devtools.restart.additional-paths", "java.util.List<java.lang.String>", null, "Blah blah");
|
||||
|
||||
Editor editor;
|
||||
|
||||
editor = harness.newEditor(
|
||||
"spring:\n" +
|
||||
" resources:\n" +
|
||||
" static_locations: []\n" +
|
||||
" devtools:\n" +
|
||||
" restart:\n" +
|
||||
" additional_paths: []\n"
|
||||
);
|
||||
editor.assertProblems(/*NONE*/);
|
||||
|
||||
//Also check whether reconciler understands the structure when inside of a 'relaxed' name key
|
||||
editor = harness.newEditor(
|
||||
"spring:\n" +
|
||||
" resources:\n" +
|
||||
" static_locations: not-a-list-1\n" +
|
||||
" devtools:\n" +
|
||||
" restart:\n" +
|
||||
" additional_paths: not-a-list-2\n"
|
||||
);
|
||||
editor.assertProblems(
|
||||
"not-a-list-1|XXXX", //TODO: fill in proper expected message instead of XXXX
|
||||
"not-a-list-2|XXXX" //TODO: fill in proper expected message instead of XXXX
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void bug_165724475() throws Exception {
|
||||
//See:
|
||||
// https://www.pivotaltracker.com/story/show/165724475
|
||||
|
||||
Reference in New Issue
Block a user