From 005fbcbfda2707e1f68f9d093640866346d2c016 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Fri, 3 May 2019 12:35:57 -0700 Subject: [PATCH] Add S3Source.initial_version and related props to Schema --- .../yaml/schema/constraints/Constraints.java | 24 +++++++- .../vscode/concourse/PipelineYmlSchema.java | 8 +++ .../desc/S3Source/initial_content_binary.md | 15 +++++ .../desc/S3Source/initial_content_text.md | 15 +++++ .../resources/desc/S3Source/initial_path.md | 15 +++++ .../desc/S3Source/initial_version.md | 15 +++++ .../vscode/concourse/ConcourseEditorTest.java | 57 ++++++++++++++++++- 7 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_binary.md create mode 100644 headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_text.md create mode 100644 headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_path.md create mode 100644 headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_version.md diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/constraints/Constraints.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/constraints/Constraints.java index ac09349bd..aa27cf4da 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/constraints/Constraints.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/constraints/Constraints.java @@ -10,7 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.commons.yaml.schema.constraints; -import static org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems.EXTRA_PROPERTY; +import static org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems.*; import static org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems.missingProperty; import static org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems.problem; @@ -46,6 +46,26 @@ import com.google.common.collect.Multimap; * @author Kris De Volder */ public class Constraints { + + public static Constraint implies(String foundProperty, String requiredProperty) { + return (DynamicSchemaContext dc, Node parent, Node node, YType type, IProblemCollector problems) -> { + if (node instanceof MappingNode) { + MappingNode map = (MappingNode) node; + Set foundProps = dc.getDefinedProperties(); + if (foundProps.contains(foundProperty) && !foundProps.contains(requiredProperty)) { + for (NodeTuple tup : map.getValue()) { + Node keyNode = tup.getKeyNode(); + String key = NodeUtil.asScalar(keyNode); + if (foundProperty.equals(key)) { + problems.accept(problem(MISSING_PROPERTY, + "Property '"+foundProperty+"' assumes that '"+requiredProperty+"' is also defined", keyNode + )); + } + } + } + } + }; + } public static Constraint requireOneOf(String... properties) { return new RequireOneOf(properties); @@ -150,7 +170,7 @@ public class Constraints { for (NodeTuple tup : map.getValue()) { Node keyNode = tup.getKeyNode(); String key = NodeUtil.asScalar(keyNode); - if (p1.equals(key) || p1.equals(key)) { + if (p1.equals(key) || p2.equals(key)) { problems.accept(problem(EXTRA_PROPERTY, "Only one of '"+p1+"' and '"+p2+"' should be defined for '"+type+"'", keyNode )); diff --git a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java index 81ea15ad4..aa06baa3d 100644 --- a/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java +++ b/headless-services/concourse-language-server/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java @@ -582,6 +582,14 @@ public class PipelineYmlSchema implements YamlSchema { addProp(source, "regexp", t_ne_string); addProp(source, "versioned_file", t_ne_string); source.requireOneOf("regexp", "versioned_file"); + addProp(source, "initial_path", t_ne_string); + addProp(source, "initial_version", t_ne_string); + source.require(Constraints.mutuallyExclusive("initial_path", "initial_version")); + source.require(Constraints.implies("initial_version", "versioned_file")); + source.require(Constraints.implies("initial_path", "regexp")); + addProp(source, "initial_content_text", t_ne_string); + addProp(source, "initial_content_binary", t_ne_string); + source.require(Constraints.mutuallyExclusive("initial_content_text", "initial_content_binary")); AbstractType get = f.ybean("S3GetParams"); addProp(get, "unpack", t_boolean); diff --git a/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_binary.md b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_binary.md new file mode 100644 index 000000000..de280b624 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_binary.md @@ -0,0 +1,15 @@ +### Initial state + +If no resource versions exist you can set up this resource to emit an initial version with a specified content. This won't create a real resource in S3 but only create an initial version for Concourse. The resource file will be created as usual when you `get` a resource with an initial version. + +You can define one of the following two options: + +* `initial_path`: *Optional.* Must be used with the `regexp` option. You should set this to the file path containing the initial version which would match the given regexp. E.g. if `regexp` is `file/build-(.*).zip`, then `initial_path` might be `file/build-0.0.0.zip`. The resource version will be `0.0.0` in this case. + +* `initial_version`: *Optional.* Must be used with the `versioned_file` option. This will be the resource version. + +By default the resource file will be created with no content when `get` runs. You can set the content by using one of the following options: + +* `initial_content_text`: *Optional.* Initial content as a string. + +* `initial_content_binary`: *Optional.* You can pass binary content as a base64 encoded string. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_text.md b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_text.md new file mode 100644 index 000000000..de280b624 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_content_text.md @@ -0,0 +1,15 @@ +### Initial state + +If no resource versions exist you can set up this resource to emit an initial version with a specified content. This won't create a real resource in S3 but only create an initial version for Concourse. The resource file will be created as usual when you `get` a resource with an initial version. + +You can define one of the following two options: + +* `initial_path`: *Optional.* Must be used with the `regexp` option. You should set this to the file path containing the initial version which would match the given regexp. E.g. if `regexp` is `file/build-(.*).zip`, then `initial_path` might be `file/build-0.0.0.zip`. The resource version will be `0.0.0` in this case. + +* `initial_version`: *Optional.* Must be used with the `versioned_file` option. This will be the resource version. + +By default the resource file will be created with no content when `get` runs. You can set the content by using one of the following options: + +* `initial_content_text`: *Optional.* Initial content as a string. + +* `initial_content_binary`: *Optional.* You can pass binary content as a base64 encoded string. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_path.md b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_path.md new file mode 100644 index 000000000..de280b624 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_path.md @@ -0,0 +1,15 @@ +### Initial state + +If no resource versions exist you can set up this resource to emit an initial version with a specified content. This won't create a real resource in S3 but only create an initial version for Concourse. The resource file will be created as usual when you `get` a resource with an initial version. + +You can define one of the following two options: + +* `initial_path`: *Optional.* Must be used with the `regexp` option. You should set this to the file path containing the initial version which would match the given regexp. E.g. if `regexp` is `file/build-(.*).zip`, then `initial_path` might be `file/build-0.0.0.zip`. The resource version will be `0.0.0` in this case. + +* `initial_version`: *Optional.* Must be used with the `versioned_file` option. This will be the resource version. + +By default the resource file will be created with no content when `get` runs. You can set the content by using one of the following options: + +* `initial_content_text`: *Optional.* Initial content as a string. + +* `initial_content_binary`: *Optional.* You can pass binary content as a base64 encoded string. diff --git a/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_version.md b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_version.md new file mode 100644 index 000000000..de280b624 --- /dev/null +++ b/headless-services/concourse-language-server/src/main/resources/desc/S3Source/initial_version.md @@ -0,0 +1,15 @@ +### Initial state + +If no resource versions exist you can set up this resource to emit an initial version with a specified content. This won't create a real resource in S3 but only create an initial version for Concourse. The resource file will be created as usual when you `get` a resource with an initial version. + +You can define one of the following two options: + +* `initial_path`: *Optional.* Must be used with the `regexp` option. You should set this to the file path containing the initial version which would match the given regexp. E.g. if `regexp` is `file/build-(.*).zip`, then `initial_path` might be `file/build-0.0.0.zip`. The resource version will be `0.0.0` in this case. + +* `initial_version`: *Optional.* Must be used with the `versioned_file` option. This will be the resource version. + +By default the resource file will be created with no content when `get` runs. You can set the content by using one of the following options: + +* `initial_content_text`: *Optional.* Initial content as a string. + +* `initial_content_binary`: *Optional.* You can pass binary content as a base64 encoded string. diff --git a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java index 227200206..f86afebcb 100644 --- a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java +++ b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java @@ -1884,6 +1884,45 @@ public class ConcourseEditorTest { editor.assertHoverContains("target_name", "Specify the name of the target build stage"); } + @Test public void s3ResourceSourceInitialResourceImplications() throws Exception { + Editor editor; + + // 'initial_path' => 'regexp' + editor = harness.newEditor( + "resources:\n" + + "- name: s3-snapshots\n" + + " type: s3\n" + + " source:\n" + + " bucket: the-bucket\n" + + " access_key_id: the-access-key\n" + + " secret_access_key: the-secret-key\n" + + " versioned_file: path/to/file.tar.gz\n" + + " initial_path: whatever\n" + ); + editor.assertProblems( + "s3-snapshots|Unused", + "initial_path|Property 'initial_path' assumes that 'regexp' is also defined" + ); + + // 'initial_version' => 'versioned_file' + editor = harness.newEditor( + "resources:\n" + + "- name: s3-snapshots\n" + + " type: s3\n" + + " source:\n" + + " bucket: the-bucket\n" + + " access_key_id: the-access-key\n" + + " secret_access_key: the-secret-key\n" + + " regexp: path/to/file.tar.gz\n" + + " initial_version: whatever\n" + ); + editor.assertProblems( + "s3-snapshots|Unused", + "initial_version|Property 'initial_version' assumes that 'versioned_file' is also defined" + ); + + } + @Test public void s3ResourceSourceReconcileAndHovers() throws Exception { Editor editor; @@ -1920,7 +1959,11 @@ public class ConcourseEditorTest { " sse_kms_key_id: the-master-key-id\n" + " use_v2_signing: should-use-v2\n" + " regexp: path-to-file-(.*).tar.gz\n" + - " versioned_file: path/to/file.tar.gz\n" + " versioned_file: path/to/file.tar.gz\n" + + " initial_path: some/initial/path\n" + + " initial_version: 0.0.0\n" + + " initial_content_text: some-initial-text\n" + + " initial_content_binary: some-base64-stuff\n" ); editor.assertProblems( "s3-snapshots|Unused 'Resource'", @@ -1931,7 +1974,13 @@ public class ConcourseEditorTest { "skipping-downloading|'boolean'", "should-use-v2|'boolean'", "regexp|Only one of [regexp, versioned_file] should be defined", - "versioned_file|Only one of [regexp, versioned_file] should be defined" + "versioned_file|Only one of [regexp, versioned_file] should be defined", + + "initial_path|Only one of 'initial_path' and 'initial_version' should be defined", + "initial_version|Only one of 'initial_path' and 'initial_version' should be defined", + + "initial_content_text|Only one of 'initial_content_text' and 'initial_content_binary' should be defined", + "initial_content_binary|Only one of 'initial_content_text' and 'initial_content_binary' should be defined" ); editor.assertHoverContains("bucket", "The name of the bucket"); @@ -1950,6 +1999,10 @@ public class ConcourseEditorTest { editor.assertHoverContains("use_v2_signing", "Use signature v2 signing"); editor.assertHoverContains("regexp", "The pattern to match filenames against within S3"); editor.assertHoverContains("versioned_file", "If you enable versioning for your S3 bucket"); + editor.assertHoverContains("initial_path", "the file path containing the initial version"); + editor.assertHoverContains("initial_version", "the resource version"); + editor.assertHoverContains("initial_content_text", "Initial content as a string"); + editor.assertHoverContains("initial_content_binary", "base64 encoded string"); } @Test public void s3ResourceRegionCompletions() throws Exception {