Make put/get resource name conditional on absence of explicit resource attribute

This commit is contained in:
Kris De Volder
2017-01-29 12:35:42 -08:00
parent f615f171d1
commit 4df86968c6
3 changed files with 217 additions and 9 deletions

View File

@@ -44,7 +44,7 @@ import com.google.common.collect.ImmutableSet;
*/
public class YTypeFactory {
public YType contextAware(String name, SchemaContextAware<YType> guessType) {
public YContextSensitive contextAware(String name, SchemaContextAware<YType> guessType) {
return new YContextSensitive(name, guessType);
}
@@ -180,8 +180,9 @@ public class YTypeFactory {
addHintProvider((DynamicSchemaContext dc) -> hintProvider);
}
public void addHintProvider(SchemaContextAware<Callable<Collection<YValueHint>>> hintProvider) {
public AbstractType addHintProvider(SchemaContextAware<Callable<Collection<YValueHint>>> hintProvider) {
this.hintProvider = hintProvider;
return this;
}
public YValueHint[] getHintValues(DynamicSchemaContext dc) throws Exception {
@@ -307,12 +308,15 @@ public class YTypeFactory {
/**
* Represents a type that depends on the DynamicSchemaContext
*/
public static class YContextSensitive extends YAny {
public static class YContextSensitive extends AbstractType {
private final SchemaContextAware<YType> typeGuesser;
private final String name;
boolean treatAsAtomic = false;
public YContextSensitive(String name, SchemaContextAware<YType> typeGuesser) {
super(name);
this.name = name;
this.typeGuesser = typeGuesser;
}
@@ -327,6 +331,38 @@ public class YTypeFactory {
return this;
}
@Override
public boolean isAtomic() {
return true;
}
@Override
public boolean isSequenceable() {
return !treatAsAtomic;
}
@Override
public boolean isMap() {
return !treatAsAtomic;
}
@Override
public String toString() {
return name;
}
/**
* If set to false (which is the default), then this type (when not yet inferred to a
* more specific version of itself) will be treated as if it can be anything (i.e atomic, map or sequence)
* <p>
* If set to true, then it is treated as strictly atomic type instead (i.e it isn't valid to
* use a map or sequence for its value).
*/
public YContextSensitive treatAsAtomic(boolean isAtomic) {
this.treatAsAtomic = isAtomic;
return this;
}
}

View File

@@ -16,6 +16,7 @@ import java.util.stream.Collectors;
import org.springframework.ide.vscode.commons.util.MimeTypes;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables;
import org.springframework.ide.vscode.commons.util.ValueParser;
import org.springframework.ide.vscode.commons.util.ValueParsers;
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
@@ -36,6 +37,7 @@ import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil;
import org.springframework.ide.vscode.commons.yaml.schema.YTypedProperty;
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
import org.springframework.ide.vscode.commons.yaml.schema.YamlSchema;
import org.yaml.snakeyaml.nodes.Node;
/**
* @author Kris De Volder
@@ -196,9 +198,19 @@ public class PipelineYmlSchema implements YamlSchema {
addProp(task, "params", t_string_params);
task.requireOneOf("image_resource", "image");
AbstractType t_put_get_name = f.contextAware("Name", (dc) -> {
if (getParentPropertyNode("resource", models, dc)!=null) {
return null;
} else {
return t_resource_name;
}
})
.treatAsAtomic(true)
.parseWith(ValueParsers.NE_STRING);
YBeanType getStep = f.ybean("GetStep");
addProp(getStep, "get", t_resource_name);
addProp(getStep, "resource", t_string);
addProp(getStep, "get", t_put_get_name);
addProp(getStep, "resource", t_resource_name);
addProp(getStep, "version", t_version);
addProp(getStep, "passed", f.yseq(t_job_name));
addProp(getStep, "params", f.contextAware("GetParams", (dc) ->
@@ -207,7 +219,7 @@ public class PipelineYmlSchema implements YamlSchema {
addProp(getStep, "trigger", t_boolean);
YBeanType putStep = f.ybean("PutStep");
addProp(putStep, "put", t_resource_name);
addProp(putStep, "put", t_put_get_name);
addProp(putStep, "resource", t_resource_name);
addProp(putStep, "params", f.contextAware("PutParams", (dc) ->
resourceTypes.getOutParamsType(getResourceType("put", models, dc))
@@ -441,7 +453,10 @@ public class PipelineYmlSchema implements YamlSchema {
}
private String getResourceType(String resourceNameProp, ConcourseModel models, DynamicSchemaContext dc) {
String resourceName = getParentPropertyValue(resourceNameProp, models, dc);
String resourceName = getParentPropertyValue("resource", models, dc);
if (resourceName==null) {
resourceName = getParentPropertyValue(resourceNameProp, models, dc);
}
if (resourceName!=null) {
return models.getResourceType(dc.getDocument(), resourceName);
}
@@ -453,11 +468,15 @@ public class PipelineYmlSchema implements YamlSchema {
}
private String getParentPropertyValue(String propName, ConcourseModel models, DynamicSchemaContext dc) {
return NodeUtil.asScalar(getParentPropertyNode(propName, models, dc));
}
private Node getParentPropertyNode(String propName, ConcourseModel models, DynamicSchemaContext dc) {
YamlPath path = dc.getPath();
if (path!=null) {
YamlFileAST root = models.getSafeAst(dc.getDocument());
if (root!=null) {
return NodeUtil.asScalar(path.dropLast().append(YamlPathSegment.valueAt(propName)).traverseToNode(root));
return path.dropLast().append(YamlPathSegment.valueAt(propName)).traverseToNode(root);
}
}
return null;

View File

@@ -1603,6 +1603,159 @@ public class ConcourseEditorTest {
editor.assertHoverContains("remove", "remove the given lock from the pool");
}
@Test public void reconcileExplicitResourceAttributeInPutStep() throws Exception {
//See: https://www.pivotaltracker.com/story/show/138568839
Editor editor;
editor = harness.newEditor(
"resources:\n" +
"- name: aws-environments\n" +
" type: pool\n" +
"jobs:\n" +
"- name: test-multi-aws\n" +
" plan:\n" +
" - put: environment-1\n" +
" resource: aws-environments\n" +
" params:\n" +
" acquire: true\n" +
" bogus_param: bad\n" +
" get_params:\n" +
" bogus_get_param: bad"
);
editor.assertProblems(
"bogus_param|Unknown property",
"bogus_get_param|Unknown property"
);
editor = harness.newEditor(
"resources:\n" +
"- name: aws-environments\n" +
" type: pool\n" +
"jobs:\n" +
"- name: test-multi-aws\n" +
" plan:\n" +
" - get: environment-1\n" +
" resource: aws-environments\n" +
" params:\n" +
" bogus_param: bad\n"
);
editor.assertProblems(
"bogus_param|Unknown property"
);
editor = harness.newEditor(
"resources:\n" +
"- name: aws-environments\n" +
" type: pool\n" +
" source:\n" +
" uri: git@github.com:concourse/locks.git\n" +
" branch: master\n" +
" pool: aws\n" +
" private_key: |\n" +
" -----BEGIN RSA PRIVATE KEY-----\n" +
" MIIEowIBAAKCAQEAtCS10/f7W7lkQaSgD/mVeaSOvSF9ql4hf/zfMwfVGgHWjj+W\n" +
" ...\n" +
" DWiJL+OFeg9kawcUL6hQ8JeXPhlImG6RTUffma9+iGQyyBMCGd1l\n" +
" -----END RSA PRIVATE KEY-----\n" +
" username: jonhsmith\n" +
" password: his-password\n" +
" retry_delay: 10s\n" +
"jobs:\n" +
"- name: test-multi-aws\n" +
" plan:\n" +
" - get: aws-environments\n" +
" params: {} \n" +
" - put: environment-1\n" +
" resource: aws-environments\n" +
" params: {acquire: true}\n" +
" - put: environment-2\n" +
" resource: aws-environments\n" +
" params: \n" +
" acquire: true\n" +
" bogus_param: blah\n" +
" - task: test-multi-aws\n" +
" file: my-scripts/test-multi-aws.yml\n" +
" - put: aws-environments\n" +
" params: {release: environment-1}\n" +
" - put: aws-environments\n" +
" params: {release: environment-2}"
);
editor.assertProblems(
"bogus_param|Unknown property"
);
}
@Test
public void resourceNameContentAssist() throws Exception {
String conText;
conText =
"resources:\n" +
"- name: foo-resource\n" +
"- name: bar-resource\n" +
"- name: other-resource\n" +
"jobs:\n" +
"- name: test-multi-aws\n" +
" plan:\n" +
" - <*>";
assertContextualCompletions(conText
, // ==============
"get: <*>"
,
"get: bar-resource<*>",
"get: foo-resource<*>",
"get: other-resource<*>"
);
assertContextualCompletions(conText
, // ==============
"put: <*>"
, // ==>
"put: bar-resource<*>",
"put: foo-resource<*>",
"put: other-resource<*>"
);
conText =
"resources:\n" +
"- name: foo-resource\n" +
"- name: bar-resource\n" +
"- name: other-resource\n" +
"jobs:\n" +
"- name: test-multi-aws\n" +
" plan:\n" +
" - put: something\n" +
" <*>";
assertContextualCompletions(conText
, // ==============
"resource: <*>"
, // ==>
"resource: bar-resource<*>",
"resource: foo-resource<*>",
"resource: other-resource<*>"
);
conText =
"resources:\n" +
"- name: foo-resource\n" +
"- name: bar-resource\n" +
"- name: other-resource\n" +
"jobs:\n" +
"- name: test-multi-aws\n" +
" plan:\n" +
" - <*>\n" +
" resource: foo-resource\n"; // presence of explicit 'resource' attribute should disable treating the name in put/get as a resource-name
assertContextualCompletions(conText,
"put: <*>"
// ==> NONE
);
assertContextualCompletions(conText,
"get: <*>"
// ==> NONE
);
}
@Test
public void gotoResourceDefinition() throws Exception {
Editor editor = harness.newEditor(