Add basic support for resource-types attribute

Also some cleanups in test code etc.
This commit is contained in:
Kris De Volder
2016-12-14 09:09:41 -08:00
parent fece70fa8d
commit e09c6cb8cd
22 changed files with 348 additions and 601 deletions

View File

@@ -65,7 +65,6 @@ public class SimpleTextDocumentService implements TextDocumentService {
this.server = server;
}
public synchronized void onHover(HoverHandler h) {
Assert.isNull("A hover handler is already set, multiple handlers not supported yet", hoverHandler);
this.hoverHandler = h;

View File

@@ -1,3 +1,13 @@
/*******************************************************************************
* Copyright (c) 2015, 2016 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.commons.yaml.schema;
import java.util.Set;

View File

@@ -1,9 +1,5 @@
package org.springframework.ide.vscode.concourse;
import java.util.Collection;
import javax.inject.Provider;
import org.eclipse.lsp4j.CompletionOptions;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.TextDocumentSyncKind;
@@ -23,19 +19,14 @@ import org.springframework.ide.vscode.commons.yaml.completion.YamlAssistContextP
import org.springframework.ide.vscode.commons.yaml.completion.YamlCompletionEngine;
import org.springframework.ide.vscode.commons.yaml.hover.YamlHoverInfoProvider;
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.schema.YamlSchema;
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
import org.yaml.snakeyaml.Yaml;
import com.google.common.collect.ImmutableList;
public class ConcourseLanguageServer extends SimpleLanguageServer {
private static final Provider<Collection<YValueHint>> NO_BUILDPACKS = () -> ImmutableList.of();
private Yaml yaml = new Yaml();
private YamlSchema schema = new PipelineYmlSchema(NO_BUILDPACKS);
private YamlSchema schema = new PipelineYmlSchema();
public ConcourseLanguageServer() {

View File

@@ -10,10 +10,6 @@
*******************************************************************************/
package org.springframework.ide.vscode.concourse;
import java.util.Collection;
import javax.inject.Provider;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables;
import org.springframework.ide.vscode.commons.yaml.schema.YType;
@@ -21,7 +17,6 @@ import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory;
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.YAtomicType;
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.YBeanType;
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;
/**
@@ -34,7 +29,7 @@ public class PipelineYmlSchema implements YamlSchema {
private final YTypeFactory f = new YTypeFactory();
public PipelineYmlSchema(Provider<Collection<YValueHint>> buildpackProvider) {
public PipelineYmlSchema() {
TYPE_UTIL = f.TYPE_UTIL;
// define schema types
@@ -52,20 +47,22 @@ public class PipelineYmlSchema implements YamlSchema {
YAtomicType t_version = f.yatomic("Version");
t_version.addHints("latest", "every");
YAtomicType t_image_type = f.yatomic("ImageType");
t_image_type.addHints("docker_image");
YAtomicType t_resource_type = f.yatomic("ResourceType");
t_resource_type.addHints(
f.hint("archive", "archive - The 'archive' resource can fetch and extract .tar.gz archives."),
f.hint("git", "git - The 'git' resource can pull and push to git repositories"),
f.hint("time", "time - The 'time' resource can start jobs on a schedule or timestamp outputs."),
f.hint("s3", "s3 - The 's3' resource can fetch from and upload to S3 buckets."),
f.hint("archive", "archive - The archive resource can fetch and extract .tar.gz archives.")
f.hint("semver", "semver - The 'semver' resource can set or bump version numbers."),
f.hint("time", "time - The 'time' resource can start jobs on a schedule or timestamp outputs."),
f.hint("docker-image", "docker-image - The 'docker-image' resource can fetch, build, and push Docker images")
//TODO: add more resource types and descriptions.
//
// The semver resource can set or bump version numbers.
//
// The github-release resource can fetch and publish versioned GitHub resources.
//
// The docker-image resource can fetch, build, and push Docker images
//
// The tracker resource can deliver stories and bugs on Pivotal Tracker
//
@@ -122,9 +119,16 @@ public class PipelineYmlSchema implements YamlSchema {
prop(job, "public", t_boolean);
prop(job, "disable_manual_trigger", t_boolean);
prop(job, "plan", f.yseq(step));
YType resource_type_def = f.ybean("ResourceTypeDef",
f.yprop("name", t_ne_string),
f.yprop("type", t_image_type),
f.yprop("source", t_any)
);
prop(TOPLEVEL_TYPE, "resources", f.yseq(resource));
prop(TOPLEVEL_TYPE, "jobs", f.yseq(job));
prop(TOPLEVEL_TYPE, "resource_types", f.yseq(resource_type_def));
}

View File

@@ -0,0 +1,52 @@
<h1>Additional resource types used by your pipeline</h1>
<p>Each resource in a pipeline has a <code>type</code>. The resource's type determines
what versions are detected, the bits that are fetched when used for a
<a href="get-step.html"><code>get</code></a> step, and the side effect that occurs when used for a
<a href="put-step.html"><code>put</code></a> step.</p><p>Out of the box, Concourse comes with a few resource types to cover common CI
use cases like dealing with Git repositories and S3 buckets.</p><p>Beyond these core types, each pipeline can configure its own custom types by
specifying <code>resource_types</code> at the top level. Each custom resource type is
itself defined as a resource that provides the container image for the custom
resource type (see <a href="implementing-resources.html">Implementing a Resource</a>). You will almost always
be using the
<a href="https://github.com/concourse/docker-image-resource"><code>docker-image</code>
resource type</a> when doing this.</p><p>The following example extends a Concourse pipeline to support use of the
<a href="https://github.com/jtarchie/pullrequest-resource"><code>pull-request</code>
resource type</a> and then uses it within the pipeline:</p><div class="highlight"><pre class="verbatim"><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">resource_types</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"></span><span class="pi">-</span><span class="t"></span><span class="t"> </span><span class="t"></span><span class="nv"></span><span class="py">name</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">pull-request</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">type</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">docker-image</span><span class="t">
</span><span class="t"> </span><span class="py">source</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">repository</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">jtarchie/pr</span><span class="t">
</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">resources</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"></span><span class="pi">-</span><span class="t"></span><span class="t"> </span><span class="t"></span><span class="nv"></span><span class="py">name</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">type</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">pull-request</span><span class="t">
</span><span class="t"> </span><span class="py">source</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">repo</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">vito/atomy</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">access_token</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="pi">{</span><span class="pi">{</span><span class="nv"></span><span class="nv">access-token</span><span class="t"></span><span class="pi">}</span><span class="pi">}</span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">jobs</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"></span><span class="pi">-</span><span class="t"></span><span class="t"> </span><span class="t"></span><span class="nv"></span><span class="py">name</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr-unit</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">plan</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="pi">-</span><span class="t"></span><span class="t"> </span><span class="t"></span><span class="nv"></span><span class="py">get</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="pi">-</span><span class="t"></span><span class="t"> </span><span class="t"></span><span class="nv"></span><span class="py">put</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="py">params</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">path</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">status</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">pending</span><span class="t">
</span><span class="t"> </span><span class="nv">-</span><span class="sp"> </span><span class="py">task</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">unit</span><span class="t">
</span><span class="t"> </span><span class="py">file</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr/ci/unit.yml</span><span class="t">
</span><span class="t"> </span><span class="py">on_success</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">put</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">params</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">path</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">status</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">success</span><span class="t">
</span><span class="t"> </span><span class="py">on_failure</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">put</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">params</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">path</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">atomy-pr</span><span class="t">
</span><span class="t"> </span><span class="t"></span><span class="t"></span><span class="t"></span><span class="t"></span><span class="nv"></span><span class="py">status</span><span class="t"></span><span class="pi">:</span><span class="t"></span><span class="t"> </span><span class="nv"></span><span class="nv">failure</span></pre></div><p>Custom resource types can override the core resource types, and can be defined
in terms of each other. Also, a custom resource type can use the core type that
it's overriding. This is useful if you want to e.g. provide your own custom
<code>docker-image</code> resource, by overriding the core one (and using it one last
time for the override itself), and then using it for all other custom resource
types.</p>

View File

@@ -12,10 +12,10 @@ import org.junit.Test;
import org.springframework.ide.vscode.concourse.ConcourseLanguageServer;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
public class ManifestYamlLanguageServerTest {
public class ConcourseLanguageServerTest {
public static File getTestResource(String name) throws URISyntaxException {
return Paths.get(ManifestYamlLanguageServerTest.class.getResource(name).toURI()).toFile();
return Paths.get(ConcourseLanguageServerTest.class.getResource(name).toURI()).toFile();
}
@Test
@@ -32,34 +32,6 @@ public class ManifestYamlLanguageServerTest {
assertExpectedInitResult(harness.intialize(workspaceRoot));
}
// @Test public void completions() throws Exception {
// LanguageServerHarness harness = new LanguageServerHarness(ManifestYamlLanguageServer::new);
//
// File workspaceRoot = getTestResource("/workspace/");
// assertExpectedInitResult(harness.intialize(workspaceRoot));
//
// TextDocumentInfo doc = harness.openDocument(getTestResource("/workspace/testfile.yml"));
//
// CompletionList completions = harness.getCompletions(doc, doc.positionOf("foo"));
// assertThat(completions.isIncomplete()).isFalse();
// assertThat(completions.getItems())
// .extracting(CompletionItem::getLabel)
// .containsExactly("TypeScript", "JavaScript");
//
// List<CompletionItem> resolved = harness.resolveCompletions(completions);
// assertThat(resolved)
// .extracting(CompletionItem::getLabel)
// .containsExactly("TypeScript", "JavaScript");
//
// assertThat(resolved)
// .extracting(CompletionItem::getDetail)
// .containsExactly("TypeScript details", "JavaScript details");
//
// assertThat(resolved)
// .extracting(CompletionItem::getDocumentation)
// .containsExactly("TypeScript docs", "JavaScript docs");
// }
private void assertExpectedInitResult(InitializeResult initResult) {
assertThat(initResult.getCapabilities().getCompletionProvider().getResolveProvider()).isFalse();
assertThat(initResult.getCapabilities().getTextDocumentSync()).isEqualTo(TextDocumentSyncKind.Incremental);

View File

@@ -1,493 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 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.manifest.yaml;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.concourse.ConcourseLanguageServer;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
public class ManifestYamlEditorTest {
LanguageServerHarness harness;
@Before public void setup() throws Exception {
harness = new LanguageServerHarness(ConcourseLanguageServer::new);
harness.intialize(null);
}
@Test public void testReconcileCatchesParseError() throws Exception {
Editor editor = harness.newEditor(
"somemap: val\n"+
"- sequence"
);
editor.assertProblems(
"-|expected <block end>"
);
}
@Test public void reconcileRunsOnDocumentOpenAndChange() throws Exception {
LanguageServerHarness harness = new LanguageServerHarness(ConcourseLanguageServer::new);
harness.intialize(null);
Editor editor = harness.newEditor(
"somemap: val\n"+
"- sequence"
);
editor.assertProblems(
"-|expected <block end>"
);
editor.setText(
"- sequence\n" +
"zomemap: val"
);
editor.assertProblems(
"z|expected <block end>"
);
}
@Test
public void reconcileMisSpelledPropertyNames() throws Exception {
Editor editor;
editor = harness.newEditor(
"memory: 1G\n" +
"aplications:\n" +
" - buildpack: zbuildpack\n" +
" domain: zdomain\n" +
" name: foo"
);
editor.assertProblems("aplications|Unknown property");
//mispelled or not allowed at toplevel
editor = harness.newEditor(
"name: foo\n" +
"buildpeck: yahah\n" +
"memory: 1G\n" +
"memori: 1G\n"
);
editor.assertProblems(
"name|Unknown property",
"buildpeck|Unknown property",
"memori|Unknown property"
);
//mispelled or not allowed as nested
editor = harness.newEditor(
"applications:\n" +
"- name: fine\n" +
" buildpeck: yahah\n" +
" memory: 1G\n" +
" memori: 1G\n" +
" applications: bad\n"
);
editor.assertProblems(
"buildpeck|Unknown property",
"memori|Unknown property",
"applications|Unknown property"
);
}
@Test
public void reconcileStructuralProblems() throws Exception {
Editor editor;
//forgot the 'applications:' heading
editor = harness.newEditor(
"- name: foo"
);
editor.assertProblems(
"- name: foo|Expecting a 'Map' but found a 'Sequence'"
);
//forgot to make the '-' after applications
editor = harness.newEditor(
"applications:\n" +
" name: foo"
);
editor.assertProblems(
"name: foo|Expecting a 'Sequence' but found a 'Map'"
);
//Using a 'composite' element where a scalar type is expected
editor = harness.newEditor(
"memory:\n"+
"- bad sequence\n" +
"buildpack:\n" +
" bad: map\n"
);
editor.assertProblems(
"- bad sequence|Expecting a 'Memory' but found a 'Sequence'",
"bad: map|Expecting a 'Buildpack' but found a 'Map'"
);
}
@Test
public void reconcileSimpleTypes() throws Exception {
Editor editor;
//check for 'format' errors:
editor = harness.newEditor(
"applications:\n" +
"- name: foo\n" +
" instances: not a number\n" +
" no-route: notBool\n"+
" memory: 1024\n" +
" disk_quota: 2048\n" +
" health-check-type: unhealthy"
);
editor.assertProblems(
"not a number|Positive Integer",
"notBool|boolean",
"1024|Memory",
"2048|Memory",
"unhealthy|Health Check Type"
);
//check for 'range' errors:
editor = harness.newEditor(
"applications:\n" +
"- name: foo\n" +
" instances: -3\n" +
" memory: -1024M\n" +
" disk_quota: -2048M\n"
);
editor.assertProblems(
"-3|Positive Integer",
"-1024M|Memory",
"-2048M|Memory"
);
//check that correct values are indeed accepted
editor = harness.newEditor(
"applications:\n" +
"- name: foo\n" +
" instances: 2\n" +
" no-route: true\n"+
" memory: 1024M\n" +
" disk_quota: 2048MB\n"
);
editor.assertProblems(/*none*/);
//check that correct values are indeed accepted
editor = harness.newEditor(
"applications:\n" +
"- name: foo\n" +
" instances: 2\n" +
" no-route: false\n" +
" memory: 1024m\n" +
" disk_quota: 2048mb\n"
);
editor.assertProblems(/*none*/);
editor = harness.newEditor(
"applications:\n" +
"- name: foo\n" +
" instances: 2\n" +
" memory: 1G\n" +
" disk_quota: 2g\n"
);
editor.assertProblems(/*none*/);
}
@Test
public void noListIndent() throws Exception {
Editor editor;
editor = harness.newEditor("appl<*>");
editor.assertCompletions(
"applications:\n"+
"- <*>"
);
}
@Test
public void toplevelCompletions() throws Exception {
Editor editor;
editor = harness.newEditor("<*>");
editor.assertCompletions(
"applications:\n"+
"- <*>",
// ---------------
"buildpack: <*>",
// ---------------
"command: <*>",
// ---------------
"disk_quota: <*>",
// ---------------
"domain: <*>",
// ---------------
"domains:\n"+
"- <*>",
// ---------------
"env:\n"+
" <*>",
// ---------------
"health-check-type: <*>",
// ---------------
// "host: <*>",
// ---------------
// "hosts: \n"+
// " - <*>",
// ---------------
"inherit: <*>",
// ---------------
"instances: <*>",
// ---------------
"memory: <*>",
// ---------------
// "name: <*>",
// ---------------
"no-hostname: <*>",
// ---------------
"no-route: <*>",
// ---------------
"path: <*>",
// ---------------
"random-route: <*>",
// ---------------
"services:\n"+
"- <*>",
// ---------------
"stack: <*>",
// ---------------
"timeout: <*>"
);
editor = harness.newEditor("ranro<*>");
editor.assertCompletions(
"random-route: <*>"
);
}
@Test
public void nestedCompletions() throws Exception {
Editor editor;
editor = harness.newEditor(
"applications:\n" +
"- <*>"
);
editor.assertCompletions(
// ---------------
"applications:\n" +
"- buildpack: <*>",
// ---------------
"applications:\n" +
"- command: <*>",
// ---------------
"applications:\n" +
"- disk_quota: <*>",
// ---------------
"applications:\n" +
"- domain: <*>",
// ---------------
"applications:\n" +
"- domains:\n"+
" - <*>",
// ---------------
"applications:\n" +
"- env:\n"+
" <*>",
// ---------------
"applications:\n" +
"- health-check-type: <*>",
// ---------------
"applications:\n" +
"- host: <*>",
// ---------------
"applications:\n" +
"- hosts:\n"+
" - <*>",
// ---------------
"applications:\n" +
"- instances: <*>",
// ---------------
"applications:\n" +
"- memory: <*>",
// ---------------
"applications:\n" +
"- name: <*>",
// ---------------
"applications:\n" +
"- no-hostname: <*>",
// ---------------
"applications:\n" +
"- no-route: <*>",
// ---------------
"applications:\n" +
"- path: <*>",
// ---------------
"applications:\n" +
"- random-route: <*>",
// ---------------
"applications:\n" +
"- services:\n"+
" - <*>",
// ---------------
"applications:\n" +
"- stack: <*>",
// ---------------
"applications:\n" +
"- timeout: <*>"
);
}
@Test
public void completionDetailsAndDocs() throws Exception {
Editor editor = harness.newEditor(
"applications:\n" +
"- build<*>"
);
editor.assertCompletionDetails("buildpack", "Buildpack", "If your application requires a custom buildpack");
}
@Test
public void valueCompletions() throws Exception {
assertCompletions("disk_quota: <*>",
"disk_quota: 1024M<*>",
"disk_quota: 256M<*>",
"disk_quota: 512M<*>"
);
assertCompletions("memory: <*>",
"memory: 1024M<*>",
"memory: 256M<*>",
"memory: 512M<*>"
);
assertCompletions("no-hostname: <*>",
"no-hostname: false<*>",
"no-hostname: true<*>"
);
assertCompletions("no-route: <*>",
"no-route: false<*>",
"no-route: true<*>"
);
assertCompletions("random-route: <*>",
"random-route: false<*>",
"random-route: true<*>"
);
assertCompletions("health-check-type: <*>",
"health-check-type: none<*>",
"health-check-type: port<*>"
);
}
@Test
public void hoverInfos() throws Exception {
Editor editor = harness.newEditor(
"memory: 1G\n" +
"#comment\n" +
"inherit: base-manifest.yml\n"+
"applications:\n" +
"- buildpack: zbuildpack\n" +
" domain: zdomain\n" +
" name: foo\n" +
" command: java main.java\n" +
" disk_quota: 1024M\n" +
" domains:\n" +
" - pivotal.io\n" +
" - otherdomain.org\n" +
" env:\n" +
" RAILS_ENV: production\n" +
" RACK_ENV: production\n" +
" host: apppage\n" +
" hosts:\n" +
" - apppage2\n" +
" - appage3\n" +
" instances: 2\n" +
" no-hostname: true\n" +
" no-route: true\n" +
" path: somepath/app.jar\n" +
" random-route: true\n" +
" services:\n" +
" - instance_ABC\n" +
" - instance_XYZ\n" +
" stack: cflinuxfs2\n" +
" timeout: 80\n" +
" health-check-type: none\n"
);
editor.assertIsHoverRegion("memory");
editor.assertIsHoverRegion("inherit");
editor.assertIsHoverRegion("applications");
editor.assertIsHoverRegion("buildpack");
editor.assertIsHoverRegion("domain");
editor.assertIsHoverRegion("name");
editor.assertIsHoverRegion("command");
editor.assertIsHoverRegion("disk_quota");
editor.assertIsHoverRegion("domains");
editor.assertIsHoverRegion("env");
editor.assertIsHoverRegion("host");
editor.assertIsHoverRegion("hosts");
editor.assertIsHoverRegion("instances");
editor.assertIsHoverRegion("no-hostname");
editor.assertIsHoverRegion("no-route");
editor.assertIsHoverRegion("path");
editor.assertIsHoverRegion("random-route");
editor.assertIsHoverRegion("services");
editor.assertIsHoverRegion("stack");
editor.assertIsHoverRegion("timeout");
editor.assertIsHoverRegion("health-check-type");
editor.assertHoverContains("memory", "Use the `memory` attribute to specify the memory limit");
editor.assertHoverContains("1G", "Use the `memory` attribute to specify the memory limit");
editor.assertHoverContains("inherit", "For example, every child of a parent manifest called `base-manifest.yml` begins like this");
editor.assertHoverContains("buildpack", "use the `buildpack` attribute to specify its URL or name");
editor.assertHoverContains("name", "The `name` attribute is the only required attribute for an application in a manifest file");
editor.assertHoverContains("command", "On the command line, use the `-c` option to specify the custom start command as the following example shows");
editor.assertHoverContains("disk_quota", "Use the `disk_quota` attribute to allocate the disk space for your app instance");
editor.assertHoverContains("domain", "You can use the `domain` attribute when you want your application to be served");
editor.assertHoverContains("domains", "Use the `domains` attribute to provide multiple domains");
editor.assertHoverContains("env", "The `env` block consists of a heading, then one or more environment variable/value pairs");
editor.assertHoverContains("host", "Use the `host` attribute to provide a hostname, or subdomain, in the form of a string");
editor.assertHoverContains("hosts", "Use the `hosts` attribute to provide multiple hostnames, or subdomains");
editor.assertHoverContains("instances", "Use the `instances` attribute to specify the number of app instances that you want to start upon push");
editor.assertHoverContains("no-hostname", "By default, if you do not provide a hostname, the URL for the app takes the form of `APP-NAME.DOMAIN`");
editor.assertHoverContains("no-route", "You can use the `no-route` attribute with a value of `true` to prevent a route from being created for your application");
editor.assertHoverContains("path", "You can use the `path` attribute to tell Cloud Foundry where to find your application");
editor.assertHoverContains("random-route", "Use the `random-route` attribute to create a URL that includes the app name and random words");
editor.assertHoverContains("services", "The `services` block consists of a heading, then one or more service instance names");
editor.assertHoverContains("stack", "Use the `stack` attribute to specify which stack to deploy your application to.");
editor.assertHoverContains("timeout", "The `timeout` attribute defines the number of seconds Cloud Foundry allocates for starting your application");
editor.assertHoverContains("health-check-type", "Use the `health-check-type` attribute to");
}
@Test
public void noHoverInfos() throws Exception {
Editor editor = harness.newEditor(
"#comment\n" +
"applications:\n" +
"- buildpack: zbuildpack\n" +
" name: foo\n" +
" domains:\n" +
" - pivotal.io\n" +
" - otherdomain.org\n"
);
editor.assertNoHover("comment");
// May fail in the future if hover support is added, but if hover support is added in the future,
// it is expected that these should start to fail, as right now they have no hover
editor.assertNoHover("pivotal.io");
editor.assertNoHover("otherdomain.org");
}
//////////////////////////////////////////////////////////////////////////////
private void assertCompletions(String textBefore, String... textAfter) throws Exception {
Editor editor = harness.newEditor(textBefore);
editor.assertCompletions(textAfter);
}
}

View File

@@ -0,0 +1,258 @@
/*******************************************************************************
* Copyright (c) 2016 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.manifest.yaml;
import java.io.InputStream;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.commons.util.IOUtil;
import org.springframework.ide.vscode.concourse.ConcourseLanguageServer;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
public class PipelineYamlEditorTest {
LanguageServerHarness harness;
@Before public void setup() throws Exception {
harness = new LanguageServerHarness(ConcourseLanguageServer::new);
harness.intialize(null);
}
@Test public void testReconcileCatchesParseError() throws Exception {
Editor editor = harness.newEditor(
"somemap: val\n"+
"- sequence"
);
editor.assertProblems(
"-|expected <block end>"
);
}
@Test public void reconcileRunsOnDocumentOpenAndChange() throws Exception {
LanguageServerHarness harness = new LanguageServerHarness(ConcourseLanguageServer::new);
harness.intialize(null);
Editor editor = harness.newEditor(
"somemap: val\n"+
"- sequence"
);
editor.assertProblems(
"-|expected <block end>"
);
editor.setText(
"- sequence\n" +
"zomemap: val"
);
editor.assertProblems(
"z|expected <block end>"
);
}
@Test
public void reconcileMisSpelledPropertyNames() throws Exception {
Editor editor;
editor = harness.newEditor(
"resorces:\n" +
"- name: git\n" +
" type: git\n"
);
editor.assertProblems("resorces|Unknown property");
}
@Test
public void reconcileAcceptsSensiblePipelineFile() throws Exception {
Editor editor;
editor = harness.newEditor(
getClasspathResourceText("workspace/pipeline.yml")
);
editor.assertProblems(/*NONE*/);;
}
private String getClasspathResourceText(String resourceName) throws Exception {
InputStream stream = PipelineYamlEditorTest.class.getClassLoader().getResourceAsStream(resourceName);
return IOUtil.toString(stream);
}
@Test
public void reconcileStructuralProblems() throws Exception {
Editor editor;
//resources should be a sequence not a map, even if there's only one entry
editor = harness.newEditor(
"resources:\n" +
" name: git\n" +
" type: git\n"
);
editor.assertProblems(
"name: git\n type: git|Expecting a 'Sequence' but found a 'Map'"
);
//TODO: Add more test cases for structural problem?
}
@Test
public void reconcileSimpleTypes() throws Exception {
Editor editor;
//check for 'format' errors:
editor = harness.newEditor(
"jobs:\n" +
"- name: foo\n" +
" serial: boohoo\n" +
" max_in_flight: 0\n" +
" plan:\n" +
" - get: git\n" +
" trigger: yohoho"
);
editor.assertProblems(
"boohoo|boolean",
"0|Positive Integer",
"yohoho|boolean"
);
//check that correct values are indeed accepted
editor = harness.newEditor(
"jobs:\n" +
"- name: foo\n" +
" serial: true\n" +
" max_in_flight: 2\n" +
" plan:\n" +
" - get: git\n" +
" trigger: true"
);
editor.assertProblems(/*none*/);
}
@Test
public void noListIndent() throws Exception {
Editor editor;
editor = harness.newEditor("jo<*>");
editor.assertCompletions(
"jobs:\n"+
"- <*>"
);
}
@Test
public void toplevelCompletions() throws Exception {
Editor editor;
editor = harness.newEditor("<*>");
editor.assertCompletions(
"resources:\n"+
"- <*>",
// ---------------
"resource-types:\n" +
"- <*>",
// ---------------
"jobs:\n" +
"- <*>"
);
editor = harness.newEditor("ranro<*>");
editor.assertCompletions(
"random-route: <*>"
);
}
@Test
public void completionDetailsAndDocs() throws Exception {
Editor editor = harness.newEditor(
"applications:\n" +
"- build<*>"
);
editor.assertCompletionDetails("buildpack", "Buildpack", "If your application requires a custom buildpack");
}
@Test
public void valueCompletions() throws Exception {
assertCompletions(
"resources:\n" +
"- type: <*>"
, //=>
"resources:\n" +
"- type: archive<*>",
"resources:\n" +
"- type: docker-image<*>",
"resources:\n" +
"- type: git<*>",
"resources:\n" +
"- type: s3<*>",
"resources:\n" +
"- type: semver<*>",
"resources:\n" +
"- type: time<*>"
);
assertCompletions(
"jobs:\n" +
"- name: foo\n" +
" serial: <*>"
, // =>
"jobs:\n" +
"- name: foo\n" +
" serial: false<*>"
, // --
"jobs:\n" +
"- name: foo\n" +
" serial: true<*>"
);
}
@Test
public void topLevelHoverInfos() throws Exception {
Editor editor = harness.newEditor(
"resource_types:\n" +
"- name: s3-multi\n" +
" type: docker-image\n" +
" source:\n" +
" repository: kdvolder/s3-resource-simple\n" +
"resources:\n" +
"- name: docker-git\n" +
" type: git\n" +
" source:\n" +
" uri: git@github.com:spring-projects/sts4.git\n" +
" branch: {{branch}}\n" +
" username: kdvolder\n" +
" private_key: {{rsa_id}}\n" +
" paths:\n" +
" - concourse/docker\n" +
"jobs:\n" +
"- name: build-docker-image\n" +
" serial: true\n" +
" plan:\n" +
" - get: docker-git\n" +
" trigger: true\n" +
" - put: docker-image\n" +
" params:\n" +
" build: docker-git/concourse/docker\n" +
" get_params: \n" +
" skip_download: true\n"
);
editor.assertHoverContains("resource_types", "each pipeline can configure its own custom types by specifying `resource_types` at the top level.");
editor.assertHoverContains("resources", "A resource is any entity that can be checked for new versions");
editor.assertHoverContains("jobs", "At a high level, a job describes some actions to perform");
}
//////////////////////////////////////////////////////////////////////////////
private void assertCompletions(String textBefore, String... textAfter) throws Exception {
Editor editor = harness.newEditor(textBefore);
editor.assertCompletions(textAfter);
}
}

View File

@@ -13,11 +13,12 @@ package org.springframework.ide.vscode.manifest.yaml;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.ide.vscode.concourse.PipelineYmlSchema;
/**
* @author Kris De Volder
*/
public class ManifestYmlSchemaTest {
public class PipelineYmlSchemaTest {
@Test
public void shouldMakeSomeTests() {
@@ -48,31 +49,14 @@ public class ManifestYmlSchemaTest {
// "timeout"
// };
//
// private static final String[] TOPLEVEL_PROP_NAMES = {
// "applications",
// "buildpack",
// "command",
// "disk_quota",
// "domain",
// "domains",
// "env",
// "health-check-type",
//// "host",
//// "hosts",
// "inherit",
// "instances",
// "memory",
//// "name",
// "no-hostname",
// "no-route",
// "path",
// "random-route",
// "services",
// "stack",
// "timeout"
// };
//
// PipelineYmlSchema schema = new PipelineYmlSchema(null);
private static final String[] TOPLEVEL_PROP_NAMES = {
"resources",
"jobs",
"resource-types"
//groups
};
PipelineYmlSchema schema = new PipelineYmlSchema();
//
// @Test
// public void toplevelProperties() throws Exception {

View File

@@ -1,5 +0,0 @@
#Comment
applications:
- name: foo
buildpack: something

View File

@@ -1,4 +0,0 @@
#!/bin/bash
branch=`git rev-parse --abbrev-ref HEAD`
fly -t tools destroy-pipeline -p sts4-${branch}

View File

@@ -1,17 +0,0 @@
FROM ubuntu:16.04
ADD npmrc /root/.npmrc
RUN apt-get update && apt-get install -y \
build-essential \
gettext-base \
git \
jq \
openjdk-8-jdk \
maven \
curl
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - \
&& apt-get install -y nodejs
CMD /bin/bash

View File

@@ -1 +0,0 @@
unsafe-perm=true

View File

@@ -1,3 +0,0 @@
#!/bin/bash
branch=`git rev-parse --abbrev-ref HEAD`
fly -t tools set-pipeline --var "branch=${branch}" --load-vars-from ${HOME}/.sts4-concourse-credentials.yml -p sts4-${branch} -c pipeline.yml