Basic support for update block

This commit is contained in:
Kris De Volder
2017-07-12 12:34:16 -07:00
parent bfec669ced
commit 1efaae53e5
9 changed files with 205 additions and 2 deletions

View File

@@ -50,6 +50,8 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
public final YType t_strictly_pos_integer = f.yatomic("Strictly Positive Integer")
.parseWith(ValueParsers.integerAtLeast(1));
public final YType t_uuid = f.yatomic("UUID").parseWith(UUID::fromString);
public final YType t_integer_or_range = f.yatomic("Integer or Range")
.parseWith(BoshValueParsers.INTEGER_OR_RANGE);
public BoshDeploymentManifestSchema() {
TYPE_UTIL = f.TYPE_UTIL;
@@ -108,7 +110,12 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
t_stemcell.requireOneOf("name", "os");
addProp(TOPLEVEL_TYPE, "stemcells", f.yseq(t_stemcell)).isRequired(true);
YType t_update = t_params; //TODO: https://www.pivotaltracker.com/story/show/148627121
YBeanType t_update = f.ybean("Update");
addProp(t_update, "canaries", t_strictly_pos_integer).isRequired(true);
addProp(t_update, "max_in_flight", t_pos_integer).isRequired(true);
addProp(t_update, "canary_watch_time", t_integer_or_range).isRequired(true);
addProp(t_update, "update_watch_time", t_integer_or_range).isRequired(true);
addProp(t_update, "serial", t_boolean);
addProp(TOPLEVEL_TYPE, "update", t_update).isRequired(true);
YBeanType t_job = f.ybean("Job");

View File

@@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright (c) 2017 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.bosh;
import org.springframework.ide.vscode.commons.util.ValueParseException;
import org.springframework.ide.vscode.commons.util.ValueParser;
public class BoshValueParsers {
public static final ValueParser INTEGER_OR_RANGE = new ValueParser() {
private int findDash(String s) throws ValueParseException {
int firstDash = s.indexOf('-');
if (firstDash<0) {
return firstDash; //no dash... and that's okay!
}
int secondDash = s.indexOf('-', firstDash+1);
if (secondDash>=0) {
//Only one dash is expected!
throw new ValueParseException("Should be either a Integer, or a range (of the form '<integer>-<integer>')");
}
return firstDash;
}
@Override
public Object parse(String s) throws Exception {
int dash = findDash(s);
if (dash>=0) {
int low, high;
//range
try {
low = Integer.parseInt(s.substring(0, dash));
} catch (Exception e) {
throw new ValueParseException("Should be a Integer", 0, dash);
}
try {
high = Integer.parseInt(s.substring(dash+1));
} catch (Exception e) {
throw new ValueParseException("Should be a Integer", dash+1, s.length());
}
if (low>high) {
throw new ValueParseException(low + " should be smaller than "+high);
}
} else {
//integer
try {
return Integer.parseInt(s);
} catch (Exception e) {
throw new ValueParseException("Should be either a Integer, or a range (of the form '<integer>-<integer>')");
}
}
return s;
}
};
}

View File

@@ -0,0 +1 @@
*Required*. The number of [canary](https://bosh.io/docs/terminology.html#canary) instances.

View File

@@ -0,0 +1,6 @@
*Required*. Only applies to monit start operation.
- If the `canary_watch_time` is an integer, the Director sleeps for that many milliseconds, then checks whether the canary instances are healthy.
- If the `canary_watch_time` is a range (low-high), the Director:
- Waits for `low` milliseconds
- Waits until instances are healthy or `high` milliseconds have passed since instances started updating

View File

@@ -0,0 +1 @@
*Required*. The maximum number of non-canary instances to update in parallel.

View File

@@ -0,0 +1 @@
If disabled (set to `false`), instance groups will be deployed in parallel, otherwise - sequentially. Instances within a group will still follow `canary` and `max_in_flight` configuration. Defaults to `true`.

View File

@@ -0,0 +1,6 @@
*Required*. Only applies to monit start operation.
- If the `update_watch_time` is an integer, the Director sleeps for that many milliseconds, then checks whether the instances are healthy.
- If the `update_watch_time` is a range (low-high), the Director:
- Waits for `low` milliseconds
- Waits until instances are healthy or `high` milliseconds have passed since instances started updating

View File

@@ -387,7 +387,6 @@ public class BoshEditorTest {
" provides:\n" +
" blah: blah\n"
);
editor.assertHoverContains("name", 3, "The job name");
editor.assertHoverContains("release", "The release where the job exists");
editor.assertHoverContains("consumes", "Links consumed by the job");
@@ -422,5 +421,44 @@ public class BoshEditorTest {
editor.assertHoverContains("bosh", "no description");
editor.assertHoverContains("password", "Crypted password");
}
@Test public void updateBlockCompletions() throws Exception {
Editor editor = harness.newEditor(
"update:\n" +
" <*>"
);
editor.assertCompletions(PLAIN_COMPLETION,
"update:\n" +
" canaries: <*>"
, // =====
"update:\n" +
" canary_watch_time: <*>"
, // =====
"update:\n" +
" max_in_flight: <*>"
, // =====
"update:\n" +
" serial: <*>"
, // =====
"update:\n" +
" update_watch_time: <*>"
);
}
@Test public void updateBlockHovers() throws Exception {
Editor editor = harness.newEditor(
"update:\n" +
" canaries: 1\n" +
" max_in_flight: 10\n" +
" canary_watch_time: 1000-30000\n" +
" update_watch_time: 1000-30000\n" +
" serial: false"
);
editor.assertHoverContains("canaries", "The number of [canary]");
editor.assertHoverContains("max_in_flight", "maximum number of non-canary instances");
editor.assertHoverContains("canary_watch_time", "checks whether the canary instances");
editor.assertHoverContains("update_watch_time", "checks whether the instances");
editor.assertHoverContains("serial", "deployed in parallel");
}
}

View File

@@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2017 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.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.springframework.ide.vscode.bosh.BoshValueParsers;
import org.springframework.ide.vscode.commons.util.ValueParseException;
import org.springframework.ide.vscode.commons.util.ValueParser;
public class BoshValueParserTest {
private static final String MARKER = "<*>";
@Test public void integerOrRangeOkay() throws Exception {
BoshValueParsers.INTEGER_OR_RANGE.parse("123");
BoshValueParsers.INTEGER_OR_RANGE.parse("123-456");
}
@Test public void integerOrRangeGarbage() throws Exception {
assertProblem(BoshValueParsers.INTEGER_OR_RANGE, "<*>garbage<*>", "Should be either a Integer, or a range (of the form '<integer>-<integer>')");
assertProblem(BoshValueParsers.INTEGER_OR_RANGE, "<*>123--456<*>", "Should be either a Integer, or a range (of the form '<integer>-<integer>')");
assertProblem(BoshValueParsers.INTEGER_OR_RANGE, "<*>garbage<*>-123", "Should be a Integer");
assertProblem(BoshValueParsers.INTEGER_OR_RANGE, "123-<*>garbage<*>", "Should be a Integer");
assertProblem(BoshValueParsers.INTEGER_OR_RANGE, "<*>123-122<*>", "123 should be smaller than 122");
}
private void assertProblem(ValueParser parser, String input, String expectedMessage) throws Exception {
String unmarkedInput = input.replace(MARKER, "");
int firstMarker = input.indexOf(MARKER);
assertTrue(firstMarker>=0);
int secondMarker = input.indexOf(MARKER, firstMarker+1)-MARKER.length();
assertTrue(secondMarker>=firstMarker);
try {
parser.parse(unmarkedInput);
} catch (ValueParseException e) {
int startIndex = startIndex(unmarkedInput, e);
int endIndex = endIndex(unmarkedInput, e);
String markedInput =
unmarkedInput.substring(0, startIndex) +
MARKER +
unmarkedInput.substring(startIndex, endIndex) +
MARKER +
unmarkedInput.substring(endIndex);
assertEquals(input, markedInput);
assertEquals(expectedMessage, e.getMessage());
}
}
private int endIndex(String unmarkedInput, ValueParseException e) {
int i = e.getEndIndex();
if (i>=0) {
return i;
} else {
return unmarkedInput.length();
}
}
private int startIndex(String unarkedInput, ValueParseException e) {
int i = e.getStartIndex();
if (i>=0) {
return i;
} else {
return 0;
}
}
}