Concourse: basic support for 'timeout' attribute
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package org.springframework.ide.vscode.commons.util;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class RegexpParser implements ValueParser {
|
||||
|
||||
final private Pattern pat;
|
||||
final private String typeName; // used only for error message
|
||||
final private String patternDescription; //Human readable description of the regexp pay
|
||||
|
||||
/**
|
||||
* Create a RegexpParser which succeeds if the input string matches the given regexp
|
||||
* and fail otherwise.
|
||||
*
|
||||
* @param regexp
|
||||
* @param typeName Name of the type (used in error message for failing parses)
|
||||
* @param patternDescription Human readable description of the regexp pattern (included in the error message for failing parses)
|
||||
*/
|
||||
public RegexpParser(String regexp, String typeName, String patternDescription) {
|
||||
super();
|
||||
this.pat = Pattern.compile(regexp);
|
||||
this.typeName = typeName;
|
||||
this.patternDescription = patternDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object parse(String str) {
|
||||
Matcher matcher = pat.matcher(str);
|
||||
if (matcher.matches()) {
|
||||
return matcher;
|
||||
}
|
||||
throw new IllegalArgumentException("'"+str+"' is not a valid '"+typeName+"'. "+patternDescription);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,6 +52,9 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
YType t_params = f.ymap(t_string, t_any);
|
||||
YType t_string_params = f.ymap(t_string, t_string);
|
||||
|
||||
YAtomicType t_duration = f.yatomic("Duration");
|
||||
t_duration.parseWith(ValueParsers.DURATION);
|
||||
|
||||
YAtomicType t_version = f.yatomic("Version");
|
||||
t_version.addHints("latest", "every");
|
||||
|
||||
@@ -142,6 +145,7 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
prop(step, "ensure", step);
|
||||
prop(step, "attempts", t_strictly_pos_integer);
|
||||
prop(step, "tags", t_strings);
|
||||
prop(step, "timeout", t_duration);
|
||||
|
||||
YBeanType resource = f.ybean("Resource");
|
||||
prop(resource, "name", t_ne_string);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.concourse;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.RegexpParser;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.ValueParser;
|
||||
|
||||
@@ -56,5 +57,16 @@ public class ValueParsers {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static ValueParser DURATION = new RegexpParser(
|
||||
"^(([0-9]+(.[0-9]+)?)(ns|us|µs|ms|s|h|m))+$",
|
||||
"Duration",
|
||||
" A duration string is a sequence of decimal numbers, each with "
|
||||
+ "optional fraction and a unit suffix, such as '300ms', '1.5h' or"
|
||||
+ " '2h45m'. Valid time units are 'ns', 'us' (or 'µs'), 'ms', 's', "
|
||||
+ "'m', 'h'."
|
||||
);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Enforce a time limit on a step.
|
||||
|
||||
Any step can have a hard time limit enforced by attaching timeout and the number of seconds to limit it to.
|
||||
|
||||
timeout: duration
|
||||
|
||||
The amount of time to limit the step's execution to, e.g. `30m` for 30 minutes.
|
||||
|
||||
When exceeded, the step will be interrupted, with the same semantics as aborting the build (except the build will be `failed`, not `aborted`, to distinguish between human intervention and timeouts being enforced).
|
||||
|
||||
The following will run the task, and cancel it if it takes longer than 1 hour and 30 minutes:
|
||||
|
||||
plan:
|
||||
- get: foo
|
||||
- task: unit
|
||||
file: foo/unit.yml
|
||||
timeout: 1h30m
|
||||
@@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* 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.concourse;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.ValueParser;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.*;
|
||||
|
||||
public class DurationParserTest {
|
||||
|
||||
private ValueParser parser = ValueParsers.DURATION;
|
||||
|
||||
@Test
|
||||
public void goodExamples() {
|
||||
parser.parse("1h40m");
|
||||
parser.parse("1.5h");
|
||||
parser.parse("23h59m59s99ms200µs100ns");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badExamples() {
|
||||
does_not_parse("1h:40m");
|
||||
does_not_parse("15h 30m");
|
||||
does_not_parse("23hours");
|
||||
}
|
||||
|
||||
private void does_not_parse(String string) {
|
||||
try {
|
||||
parser.parse(string);
|
||||
fail("Should have failed parsing!");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertContains("Duration", ExceptionUtil.getMessage(e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -252,6 +252,7 @@ public class PipelineYamlEditorTest {
|
||||
" config: some-config\n" +
|
||||
" tags: [a, b, c]\n"+
|
||||
" attempts: 10\n" +
|
||||
" timeout: 1h30m\n" +
|
||||
" ensure:\n" +
|
||||
" bogus: bad\n" +
|
||||
" on_failure:\n" +
|
||||
@@ -267,6 +268,7 @@ public class PipelineYamlEditorTest {
|
||||
editor.assertHoverContains("output_mapping", "A map from task output names to concrete names");
|
||||
editor.assertHoverContains("config", "Use `config` to inline the task config");
|
||||
editor.assertHoverContains("tags", "Any step can be directed at a pool of workers");
|
||||
editor.assertHoverContains("timeout", "amount of time to limit the step's execution");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -297,14 +299,16 @@ public class PipelineYamlEditorTest {
|
||||
" plan:\n" +
|
||||
" - get: git\n" +
|
||||
" trigger: yohoho\n" +
|
||||
" attempts: 0\n"
|
||||
" attempts: 0\n" +
|
||||
" timeout: 1h:30m\n"
|
||||
);
|
||||
editor.assertProblems(
|
||||
"boohoo|boolean",
|
||||
"-1|must be positive",
|
||||
"git|resource does not exist",
|
||||
"yohoho|boolean",
|
||||
"0|must be at least 1"
|
||||
"0|must be at least 1",
|
||||
"1h:30m|Duration"
|
||||
);
|
||||
|
||||
//check that correct values are indeed accepted
|
||||
@@ -508,6 +512,7 @@ public class PipelineYamlEditorTest {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void assertContextualCompletions(String conText, String textBefore, String... textAfter) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user