Add support for 'docker' attribute to CF editor

This commit is contained in:
Kris De Volder
2019-07-23 11:43:41 -07:00
parent b9c491466f
commit 32d1e6fd36
8 changed files with 155 additions and 11 deletions

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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");
}
//////////////////////////////////////////////////////////////////////////////

View File

@@ -42,6 +42,7 @@ public class ManifestYmlSchemaTest {
"buildpacks",
"command",
"disk_quota",
"docker",
"domain",
"domains",
"env",

View File

@@ -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;

View File

@@ -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();

View File

@@ -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