You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2017/10/11 00:29:14 UTC
[5/8] aurora git commit: Use a simpler command line argument system
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/ArgScannerTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/ArgScannerTest.java b/commons/src/test/java/org/apache/aurora/common/args/ArgScannerTest.java
deleted file mode 100644
index 06ce914..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/ArgScannerTest.java
+++ /dev/null
@@ -1,632 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args;
-
-import java.io.PrintStream;
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.io.ByteStreams;
-
-import org.apache.aurora.common.args.ArgScannerTest.StandardArgs.Optimizations;
-import org.apache.aurora.common.args.constraints.NotEmpty;
-import org.apache.aurora.common.args.constraints.NotNegative;
-import org.apache.aurora.common.args.constraints.NotNull;
-import org.apache.aurora.common.args.constraints.Positive;
-import org.apache.aurora.common.args.constraints.Range;
-import org.apache.aurora.common.args.parsers.NonParameterizedTypeParser;
-import org.apache.aurora.common.base.Command;
-import org.apache.aurora.common.base.MorePreconditions;
-import org.apache.aurora.common.collections.Pair;
-import org.apache.aurora.common.quantity.Amount;
-import org.apache.aurora.common.quantity.Data;
-import org.apache.aurora.common.quantity.Time;
-import org.hamcrest.CoreMatchers;
-import org.junit.Before;
-import org.junit.Test;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-/**
- * @author William Farner
- */
-public class ArgScannerTest {
-
- private static final Function<Class<?>, Predicate<Field>> TO_SCOPE_PREDICATE =
- cls -> new Predicate<Field>() {
- @Override public boolean apply(Field field) {
- return field.getDeclaringClass() == cls;
- }
- };
-
- @Before
- public void setUp() {
- // Reset args in all classes before each test.
- for (Class<?> cls : this.getClass().getDeclaredClasses()) {
- resetArgs(cls);
- }
- }
-
- public static class StandardArgs {
- enum Optimizations { NONE, MINIMAL, ALL }
- @CmdLine(name = "enum", help = "help")
- static final Arg<Optimizations> ENUM_VAL = Arg.create(Optimizations.MINIMAL);
- @CmdLine(name = "string", help = "help")
- static final Arg<String> STRING_VAL = Arg.create("string");
- @CmdLine(name = "char", help = "help")
- static final Arg<Character> CHAR_VAL = Arg.create('c');
- @CmdLine(name = "byte", help = "help")
- static final Arg<Byte> BYTE_VAL = Arg.create((byte) 0);
- @CmdLine(name = "short", help = "help")
- static final Arg<Short> SHORT_VAL = Arg.create((short) 0);
- @CmdLine(name = "int", help = "help")
- static final Arg<Integer> INT_VAL = Arg.create(0);
- @CmdLine(name = "long", help = "help")
- static final Arg<Long> LONG_VAL = Arg.create(0L);
- @CmdLine(name = "float", help = "help")
- static final Arg<Float> FLOAT_VAL = Arg.create(0F);
- @CmdLine(name = "double", help = "help")
- static final Arg<Double> DOUBLE_VAL = Arg.create(0D);
- @CmdLine(name = "bool", help = "help")
- static final Arg<Boolean> BOOL = Arg.create(false);
- @CmdLine(name = "regex", help = "help")
- static final Arg<Pattern> REGEX = Arg.create(null);
- @CmdLine(name = "time_amount", help = "help")
- static final Arg<Amount<Long, Time>> TIME_AMOUNT = Arg.create(Amount.of(1L, Time.SECONDS));
- @CmdLine(name = "data_amount", help = "help")
- static final Arg<Amount<Long, Data>> DATA_AMOUNT = Arg.create(Amount.of(1L, Data.MB));
- @CmdLine(name = "range", help = "help")
- static final Arg<com.google.common.collect.Range<Integer>> RANGE =
- Arg.create(com.google.common.collect.Range.closed(1, 5));
- }
-
- @Test
- public void testStandardArgs() {
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.ENUM_VAL.get(), CoreMatchers.is(Optimizations.ALL)), "enum", "ALL");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.STRING_VAL.get(), is("newstring")),
- "string", "newstring");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.CHAR_VAL.get(), is('x')),
- "char", "x");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.BYTE_VAL.get(), is((byte) 10)),
- "byte", "10");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.SHORT_VAL.get(), is((short) 10)),
- "short", "10");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.INT_VAL.get(), is(10)),
- "int", "10");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.LONG_VAL.get(), is(10L)),
- "long", "10");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.FLOAT_VAL.get(), is(10f)),
- "float", "10.0");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.DOUBLE_VAL.get(), is(10d)),
- "double", "10.0");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.BOOL.get(), is(true)),
- "bool", "true");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.BOOL.get(), is(true)),
- "bool", "");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.REGEX.get().matcher("jack").matches(), is(true)),
- "regex", ".*ack$");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.BOOL.get(), is(false)),
- "no_bool", "");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.BOOL.get(), is(true)),
- "no_bool", "false");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.TIME_AMOUNT.get(), is(Amount.of(100L, Time.SECONDS))),
- "time_amount", "100secs");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.DATA_AMOUNT.get(), is(Amount.of(1L, Data.Gb))),
- "data_amount", "1Gb");
- test(StandardArgs.class,
- () -> assertThat(StandardArgs.RANGE.get(), is(com.google.common.collect.Range.closed(1, 5))),
- "range", "1-5");
- }
-
- public static class Name {
- private final String name;
-
- public Name(String name) {
- this.name = MorePreconditions.checkNotBlank(name);
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public int hashCode() {
- return this.name.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof Name) && name.equals(((Name) obj).name);
- }
- }
-
- @ArgParser
- public static class NameParser extends NonParameterizedTypeParser<Name> {
- @Override public Name doParse(String raw) {
- return new Name(raw);
- }
- }
-
- public static class MeaningOfLife {
- private final Long answer;
-
- public MeaningOfLife(Long answer) {
- this.answer = Preconditions.checkNotNull(answer);
- }
-
- @Override
- public int hashCode() {
- return this.answer.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof MeaningOfLife) && answer.equals(((MeaningOfLife) obj).answer);
- }
- }
-
- public static class Monty extends NonParameterizedTypeParser<MeaningOfLife> {
- @Override public MeaningOfLife doParse(String raw) {
- return new MeaningOfLife(42L);
- }
- }
-
- public static class CustomArgs {
- @CmdLine(name = "custom1", help = "help")
- static final Arg<Name> NAME_VAL = Arg.create(new Name("jim"));
-
- @CmdLine(name = "custom2", help = "help", parser = Monty.class)
- static final Arg<MeaningOfLife> MEANING_VAL = Arg.create(new MeaningOfLife(13L));
- }
-
- @Test
- public void testCustomArgs() {
- test(CustomArgs.class,
- () -> assertThat(CustomArgs.NAME_VAL.get(), is(new Name("jane"))), "custom1", "jane");
- test(CustomArgs.class,
- () -> assertThat(CustomArgs.MEANING_VAL.get(), is(new MeaningOfLife(42L))), "custom2", "jim");
- }
-
- @Test
- public void testHelp() {
- assertFalse(parse(StandardArgs.class, "-h"));
- assertFalse(parse(StandardArgs.class, "-help"));
- }
-
- @Test
- public void testAllowsEmptyString() {
- parse(StandardArgs.class, "-string=");
- assertThat(StandardArgs.STRING_VAL.get(), is(""));
-
- resetArgs(StandardArgs.class);
-
- parse(StandardArgs.class, "-string=''");
- assertThat(StandardArgs.STRING_VAL.get(), is(""));
-
- resetArgs(StandardArgs.class);
-
- parse(StandardArgs.class, "-string=\"\"");
- assertThat(StandardArgs.STRING_VAL.get(), is(""));
- }
-
- public static class CollectionArgs {
- @CmdLine(name = "stringList", help = "help")
- static final Arg<List<String>> STRING_LIST = Arg.create(null);
- @CmdLine(name = "intList", help = "help")
- static final Arg<List<Integer>> INT_LIST = Arg.create(null);
- @CmdLine(name = "stringSet", help = "help")
- static final Arg<Set<String>> STRING_SET = Arg.create(null);
- @CmdLine(name = "intSet", help = "help")
- static final Arg<Set<Integer>> INT_SET = Arg.create(null);
- @CmdLine(name = "stringStringMap", help = "help")
- static final Arg<Map<String, String>> STRING_STRING_MAP = Arg.create(null);
- @CmdLine(name = "intIntMap", help = "help")
- static final Arg<Map<Integer, Integer>> INT_INT_MAP = Arg.create(null);
- @CmdLine(name = "stringIntMap", help = "help")
- static final Arg<Map<String, Integer>> STRING_INT_MAP = Arg.create(null);
- @CmdLine(name = "intStringMap", help = "help")
- static final Arg<Map<Integer, String>> INT_STRING_MAP = Arg.create(null);
- @CmdLine(name = "stringStringPair", help = "help")
- static final Arg<Pair<String, String>> STRING_STRING_PAIR = Arg.create(null);
- @CmdLine(name = "intIntPair", help = "help")
- static final Arg<Pair<Integer, Integer>> INT_INT_PAIR = Arg.create(null);
- @CmdLine(name = "stringTimeAmountPair", help = "help")
- static final Arg<Pair<String, Amount<Long, Time>>> STRING_TIME_AMOUNT_PAIR = Arg.create(null);
- }
-
- @Test
- public void testCollectionArgs() {
- test(CollectionArgs.class,
- () -> assertThat(CollectionArgs.STRING_LIST.get(), is(Arrays.asList("a", "b", "c", "d"))),
- "stringList", "a,b,c,d");
- test(CollectionArgs.class,
- () -> assertThat(CollectionArgs.INT_LIST.get(), is(Arrays.asList(1, 2, 3, 4))),
- "intList", "1, 2, 3, 4");
- test(CollectionArgs.class,
- () -> {
- Set<String> expected = ImmutableSet.of("a", "b", "c", "d");
- assertThat(CollectionArgs.STRING_SET.get(), is(expected));
- },
- "stringSet", "a,b,c,d");
- test(CollectionArgs.class,
- () -> {
- Set<Integer> expected = ImmutableSet.of(1, 2, 3, 4);
- assertThat(CollectionArgs.INT_SET.get(), is(expected));
- },
- "intSet", "1, 2, 3, 4");
- test(CollectionArgs.class,
- () -> {
- Map<String, String> expected = ImmutableMap.of("a", "b", "c", "d", "e", "f", "g", "h");
- assertThat(CollectionArgs.STRING_STRING_MAP.get(), is(expected));
- },
- "stringStringMap", "a=b, c=d, e=f, g=h");
- test(CollectionArgs.class,
- () -> {
- Map<Integer, Integer> expected = ImmutableMap.of(1, 2, 3, 4, 5, 6, 7, 8);
- assertThat(CollectionArgs.INT_INT_MAP.get(), is(expected));
- },
- "intIntMap", "1 = 2,3=4, 5=6 ,7=8");
- test(CollectionArgs.class,
- () -> {
- Map<String, Integer> expected = ImmutableMap.of("a", 1, "b", 2, "c", 3, "d", 4);
- assertThat(CollectionArgs.STRING_INT_MAP.get(), is(expected));
- },
- "stringIntMap", "a=1 , b=2, c=3 ,d=4");
- test(CollectionArgs.class,
- () -> {
- Map<Integer, String> expected = ImmutableMap.of(1, "1", 2, "2", 3, "3", 4, "4");
- assertThat(CollectionArgs.INT_STRING_MAP.get(), is(expected));
- },
- "intStringMap", " 1=1 , 2=2, 3=3,4=4");
- test(CollectionArgs.class,
- () -> assertThat(CollectionArgs.STRING_STRING_PAIR.get(), is(Pair.of("foo", "bar"))),
- "stringStringPair", "foo , bar");
- test(CollectionArgs.class,
- () -> assertThat(CollectionArgs.INT_INT_PAIR.get(), is(Pair.of(10, 20))),
- "intIntPair", "10 ,20");
- test(CollectionArgs.class,
- () -> assertThat(CollectionArgs.STRING_TIME_AMOUNT_PAIR.get(),
- is(Pair.of("fred", Amount.of(42L, Time.MINUTES)))),
- "stringTimeAmountPair", "fred ,42mins");
- test(CollectionArgs.class,
- CollectionArgs.STRING_TIME_AMOUNT_PAIR::get,
- true, "stringTimeAmountPair", "george,1MB");
-
- }
-
- static class Serializable1 implements Serializable { }
- static class Serializable2 implements Serializable { }
-
- public static class WildcardArgs {
- @CmdLine(name = "class", help = "help")
- static final Arg<? extends Class<? extends Serializable>> CLAZZ =
- Arg.create(Serializable1.class);
- @CmdLine(name = "classList1", help = "help")
- static final Arg<List<Class<? extends Serializable>>> CLASS_LIST_1 = Arg.create(null);
- @CmdLine(name = "classList2", help = "help")
- static final Arg<List<? extends Class<? extends Serializable>>> CLASS_LIST_2 = Arg.create(null);
- }
-
- @Test
- public void testWildcardArgs() {
- test(WildcardArgs.class,
- () -> assertSame(Serializable2.class, WildcardArgs.CLAZZ.get()),
- "class", Serializable2.class.getName());
-
- test(WildcardArgs.class,
- WildcardArgs.CLAZZ::get,
- true, "class", Runnable.class.getName());
-
- test(WildcardArgs.class,
- () -> assertEquals(ImmutableList.of(Serializable1.class, Serializable2.class),
- WildcardArgs.CLASS_LIST_1.get()),
- "classList1", Serializable1.class.getName() + "," + Serializable2.class.getName());
-
- test(WildcardArgs.class,
- () -> assertEquals(ImmutableList.of(Serializable2.class), WildcardArgs.CLASS_LIST_2.get()),
- "classList2", Serializable2.class.getName());
-
- test(WildcardArgs.class,
- WildcardArgs.CLASS_LIST_2::get,
- true, "classList2", Serializable1.class.getName() + "," + Runnable.class.getName());
- }
-
- @Target(FIELD)
- @Retention(RUNTIME)
- public static @interface Equals {
- String value();
- }
-
- @VerifierFor(Equals.class)
- public static class SameName implements Verifier<Name> {
- @Override
- public void verify(Name value, Annotation annotation) {
- Preconditions.checkArgument(getValue(annotation).equals(value.getName()));
- }
-
- @Override
- public String toString(Class<? extends Name> argType, Annotation annotation) {
- return "name = " + getValue(annotation);
- }
-
- private String getValue(Annotation annotation) {
- return ((Equals) annotation).value();
- }
- }
-
- public static class VerifyArgs {
- @Equals("jake") @CmdLine(name = "custom", help = "help")
- static final Arg<Name> CUSTOM_VAL = Arg.create(new Name("jake"));
- @NotEmpty @CmdLine(name = "string", help = "help")
- static final Arg<String> STRING_VAL = Arg.create("string");
- @NotEmpty @CmdLine(name = "optional_string", help = "help")
- static final Arg<String> OPTIONAL_STRING_VAL = Arg.create(null);
- @Positive
- @CmdLine(name = "int", help = "help")
- static final Arg<Integer> INT_VAL = Arg.create(1);
- @NotNegative
- @CmdLine(name = "long", help = "help")
- static final Arg<Long> LONG_VAL = Arg.create(0L);
- @Range(lower = 10, upper = 20) @CmdLine(name = "float", help = "help")
- static final Arg<Float> FLOAT_VAL = Arg.create(10F);
- @CmdLine(name = "double", help = "help")
- static final Arg<Double> DOUBLE_VAL = Arg.create(0D);
- @CmdLine(name = "bool", help = "help")
- static final Arg<Boolean> BOOL = Arg.create(false);
- @CmdLine(name = "arg_without_default", help = "help")
- static final Arg<Boolean> ARG_WITHOUT_DEFAULT = Arg.create();
- }
-
- @Test
- public void testEnforcesConstraints() {
- test(VerifyArgs.class,
- () -> {
- assertThat(VerifyArgs.STRING_VAL.get(), is("newstring"));
- assertThat(VerifyArgs.OPTIONAL_STRING_VAL.get(), nullValue(String.class));
- },
- "string", "newstring");
-
- testFails(VerifyArgs.class, "custom", "jane");
- testFails(VerifyArgs.class, "string", "");
- testFails(VerifyArgs.class, "optional_string", "");
- testFails(VerifyArgs.class, "int", "0");
- testFails(VerifyArgs.class, "long", "-1");
-
- test(VerifyArgs.class,
- () -> assertThat(VerifyArgs.FLOAT_VAL.get(), is(10.5f)),
- "float", "10.5");
- testFails(VerifyArgs.class, "float", "9");
- }
-
- @Test
- public void testJoinKeysToValues() {
- assertThat(ArgScanner.joinKeysToValues(Arrays.asList("")), is(Arrays.asList("")));
- assertThat(ArgScanner.joinKeysToValues(Arrays.asList("-a", "b", "-c", "-d")),
- is(Arrays.asList("-a=b", "-c", "-d")));
- assertThat(ArgScanner.joinKeysToValues(Arrays.asList("-a='b'", "-c", "-d", "'e'")),
- is(Arrays.asList("-a='b'", "-c", "-d='e'")));
- assertThat(ArgScanner.joinKeysToValues(Arrays.asList("-a=-b", "c", "-d", "\"e\"")),
- is(Arrays.asList("-a=-b", "c", "-d=\"e\"")));
- }
-
- public static class ShortHelpArg {
- @CmdLine(name = "h", help = "help")
- static final Arg<String> SHORT_HELP = Arg.create("string");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testShortHelpReserved() {
- parse(ShortHelpArg.class);
- }
-
- public static class LongHelpArg {
- @CmdLine(name = "help", help = "help")
- static final Arg<String> LONG_HELP = Arg.create("string");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testLongHelpReserved() {
- parse(LongHelpArg.class);
- }
-
- public static class DuplicateNames {
- @CmdLine(name = "string", help = "help") static final Arg<String> STRING_1 = Arg.create();
- @CmdLine(name = "string", help = "help") static final Arg<String> STRING_2 = Arg.create();
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testRejectsDuplicates() {
- parse(DuplicateNames.class, "-string-str");
- }
-
- public static class OneRequired {
- @CmdLine(name = "string1", help = "help")
- static final Arg<String> STRING_1 = Arg.create(null);
- @NotNull
- @CmdLine(name = "string2", help = "help")
- static final Arg<String> STRING_2 = Arg.create(null);
- }
-
- @Test
- public void testRequiredProvided() {
- parse(OneRequired.class, "-string2=blah");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testMissingRequired() {
- parse(OneRequired.class, "-string1=blah");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testUnrecognizedArg() {
- parse(OneRequired.class, "-string2=blah", "-string3=blah");
- }
-
- public static class NameClashA {
- @CmdLine(name = "string", help = "help")
- static final Arg<String> STRING = Arg.create(null);
- @CmdLine(name = "boolean", help = "help")
- static final Arg<Boolean> BOOLEAN = Arg.create(true);
- }
-
- public static class NameClashB {
- @CmdLine(name = "string", help = "help")
- static final Arg<String> STRING_1 = Arg.create(null);
- @CmdLine(name = "boolean", help = "help")
- static final Arg<Boolean> BOOLEAN_1 = Arg.create(true);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testDisallowsShortNameOnArgCollision() {
- parse(ImmutableList.of(NameClashA.class, NameClashB.class), "-string=blah");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testDisallowsShortNegNameOnArgCollision() {
- parse(ImmutableList.of(NameClashA.class, NameClashB.class), "-no_boolean");
- }
-
- public static class AmountContainer {
- @CmdLine(name = "time_amount", help = "help")
- static final Arg<Amount<Integer, Time>> TIME_AMOUNT = Arg.create(null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testBadUnitType() {
- parse(ImmutableList.of(AmountContainer.class), "-time_amount=1Mb");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testUnrecognizedUnitType() {
- parse(ImmutableList.of(AmountContainer.class), "-time_amount=1abcd");
- }
-
- // TODO(William Farner): Do we want to support nested parameterized args? If so, need to define a
- // syntax for that and build it in.
- // e.g. List<List<Integer>>, List<Pair<String, String>>
-
- private static void testFails(Class<?> scope, String arg, String value) {
- test(scope, null, true, arg, value);
- }
-
- private static void test(Class<?> scope, Command validate, String arg, String value) {
- test(scope, validate, false, arg, value);
- }
-
- private static void test(Class<?> scope, Command validate, boolean expectFails, String arg,
- String value) {
-
- if (value.isEmpty()) {
- testValidate(scope, validate, expectFails, String.format("-%s", arg));
- } else {
- testValidate(scope, validate, expectFails, String.format("-%s=%s", arg, value));
- testValidate(scope, validate, expectFails, String.format("-%s='%s'", arg, value));
- testValidate(scope, validate, expectFails, String.format("-%s=\"%s\"", arg, value));
- testValidate(scope, validate, expectFails, String.format("-%s", arg), value);
- testValidate(scope, validate, expectFails,
- String.format("-%s", arg), String.format("'%s'", value));
- testValidate(scope, validate, expectFails, String.format("-%s \"%s\"", arg, value));
- testValidate(scope, validate, expectFails,
- String.format("-%s", arg), String.format("%s", value));
- }
- }
-
- private static void testValidate(Class<?> scope, Command validate, boolean expectFails,
- String... args) {
- resetArgs(scope);
- IllegalArgumentException exception = null;
- try {
- assertTrue(parse(scope, args));
- } catch (IllegalArgumentException e) {
- exception = e;
- }
-
- if (!expectFails && exception != null) {
- throw exception;
- }
- if (expectFails && exception == null) {
- fail("Expected exception.");
- }
-
- if (validate != null) {
- validate.execute();
- }
- resetArgs(scope);
- }
-
- private static void resetArgs(Class<?> scope) {
- for (Field field : scope.getDeclaredFields()) {
- if (Arg.class.isAssignableFrom(field.getType()) && Modifier.isStatic(field.getModifiers())) {
- try {
- ((Arg) field.get(null)).reset();
- } catch (IllegalAccessException e) {
- fail(e.getMessage());
- }
- }
- }
- }
-
- private static boolean parse(final Class<?> scope, String... args) {
- return parse(ImmutableList.of(scope), args);
- }
-
- private static boolean parse(Iterable<? extends Class<?>> scopes, String... args) {
- Predicate<Field> filter = Predicates.or(Iterables.transform(scopes, TO_SCOPE_PREDICATE));
- PrintStream devNull = new PrintStream(ByteStreams.nullOutputStream());
- return new ArgScanner(devNull).parse(filter, Arrays.asList(args));
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/ArgTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/ArgTest.java b/commons/src/test/java/org/apache/aurora/common/args/ArgTest.java
deleted file mode 100644
index cbcc575..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/ArgTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.fail;
-
-public class ArgTest {
-
- @Test
- public void testSetAfterGet() {
- Arg<Boolean> arg = new Arg<Boolean>(false);
- arg.get();
- try {
- arg.set(true);
- fail("Expected set after get to throw");
- } catch (IllegalStateException e) {
- assertFalse(arg.get());
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/ArgsTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/ArgsTest.java b/commons/src/test/java/org/apache/aurora/common/args/ArgsTest.java
deleted file mode 100644
index 7bccaba..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/ArgsTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args;
-
-import java.io.File;
-import java.io.IOException;
-
-import com.google.common.collect.ImmutableList;
-
-import org.apache.aurora.common.args.constraints.NotEmpty;
-import org.apache.aurora.common.args.constraints.Range;
-import org.junit.Test;
-
-import static junit.framework.Assert.assertEquals;
-
-public class ArgsTest {
- private static class App {
- @CmdLine(name = "db", help = "help")
- private static final Arg<File> DB = Arg.create();
-
- @NotEmpty
- @CmdLine(name = "name", help = "help")
- private final Arg<String> name = Arg.create();
- }
-
- @Test
- public void testMixed() throws IOException {
- App app = new App();
-
- new ArgScanner().parse(Args.from(ArgFilters.selectClass(App.class), app),
- ImmutableList.of("-name=bob", "-db=fred", "1", "137"));
-
- assertEquals(new File("fred"), App.DB.get());
- assertEquals("bob", app.name.get());
- }
-
- @Test
- public void testReentrance() throws IOException {
- class InnerApp {
- @Range(lower = 0.0, upper = 1.0)
- @CmdLine(name = "level", help = "help")
- private final Arg<Double> level = Arg.create();
- }
-
- InnerApp app1 = new InnerApp();
- InnerApp app2 = new InnerApp();
-
- new ArgScanner().parse(Args.from(ArgFilters.selectClass(InnerApp.class), app1),
- ImmutableList.of("-level=0.5"));
- new ArgScanner().parse(Args.from(ArgFilters.selectClass(InnerApp.class), app2),
- ImmutableList.of("-level=0.00729"));
-
- assertEquals(0.5, app1.level.get(), 0.00001);
- assertEquals(0.00729, app2.level.get(), 0.00001);
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/OptionInfoTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/OptionInfoTest.java b/commons/src/test/java/org/apache/aurora/common/args/OptionInfoTest.java
deleted file mode 100644
index 7573430..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/OptionInfoTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args;
-
-import java.io.File;
-import java.util.List;
-
-import com.google.common.collect.ImmutableList;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-import static junit.framework.Assert.assertEquals;
-
-public class OptionInfoTest {
- private static class App {
- @CmdLine(name = "files", help = "help.", argFile = true)
- private final Arg<List<File>> files = Arg.<List<File>>create(ImmutableList.<File>of());
-
- @CmdLine(name = "flag", help = "help.")
- private final Arg<Boolean> flag = Arg.create();
- }
-
- @Rule
- public TemporaryFolder tmpDir = new TemporaryFolder();
- private App app;
-
- @Before
- public void setUp() throws Exception {
- app = new App();
- }
-
- @Test
- public void testArgumentFilesRegularFormat() throws Exception {
- new ArgScanner().parse(Args.from(ArgFilters.selectClass(App.class), app),
- ImmutableList.of("-files=1.txt,2.txt"));
- assertEquals(
- ImmutableList.of(new File("1.txt"), new File("2.txt")),
- app.files.get());
- }
-
- @Test
- public void testArgumentFlagCreateFromField() throws Exception {
- OptionInfo optionInfo = OptionInfo.createFromField(App.class.getDeclaredField("flag"), app);
- assertEquals("flag", optionInfo.getName());
- assertEquals("help.", optionInfo.getHelp());
- assertEquals("no_flag", optionInfo.getNegatedName());
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/ParsersTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/ParsersTest.java b/commons/src/test/java/org/apache/aurora/common/args/ParsersTest.java
deleted file mode 100644
index 991291d..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/ParsersTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.reflect.TypeToken;
-
-import org.apache.aurora.common.args.apt.Configuration.ParserInfo;
-import org.apache.aurora.common.args.parsers.NonParameterizedTypeParser;
-import org.apache.aurora.common.args.parsers.PairParser;
-import org.apache.aurora.common.collections.Pair;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-
-public class ParsersTest {
-
- private Parsers defaultParsers;
-
- @Before
- public void setUp() {
- defaultParsers =
- new Parsers(ImmutableMap.<Class<?>, Parser<?>>of(
- String.class, new StringParser(),
- Pair.class, new PairParser()));
- }
-
- @Test
- public void testParseTypeFamily() {
- assertNotNull(defaultParsers.get(TypeToken.of(String.class)));
-
- class Credentials extends Pair<String, String> {
- public Credentials(String first, String second) {
- super(first, second);
- }
- }
- Parser parser = defaultParsers.get(TypeToken.of(Credentials.class));
- assertNotNull(parser);
- assertSame(parser, defaultParsers.get(TypeToken.of(Pair.class)));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testNoParser() {
- class NoParserForMe { }
- assertNull(defaultParsers.get(TypeToken.of(NoParserForMe.class)));
- }
-
- static class StringParser extends NonParameterizedTypeParser<Integer> {
- @Override public Integer doParse(String raw) throws IllegalArgumentException {
- return raw.length();
- }
- }
-
- @Test
- public void testNonPublicParsers() {
- @SuppressWarnings("unchecked")
- Parser<Integer> parser = (Parser<Integer>)
- Parsers.INFO_TO_PARSER.apply(
- new ParserInfo(Integer.class.getName(), StringParser.class.getName()));
-
- assertEquals(
- Integer.valueOf(42),
- parser.parse(null, null, "themeaningoflifeisfortytwointhebookbyadams"));
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/ArgsRoot.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/ArgsRoot.java b/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/ArgsRoot.java
deleted file mode 100644
index fefff0c..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/ArgsRoot.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args.argfilterstest;
-
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-
-/**
- * @author John Sirois
- */
-public final class ArgsRoot {
- @CmdLine(name = "args_root", help = "")
- static final Arg<String> ARGS_ROOT = Arg.create();
-
- private ArgsRoot() {
- // Test class.
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/ArgsA.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/ArgsA.java b/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/ArgsA.java
deleted file mode 100644
index 7777875..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/ArgsA.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args.argfilterstest.subpackageA;
-
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-
-/**
- * @author John Sirois
- */
-public final class ArgsA {
- @CmdLine(name = "args_a", help = "")
- static final Arg<String> ARGS_A = Arg.create();
-
- private ArgsA() {
- // Test class.
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/subsubpackage1/ArgsA1.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/subsubpackage1/ArgsA1.java b/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/subsubpackage1/ArgsA1.java
deleted file mode 100644
index 43af4f2..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageA/subsubpackage1/ArgsA1.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args.argfilterstest.subpackageA.subsubpackage1;
-
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-
-/**
- * @author John Sirois
- */
-public final class ArgsA1 {
- @CmdLine(name = "args_a1", help = "")
- static final Arg<String> ARGS_A1 = Arg.create();
-
- private ArgsA1() {
- // Test class.
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageB/ArgsB.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageB/ArgsB.java b/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageB/ArgsB.java
deleted file mode 100644
index 11ed7e3..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageB/ArgsB.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args.argfilterstest.subpackageB;
-
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-
-/**
- * @author John Sirois
- */
-public final class ArgsB {
- @CmdLine(name = "args_b", help = "")
- static final Arg<String> ARGS_B = Arg.create();
-
- private ArgsB() {
- // Test class.
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageBwithSuffix/ArgsBWithSuffix.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageBwithSuffix/ArgsBWithSuffix.java b/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageBwithSuffix/ArgsBWithSuffix.java
deleted file mode 100644
index 0ef8d5f..0000000
--- a/commons/src/test/java/org/apache/aurora/common/args/argfilterstest/subpackageBwithSuffix/ArgsBWithSuffix.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.aurora.common.args.argfilterstest.subpackageBwithSuffix;
-
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-
-/**
- * @author John Sirois
- */
-public final class ArgsBWithSuffix {
- @CmdLine(name = "args_b_with_suffix", help = "")
- static final Arg<String> ARGS_B_WITH_SUFFIX = Arg.create();
-
- private ArgsBWithSuffix() {
- // Test class.
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/config/checkstyle/checkstyle.xml
----------------------------------------------------------------------
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index abc0760..d1f8b0f 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -249,11 +249,6 @@ limitations under the License.
<module name="FinalClass"/>
<module name="HideUtilityClassConstructor"/>
<module name="InterfaceIsType"/>
- <module name="VisibilityModifier">
- <property name="protectedAllowed" value="true"/>
- <!-- Allow public members at the coder's discretion, for struct-like things. -->
- <property name="publicMemberPattern" value="^.*$" />
- </module>
<module name="MutableException"/>
<!-- Miscellaneous other checks. -->
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/config/checkstyle/suppressions.xml
----------------------------------------------------------------------
diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml
index cd7fd0a..c4081b9 100644
--- a/config/checkstyle/suppressions.xml
+++ b/config/checkstyle/suppressions.xml
@@ -19,7 +19,7 @@ limitations under the License.
<suppressions>
<!-- Allow use of System.exit() in main. -->
- <suppress files="org/apache/aurora/scheduler/app/SchedulerMain.java"
+ <suppress files="org/apache/aurora/scheduler/config/CommandLine.java"
checks="RegexpSinglelineJava"/>
<suppress files="org/apache/aurora/scheduler/storage/db/migration/.*" checks="TypeName" />
<suppress files="org/apache/aurora/scheduler/storage/db/testmigration/.*" checks="TypeName" />
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/config/findbugs/excludeFilter.xml
----------------------------------------------------------------------
diff --git a/config/findbugs/excludeFilter.xml b/config/findbugs/excludeFilter.xml
index f7d5ae0..4d5b36f 100644
--- a/config/findbugs/excludeFilter.xml
+++ b/config/findbugs/excludeFilter.xml
@@ -120,4 +120,10 @@ limitations under the License.
</Or>
<Bug pattern="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT" />
</Match>
+
+ <Match>
+ <!-- Options fields may be flagged as always null, since they are set reflectively. -->
+ <Class name="~org.apache.aurora.scheduler.*Options" />
+ <Bug pattern="UWF_NULL_FIELD" />
+ </Match>
</FindBugsFilter>
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java b/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
index cb783ce..7d37668 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/SchedulingBenchmarks.java
@@ -47,6 +47,8 @@ import org.apache.aurora.scheduler.TierModule;
import org.apache.aurora.scheduler.async.AsyncModule;
import org.apache.aurora.scheduler.async.DelayExecutor;
import org.apache.aurora.scheduler.base.TaskTestUtil;
+import org.apache.aurora.scheduler.config.CliOptions;
+import org.apache.aurora.scheduler.config.types.TimeAmount;
import org.apache.aurora.scheduler.configuration.executor.ExecutorSettings;
import org.apache.aurora.scheduler.events.EventSink;
import org.apache.aurora.scheduler.filter.SchedulingFilter;
@@ -99,7 +101,7 @@ public class SchedulingBenchmarks {
@Fork(1)
@State(Scope.Thread)
public abstract static class AbstractBase {
- private static final Amount<Long, Time> NO_DELAY = Amount.of(1L, Time.MILLISECONDS);
+ private static final TimeAmount NO_DELAY = new TimeAmount(1L, Time.MILLISECONDS);
private static final Amount<Long, Time> DELAY_FOREVER = Amount.of(30L, Time.DAYS);
private static final Integer BATCH_SIZE = 5;
protected Storage storage;
@@ -118,10 +120,16 @@ public class SchedulingBenchmarks {
final FakeClock clock = new FakeClock();
clock.setNowMillis(System.currentTimeMillis());
+ CliOptions options = new CliOptions();
+ options.preemptor.enablePreemptor = true;
+ options.preemptor.preemptionDelay = NO_DELAY;
+ options.preemptor.preemptionSlotSearchInterval = NO_DELAY;
+ options.preemptor.reservationMaxBatchSize = BATCH_SIZE;
+
// TODO(maxim): Find a way to DRY it and reuse existing modules instead.
Injector injector = Guice.createInjector(
- new StateModule(),
- new PreemptorModule(true, NO_DELAY, NO_DELAY, BATCH_SIZE),
+ new StateModule(new CliOptions()),
+ new PreemptorModule(options),
new TierModule(TaskTestUtil.TIER_CONFIG),
new PrivateModule() {
@Override
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/jmh/java/org/apache/aurora/benchmark/StateManagerBenchmarks.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/StateManagerBenchmarks.java b/src/jmh/java/org/apache/aurora/benchmark/StateManagerBenchmarks.java
index b4f14f1..c293a9f 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/StateManagerBenchmarks.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/StateManagerBenchmarks.java
@@ -185,9 +185,9 @@ public class StateManagerBenchmarks {
bind(StatsProvider.class).toInstance(new FakeStatsProvider());
}
},
- DbModule.productionModule(Bindings.KeyFactory.PLAIN),
+ DbModule.productionModule(Bindings.KeyFactory.PLAIN, new DbModule.Options()),
// This is needed for storage
- new AsyncModule()
+ new AsyncModule(new AsyncModule.Options())
);
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java b/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
index c81387f..45c2ab9 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/StatusUpdateBenchmark.java
@@ -53,6 +53,7 @@ import org.apache.aurora.scheduler.TaskStatusHandlerImpl;
import org.apache.aurora.scheduler.TierModule;
import org.apache.aurora.scheduler.base.AsyncUtil;
import org.apache.aurora.scheduler.base.TaskTestUtil;
+import org.apache.aurora.scheduler.config.CliOptions;
import org.apache.aurora.scheduler.configuration.executor.ExecutorSettings;
import org.apache.aurora.scheduler.events.EventSink;
import org.apache.aurora.scheduler.events.PubsubEvent;
@@ -179,7 +180,7 @@ public class StatusUpdateBenchmark {
storage = new SlowStorageWrapper(DbUtil.createStorage());
Injector injector = Guice.createInjector(
- new StateModule(),
+ new StateModule(new CliOptions()),
new TierModule(TaskTestUtil.TIER_CONFIG),
new AbstractModule() {
@Override
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/jmh/java/org/apache/aurora/benchmark/TaskStoreBenchmarks.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/TaskStoreBenchmarks.java b/src/jmh/java/org/apache/aurora/benchmark/TaskStoreBenchmarks.java
index 5b4d2a2..f5e44df 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/TaskStoreBenchmarks.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/TaskStoreBenchmarks.java
@@ -85,7 +85,9 @@ public class TaskStoreBenchmarks {
public void setUp() {
storage = Guice.createInjector(
Modules.combine(
- DbModule.testModuleWithWorkQueue(PLAIN, Optional.of(new InMemStoresModule(PLAIN))),
+ DbModule.testModuleWithWorkQueue(
+ PLAIN,
+ Optional.of(new InMemStoresModule(new DbModule.Options(), PLAIN))),
new AbstractModule() {
@Override
protected void configure() {
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/jmh/java/org/apache/aurora/benchmark/ThriftApiBenchmarks.java
----------------------------------------------------------------------
diff --git a/src/jmh/java/org/apache/aurora/benchmark/ThriftApiBenchmarks.java b/src/jmh/java/org/apache/aurora/benchmark/ThriftApiBenchmarks.java
index 440c4fc..7b40506 100644
--- a/src/jmh/java/org/apache/aurora/benchmark/ThriftApiBenchmarks.java
+++ b/src/jmh/java/org/apache/aurora/benchmark/ThriftApiBenchmarks.java
@@ -154,8 +154,8 @@ public class ThriftApiBenchmarks {
bind(ConfigurationManager.class).toInstance(TaskTestUtil.CONFIGURATION_MANAGER);
}
},
- new AsyncModule(),
- DbModule.productionModule(Bindings.KeyFactory.PLAIN),
+ new AsyncModule(new AsyncModule.Options()),
+ DbModule.productionModule(Bindings.KeyFactory.PLAIN, new DbModule.Options()),
new ThriftModule.ReadOnly());
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/main/java/org/apache/aurora/scheduler/SchedulerModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/SchedulerModule.java b/src/main/java/org/apache/aurora/scheduler/SchedulerModule.java
index a62bb06..3821819 100644
--- a/src/main/java/org/apache/aurora/scheduler/SchedulerModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/SchedulerModule.java
@@ -20,20 +20,21 @@ import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject;
import javax.inject.Singleton;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
import com.google.inject.AbstractModule;
import com.google.inject.PrivateModule;
import com.google.inject.TypeLiteral;
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-import org.apache.aurora.common.args.constraints.Positive;
-import org.apache.aurora.common.quantity.Amount;
import org.apache.aurora.common.quantity.Time;
import org.apache.aurora.common.stats.StatsProvider;
import org.apache.aurora.scheduler.BatchWorker.NoResult;
import org.apache.aurora.scheduler.SchedulerLifecycle.LeadingOptions;
import org.apache.aurora.scheduler.TaskIdGenerator.TaskIdGeneratorImpl;
import org.apache.aurora.scheduler.base.AsyncUtil;
+import org.apache.aurora.scheduler.config.CliOptions;
+import org.apache.aurora.scheduler.config.types.TimeAmount;
+import org.apache.aurora.scheduler.config.validators.PositiveNumber;
import org.apache.aurora.scheduler.events.PubsubEventModule;
import org.apache.aurora.scheduler.storage.Storage;
import org.apache.mesos.v1.Protos;
@@ -49,25 +50,33 @@ public class SchedulerModule extends AbstractModule {
private static final Logger LOG = LoggerFactory.getLogger(SchedulerModule.class);
- @CmdLine(name = "max_registration_delay",
- help = "Max allowable delay to allow the driver to register before aborting")
- private static final Arg<Amount<Long, Time>> MAX_REGISTRATION_DELAY =
- Arg.create(Amount.of(1L, Time.MINUTES));
-
- @CmdLine(name = "max_leading_duration",
- help = "After leading for this duration, the scheduler should commit suicide.")
- private static final Arg<Amount<Long, Time>> MAX_LEADING_DURATION =
- Arg.create(Amount.of(1L, Time.DAYS));
+ @Parameters(separators = "=")
+ public static class Options {
+ @Parameter(names = "-max_registration_delay",
+ description = "Max allowable delay to allow the driver to register before aborting")
+ public TimeAmount maxRegistrationDelay = new TimeAmount(1, Time.MINUTES);
+
+ @Parameter(names = "-max_leading_duration",
+ description = "After leading for this duration, the scheduler should commit suicide.")
+ public TimeAmount maxLeadingDuration = new TimeAmount(1, Time.DAYS);
+
+ @Parameter(names = "-max_status_update_batch_size",
+ validateValueWith = PositiveNumber.class,
+ description = "The maximum number of status updates that can be processed in a batch.")
+ public int maxStatusUpdateBatchSize = 1000;
+
+ @Parameter(names = "-max_task_event_batch_size",
+ validateValueWith = PositiveNumber.class,
+ description =
+ "The maximum number of task state change events that can be processed in a batch.")
+ public int maxTaskEventBatchSize = 300;
+ }
- @Positive
- @CmdLine(name = "max_status_update_batch_size",
- help = "The maximum number of status updates that can be processed in a batch.")
- private static final Arg<Integer> MAX_STATUS_UPDATE_BATCH_SIZE = Arg.create(1000);
+ private final Options options;
- @Positive
- @CmdLine(name = "max_task_event_batch_size",
- help = "The maximum number of task state change events that can be processed in a batch.")
- private static final Arg<Integer> MAX_TASK_EVENT_BATCH_SIZE = Arg.create(300);
+ public SchedulerModule(Options options) {
+ this.options = options;
+ }
@Override
protected void configure() {
@@ -77,7 +86,7 @@ public class SchedulerModule extends AbstractModule {
@Override
protected void configure() {
bind(LeadingOptions.class).toInstance(
- new LeadingOptions(MAX_REGISTRATION_DELAY.get(), MAX_LEADING_DURATION.get()));
+ new LeadingOptions(options.maxRegistrationDelay, options.maxLeadingDuration));
final ScheduledExecutorService executor =
AsyncUtil.singleThreadLoggingScheduledExecutor("Lifecycle-%d", LOG);
@@ -98,7 +107,7 @@ public class SchedulerModule extends AbstractModule {
.toInstance(new LinkedBlockingQueue<>());
bind(new TypeLiteral<Integer>() { })
.annotatedWith(TaskStatusHandlerImpl.MaxBatchSize.class)
- .toInstance(MAX_STATUS_UPDATE_BATCH_SIZE.get());
+ .toInstance(options.maxStatusUpdateBatchSize);
bind(TaskStatusHandler.class).to(TaskStatusHandlerImpl.class);
bind(TaskStatusHandlerImpl.class).in(Singleton.class);
@@ -110,9 +119,8 @@ public class SchedulerModule extends AbstractModule {
public static class TaskEventBatchWorker extends BatchWorker<NoResult> {
@Inject
- TaskEventBatchWorker(Storage storage, StatsProvider statsProvider) {
-
- super(storage, statsProvider, MAX_TASK_EVENT_BATCH_SIZE.get());
+ TaskEventBatchWorker(CliOptions options, Storage storage, StatsProvider statsProvider) {
+ super(storage, statsProvider, options.scheduler.maxTaskEventBatchSize);
}
@Override
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/main/java/org/apache/aurora/scheduler/TierModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/TierModule.java b/src/main/java/org/apache/aurora/scheduler/TierModule.java
index 61afa31..4244103 100644
--- a/src/main/java/org/apache/aurora/scheduler/TierModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/TierModule.java
@@ -17,17 +17,17 @@ import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.io.Files;
import com.google.common.io.Resources;
import com.google.inject.AbstractModule;
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-import org.apache.aurora.common.args.constraints.CanRead;
import org.apache.aurora.scheduler.TierManager.TierManagerImpl;
import org.apache.aurora.scheduler.TierManager.TierManagerImpl.TierConfig;
+import org.apache.aurora.scheduler.config.validators.ReadableFile;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,15 +45,19 @@ public class TierModule extends AbstractModule {
@VisibleForTesting
static final String TIER_CONFIG_PATH = "org/apache/aurora/scheduler/tiers.json";
- @CanRead
- @CmdLine(name = "tier_config",
- help = "Configuration file defining supported task tiers, task traits and behaviors.")
- private static final Arg<File> TIER_CONFIG_FILE = Arg.create();
+ @Parameters(separators = "=")
+ public static class Options {
+ @Parameter(names = "-tier_config",
+ validateValueWith = ReadableFile.class,
+ description =
+ "Configuration file defining supported task tiers, task traits and behaviors.")
+ public File tierConfigFile;
+ }
private final TierConfig tierConfig;
- public TierModule() {
- this(parseTierConfig(readTierFile()));
+ public TierModule(Options options) {
+ this(parseTierConfig(readTierFile(options)));
}
@VisibleForTesting
@@ -66,13 +70,14 @@ public class TierModule extends AbstractModule {
bind(TierManager.class).toInstance(new TierManagerImpl(tierConfig));
}
- static String readTierFile() {
+ static String readTierFile(Options options) {
try {
- return TIER_CONFIG_FILE.hasAppliedValue()
- ? Files.toString(TIER_CONFIG_FILE.get(), StandardCharsets.UTF_8)
- : Resources.toString(
+ File tierConfig = options.tierConfigFile;
+ return tierConfig == null
+ ? Resources.toString(
TierModule.class.getClassLoader().getResource(TIER_CONFIG_PATH),
- StandardCharsets.UTF_8);
+ StandardCharsets.UTF_8)
+ : Files.toString(tierConfig, StandardCharsets.UTF_8);
} catch (IOException e) {
LOG.error("Error loading tier configuration file.");
throw new RuntimeException(e);
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/app/AppModule.java b/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
index 081dff2..54d7d4c 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/AppModule.java
@@ -13,30 +13,31 @@
*/
package org.apache.aurora.scheduler.app;
-import java.util.Set;
+import java.util.List;
import javax.inject.Singleton;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
import com.google.inject.AbstractModule;
import org.apache.aurora.GuiceUtils;
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.CmdLine;
-import org.apache.aurora.common.args.constraints.Positive;
import org.apache.aurora.common.inject.TimedInterceptor;
import org.apache.aurora.common.stats.Stats;
import org.apache.aurora.common.stats.StatsProvider;
import org.apache.aurora.common.util.Clock;
import org.apache.aurora.gen.Container;
import org.apache.aurora.gen.Container._Fields;
+import org.apache.aurora.gen.DockerParameter;
import org.apache.aurora.scheduler.SchedulerModule;
import org.apache.aurora.scheduler.SchedulerServicesModule;
-import org.apache.aurora.scheduler.app.SchedulerMain.DriverKind;
+import org.apache.aurora.scheduler.app.SchedulerMain.Options.DriverKind;
import org.apache.aurora.scheduler.async.AsyncModule;
+import org.apache.aurora.scheduler.config.CliOptions;
+import org.apache.aurora.scheduler.config.validators.PositiveNumber;
import org.apache.aurora.scheduler.configuration.ConfigurationManager.ConfigurationManagerSettings;
import org.apache.aurora.scheduler.events.PubsubEventModule;
import org.apache.aurora.scheduler.filter.SchedulingFilterImpl;
@@ -62,75 +63,90 @@ import static java.util.Objects.requireNonNull;
* Binding module for the aurora scheduler application.
*/
public class AppModule extends AbstractModule {
- private static final int DEFAULT_MAX_TASKS_PER_JOB = 4000;
- @Positive
- @CmdLine(name = "max_tasks_per_job", help = "Maximum number of allowed tasks in a single job.")
- public static final Arg<Integer> MAX_TASKS_PER_JOB = Arg.create(DEFAULT_MAX_TASKS_PER_JOB);
-
- private static final int DEFAULT_MAX_UPDATE_INSTANCE_FAILURES = DEFAULT_MAX_TASKS_PER_JOB * 5;
-
- @Positive
- @CmdLine(name = "max_update_instance_failures", help = "Upper limit on the number of "
- + "failures allowed during a job update. This helps cap potentially unbounded entries into "
- + "storage.")
- public static final Arg<Integer> MAX_UPDATE_INSTANCE_FAILURES = Arg.create(
- DEFAULT_MAX_UPDATE_INSTANCE_FAILURES);
-
- @CmdLine(name = "allowed_container_types",
- help = "Container types that are allowed to be used by jobs.")
- private static final Arg<Set<_Fields>> ALLOWED_CONTAINER_TYPES =
- Arg.create(ImmutableSet.of(Container._Fields.MESOS));
-
- @CmdLine(name = "allow_docker_parameters",
- help = "Allow to pass docker container parameters in the job.")
- private static final Arg<Boolean> ENABLE_DOCKER_PARAMETERS = Arg.create(false);
-
- @CmdLine(name = "default_docker_parameters",
- help = "Default docker parameters for any job that does not explicitly declare parameters.")
- private static final Arg<Multimap<String, String>> DEFAULT_DOCKER_PARAMETERS =
- Arg.create(ImmutableMultimap.of());
-
- @CmdLine(name = "require_docker_use_executor",
- help = "If false, Docker tasks may run without an executor (EXPERIMENTAL)")
- private static final Arg<Boolean> REQUIRE_DOCKER_USE_EXECUTOR = Arg.create(true);
-
- @CmdLine(name = "enable_mesos_fetcher", help = "Allow jobs to pass URIs "
- + "to the Mesos Fetcher. Note that enabling this feature could pose "
- + "a privilege escalation threat.")
- private static final Arg<Boolean> ENABLE_MESOS_FETCHER = Arg.create(false);
-
- @CmdLine(name = "allow_container_volumes",
- help = "Allow passing in volumes in the job. Enabling this could pose a privilege "
- + "escalation threat.")
- private static final Arg<Boolean> ALLOW_CONTAINER_VOLUMES = Arg.create(false);
+ @Parameters(separators = "=")
+ public static class Options {
+ @Parameter(names = "-max_tasks_per_job",
+ validateValueWith = PositiveNumber.class,
+ description = "Maximum number of allowed tasks in a single job.")
+ public int maxTasksPerJob = 4000;
+
+ @Parameter(names = "-max_update_instance_failures",
+ validateValueWith = PositiveNumber.class,
+ description = "Upper limit on the number of "
+ + "failures allowed during a job update. This helps cap potentially unbounded entries"
+ + " into storage.")
+ public int maxUpdateInstanceFailures = maxTasksPerJob * 5;
+
+ // TODO(wfarner): From jcommander docs - "Also, note that only List<String> is allowed for
+ // parameters that define an arity. You will have to convert these values yourself..."
+
+ @Parameter(names = "-allowed_container_types",
+ description = "Container types that are allowed to be used by jobs.")
+ public List<_Fields> allowedContainerTypes = ImmutableList.of(Container._Fields.MESOS);
+
+ @Parameter(names = "-allow_docker_parameters",
+ description = "Allow to pass docker container parameters in the job.",
+ arity = 1)
+ public boolean enableDockerParameters = false;
+
+ @Parameter(names = "-default_docker_parameters",
+ description =
+ "Default docker parameters for any job that does not explicitly declare parameters.")
+ public List<DockerParameter> defaultDockerParameters = ImmutableList.of();
+
+ @Parameter(names = "-require_docker_use_executor",
+ description = "If false, Docker tasks may run without an executor (EXPERIMENTAL)",
+ arity = 1)
+ public boolean requireDockerUseExecutor = true;
+
+ @Parameter(names = "-enable_mesos_fetcher", description = "Allow jobs to pass URIs "
+ + "to the Mesos Fetcher. Note that enabling this feature could pose "
+ + "a privilege escalation threat.",
+ arity = 1)
+ public boolean enableMesosFetcher = false;
+
+ @Parameter(names = "-allow_container_volumes",
+ description = "Allow passing in volumes in the job. Enabling this could pose a privilege "
+ + "escalation threat.",
+ arity = 1)
+ public boolean allowContainerVolumes = false;
+ }
private final ConfigurationManagerSettings configurationManagerSettings;
private final DriverKind kind;
+ private final CliOptions options;
@VisibleForTesting
- public AppModule(ConfigurationManagerSettings configurationManagerSettings, DriverKind kind) {
+ public AppModule(
+ ConfigurationManagerSettings configurationManagerSettings,
+ DriverKind kind,
+ CliOptions options) {
this.configurationManagerSettings = requireNonNull(configurationManagerSettings);
this.kind = kind;
+ this.options = options;
}
- public AppModule(boolean allowGpuResource, DriverKind kind) {
+ public AppModule(CliOptions opts) {
this(new ConfigurationManagerSettings(
- ImmutableSet.copyOf(ALLOWED_CONTAINER_TYPES.get()),
- ENABLE_DOCKER_PARAMETERS.get(),
- DEFAULT_DOCKER_PARAMETERS.get(),
- REQUIRE_DOCKER_USE_EXECUTOR.get(),
- allowGpuResource,
- ENABLE_MESOS_FETCHER.get(),
- ALLOW_CONTAINER_VOLUMES.get()),
- kind);
+ ImmutableSet.copyOf(opts.app.allowedContainerTypes),
+ opts.app.enableDockerParameters,
+ opts.app.defaultDockerParameters,
+ opts.app.requireDockerUseExecutor,
+ opts.main.allowGpuResource,
+ opts.app.enableMesosFetcher,
+ opts.app.allowContainerVolumes),
+ opts.main.driverImpl,
+ opts);
}
@Override
protected void configure() {
bind(ConfigurationManagerSettings.class).toInstance(configurationManagerSettings);
bind(Thresholds.class)
- .toInstance(new Thresholds(MAX_TASKS_PER_JOB.get(), MAX_UPDATE_INSTANCE_FAILURES.get()));
+ .toInstance(
+ new Thresholds(options.app.maxTasksPerJob,
+ options.app.maxUpdateInstanceFailures));
// Enable intercepted method timings and context classloader repair.
TimedInterceptor.bind(binder());
@@ -143,22 +159,22 @@ public class AppModule extends AbstractModule {
PubsubEventModule.bindSchedulingFilterDelegate(binder()).to(SchedulingFilterImpl.class);
bind(SchedulingFilterImpl.class).in(Singleton.class);
- install(new AsyncModule());
- install(new OffersModule());
- install(new PruningModule());
- install(new ReconciliationModule());
- install(new SchedulingModule());
- install(new AsyncStatsModule());
+ install(new AsyncModule(options.async));
+ install(new OffersModule(options));
+ install(new PruningModule(options.pruning));
+ install(new ReconciliationModule(options.reconciliation));
+ install(new SchedulingModule(options.scheduling));
+ install(new AsyncStatsModule(options.asyncStats));
install(new MetadataModule());
install(new QuotaModule());
- install(new JettyServerModule());
- install(new PreemptorModule());
+ install(new JettyServerModule(options));
+ install(new PreemptorModule(options));
install(new SchedulerDriverModule(kind));
install(new SchedulerServicesModule());
- install(new SchedulerModule());
- install(new StateModule());
- install(new SlaModule());
- install(new UpdaterModule());
+ install(new SchedulerModule(options.scheduler));
+ install(new StateModule(options));
+ install(new SlaModule(options.sla));
+ install(new UpdaterModule(options.updater));
bind(StatsProvider.class).toInstance(Stats.STATS_PROVIDER);
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/main/java/org/apache/aurora/scheduler/app/MoreModules.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/app/MoreModules.java b/src/main/java/org/apache/aurora/scheduler/app/MoreModules.java
index 074f220..bf0ed92 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/MoreModules.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/MoreModules.java
@@ -13,9 +13,16 @@
*/
package org.apache.aurora.scheduler.app;
-import com.google.inject.AbstractModule;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.FluentIterable;
import com.google.inject.Module;
+import org.apache.aurora.scheduler.config.CliOptions;
+
/**
* A utility class for managing guice modules.
*/
@@ -24,13 +31,36 @@ public final class MoreModules {
// Utility class
}
- private static Module instantiateModule(final Class<? extends Module> moduleClass) {
+ /**
+ * Instantiate a module, supplying command line options if accepted by the module class.
+ * <p>
+ * Reflectively instantiates a module, first invoking a constructor that accepts
+ * {@link CliOptions} as the only parameter, falling back to a default constructor if options are
+ * not accepted by the class.
+ *
+ * @param moduleClass Module to instantiate
+ * @param options Options to provide the module.
+ * @return An instance of the module class.
+ */
+ public static Module instantiate(Class<?> moduleClass, CliOptions options) {
try {
- return moduleClass.newInstance();
+ // If it exists, use the constructor accepting CliOptions.
+ try {
+ Constructor<?> constructor = moduleClass.getConstructor(CliOptions.class);
+ return (Module) constructor.newInstance(options);
+ } catch (NoSuchMethodException e) {
+ // Fall back to default constructor.
+ return (Module) moduleClass.newInstance();
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException(
+ String.format("Failed to invoke %s(CliOption)", moduleClass.getName()),
+ e);
+ }
} catch (InstantiationException e) {
throw new IllegalArgumentException(
String.format(
- "Failed to instantiate module %s. Are you sure it has a no-arg constructor?",
+ "Failed to instantiate module %s."
+ + "Dynamic modules must have a default constructor or accept CliOptions",
moduleClass.getName()),
e);
} catch (IllegalAccessException e) {
@@ -42,32 +72,11 @@ public final class MoreModules {
}
}
- static Module getModule(Class<? extends Module> moduleClass) {
- return instantiateModule(moduleClass);
- }
-
/**
- * Creates a module that will lazily instantiate and install another module.
- * <p/>
- * This serves as an indirection between module procurement and installation, which is necessary
- * in cases where a module is referenced within a static initializer. In this scenario, a module
- * must not be instantiated if it reads command line arguments, as the args system has not yet
- * had a chance to populate them.
- *
- * @param moduleClass Module to install.
- * @return An installer that will install {@code moduleClass}.
+ * Identical to {@link #instantiate(Class, CliOptions)} for multiple module classes.
*/
- public static Module lazilyInstantiated(final Class<? extends Module> moduleClass) {
- return new AbstractModule() {
- @Override
- protected void configure() {
- install(getModule(moduleClass));
- }
-
- @Override
- public String toString() {
- return moduleClass.toString();
- }
- };
+ @SuppressWarnings("rawtypes")
+ public static Set<Module> instantiateAll(List<Class> moduleClasses, CliOptions options) {
+ return FluentIterable.from(moduleClasses).transform(c -> instantiate(c, options)).toSet();
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/519e3df7/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
index bb7055e..dd0e480 100644
--- a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
+++ b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java
@@ -14,7 +14,6 @@
package org.apache.aurora.scheduler.app;
import java.net.InetSocketAddress;
-import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -22,6 +21,8 @@ import java.util.concurrent.atomic.AtomicLong;
import javax.inject.Inject;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -31,17 +32,12 @@ import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
+import com.google.inject.ProvisionException;
import com.google.inject.spi.Message;
import com.google.inject.util.Modules;
import org.apache.aurora.GuavaUtils.ServiceManagerIface;
import org.apache.aurora.common.application.Lifecycle;
-import org.apache.aurora.common.args.Arg;
-import org.apache.aurora.common.args.ArgScanner;
-import org.apache.aurora.common.args.ArgScanner.ArgScanException;
-import org.apache.aurora.common.args.CmdLine;
-import org.apache.aurora.common.args.constraints.NotEmpty;
-import org.apache.aurora.common.args.constraints.NotNull;
import org.apache.aurora.common.inject.Bindings;
import org.apache.aurora.common.stats.Stats;
import org.apache.aurora.common.zookeeper.SingletonService;
@@ -50,6 +46,9 @@ import org.apache.aurora.gen.ServerInfo;
import org.apache.aurora.scheduler.AppStartup;
import org.apache.aurora.scheduler.SchedulerLifecycle;
import org.apache.aurora.scheduler.TierModule;
+import org.apache.aurora.scheduler.config.CliOptions;
+import org.apache.aurora.scheduler.config.CommandLine;
+import org.apache.aurora.scheduler.config.validators.NotEmptyString;
import org.apache.aurora.scheduler.configuration.executor.ExecutorModule;
import org.apache.aurora.scheduler.cron.quartz.CronModule;
import org.apache.aurora.scheduler.discovery.FlaggedZooKeeperConfig;
@@ -76,51 +75,65 @@ import org.slf4j.LoggerFactory;
public class SchedulerMain {
private static final Logger LOG = LoggerFactory.getLogger(SchedulerMain.class);
- @NotNull
- @CmdLine(name = "cluster_name", help = "Name to identify the cluster being served.")
- private static final Arg<String> CLUSTER_NAME = Arg.create();
+ @Parameters(separators = "=")
+ public static class Options {
+ @Parameter(names = "-cluster_name",
+ required = true,
+ description = "Name to identify the cluster being served.")
+ public String clusterName;
- @NotNull
- @NotEmpty
- @CmdLine(name = "serverset_path", help = "ZooKeeper ServerSet path to register at.")
- private static final Arg<String> SERVERSET_PATH = Arg.create();
+ @Parameter(
+ names = "-serverset_path",
+ required = true,
+ validateValueWith = NotEmptyString.class,
+ description = "ZooKeeper ServerSet path to register at.")
+ public String serversetPath;
- // TODO(zmanji): Consider making this an enum of HTTP or HTTPS.
- @CmdLine(name = "serverset_endpoint_name",
- help = "Name of the scheduler endpoint published in ZooKeeper.")
- private static final Arg<String> SERVERSET_ENDPOINT_NAME = Arg.create("http");
+ // TODO(zmanji): Consider making this an enum of HTTP or HTTPS.
+ @Parameter(names = "-serverset_endpoint_name",
+ description = "Name of the scheduler endpoint published in ZooKeeper.")
+ public String serversetEndpointName = "http";
- // TODO(Suman Karumuri): Rename viz_job_url_prefix to stats_job_url_prefix for consistency.
- @CmdLine(name = "viz_job_url_prefix", help = "URL prefix for job container stats.")
- private static final Arg<String> STATS_URL_PREFIX = Arg.create("");
+ // TODO(Suman Karumuri): Rename viz_job_url_prefix to stats_job_url_prefix for consistency.
+ @Parameter(names = "-viz_job_url_prefix", description = "URL prefix for job container stats.")
+ public String statsUrlPrefix = "";
- @CmdLine(name = "allow_gpu_resource", help = "Allow jobs to request Mesos GPU resource.")
- private static final Arg<Boolean> ALLOW_GPU_RESOURCE = Arg.create(false);
+ @Parameter(names = "-allow_gpu_resource",
+ description = "Allow jobs to request Mesos GPU resource.",
+ arity = 1)
+ public boolean allowGpuResource = false;
- public enum DriverKind {
- // TODO(zmanji): Remove this option once V0_DRIVER has been proven out in production.
- // This is the original driver that libmesos shipped with. Uses unversioned protobufs, and has
- // minimal backwards compatability guarantees.
- SCHEDULER_DRIVER,
- // These are the new drivers that libmesos ships with. They use versioned (V1) protobufs for
- // the Java API.
- // V0 Driver offers the V1 API over the old Scheduler Driver. It does not fully support
- // the V1 API (ie mesos maintenance).
- V0_DRIVER,
- // V1 Driver offers the V1 API over a full HTTP API implementation. It allows for maintenance
- // primatives and other new features.
- V1_DRIVER,
- }
+ public enum DriverKind {
+ // TODO(zmanji): Remove this option once V0_DRIVER has been proven out in production.
+ // This is the original driver that libmesos shipped with. Uses unversioned protobufs, and has
+ // minimal backwards compatability guarantees.
+ SCHEDULER_DRIVER,
+ // These are the new drivers that libmesos ships with. They use versioned (V1) protobufs for
+ // the Java API.
+ // V0 Driver offers the V1 API over the old Scheduler Driver. It does not fully support
+ // the V1 API (ie mesos maintenance).
+ V0_DRIVER,
+ // V1 Driver offers the V1 API over a full HTTP API implementation. It allows for maintenance
+ // primatives and other new features.
+ V1_DRIVER,
+ }
- @CmdLine(name = "mesos_driver", help = "Which Mesos Driver to use")
- private static final Arg<DriverKind> DRIVER_IMPL = Arg.create(DriverKind.SCHEDULER_DRIVER);
+ @Parameter(names = "-mesos_driver", description = "Which Mesos Driver to use")
+ public DriverKind driverImpl = DriverKind.SCHEDULER_DRIVER;
+ }
public static class ProtocolModule extends AbstractModule {
+ private final Options options;
+
+ public ProtocolModule(Options options) {
+ this.options = options;
+ }
+
@Override
protected void configure() {
bind(String.class)
.annotatedWith(SchedulerProtocol.class)
- .toInstance(SERVERSET_ENDPOINT_NAME.get());
+ .toInstance(options.serversetEndpointName);
}
}
@@ -142,7 +155,7 @@ public class SchedulerMain {
appLifecycle.shutdown();
}
- void run() {
+ void run(Options options) {
try {
startupServices.startAsync();
Runtime.getRuntime().addShutdownHook(new Thread(SchedulerMain.this::stop, "ShutdownHook"));
@@ -156,7 +169,7 @@ public class SchedulerMain {
schedulerService.lead(
httpSocketAddress,
- ImmutableMap.of(SERVERSET_ENDPOINT_NAME.get(), httpSocketAddress),
+ ImmutableMap.of(options.serversetEndpointName, httpSocketAddress),
leaderListener);
} catch (SingletonService.LeadException e) {
throw new IllegalStateException("Failed to lead service.", e);
@@ -169,16 +182,16 @@ public class SchedulerMain {
}
@VisibleForTesting
- static Module getUniversalModule() {
+ static Module getUniversalModule(CliOptions options) {
return Modules.combine(
- new ProtocolModule(),
+ new ProtocolModule(options.main),
new LifecycleModule(),
- new StatsModule(),
- new AppModule(ALLOW_GPU_RESOURCE.get(), DRIVER_IMPL.get()),
- new CronModule(),
+ new StatsModule(options.stats),
+ new AppModule(options),
+ new CronModule(options.cron),
new DbModule.MigrationManagerModule(),
- DbModule.productionModule(Bindings.annotatedKeyFactory(Storage.Volatile.class)),
- new DbModule.GarbageCollectorModule());
+ DbModule.productionModule(Bindings.annotatedKeyFactory(Storage.Volatile.class), options.db),
+ new DbModule.GarbageCollectorModule(options.db));
}
/**
@@ -188,7 +201,7 @@ public class SchedulerMain {
* @param appEnvironmentModule Additional modules based on the execution environment.
*/
@VisibleForTesting
- public static void flagConfiguredMain(Module appEnvironmentModule) {
+ public static void flagConfiguredMain(CliOptions options, Module appEnvironmentModule) {
AtomicLong uncaughtExceptions = Stats.exportLong("uncaught_exceptions");
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
uncaughtExceptions.incrementAndGet();
@@ -207,6 +220,12 @@ public class SchedulerMain {
LOG.error(" source: " + m.getSource());
}
}
+ } else if (e instanceof ProvisionException) {
+ // More special handling for guice 3 + java 8. Remove this once using guice >=4.0.
+ ProvisionException pe = (ProvisionException) e;
+ for (Message message : pe.getErrorMessages()) {
+ LOG.error(message.getMessage());
+ }
} else {
LOG.error("Uncaught exception from " + t + ":" + e, e);
}
@@ -214,18 +233,21 @@ public class SchedulerMain {
Module module = Modules.combine(
appEnvironmentModule,
- getUniversalModule(),
- new ServiceDiscoveryModule(FlaggedZooKeeperConfig.create(), SERVERSET_PATH.get()),
- new BackupModule(SnapshotStoreImpl.class),
- new ExecutorModule(),
+ getUniversalModule(options),
+ new ServiceDiscoveryModule(
+ FlaggedZooKeeperConfig.create(options.zk),
+ options.main.serversetPath),
+ new BackupModule(options.backup, SnapshotStoreImpl.class),
+ new ExecutorModule(options.executor),
new AbstractModule() {
@Override
protected void configure() {
+ bind(CliOptions.class).toInstance(options);
bind(IServerInfo.class).toInstance(
IServerInfo.build(
new ServerInfo()
- .setClusterName(CLUSTER_NAME.get())
- .setStatsUrlPrefix(STATS_URL_PREFIX.get())));
+ .setClusterName(options.main.clusterName)
+ .setStatsUrlPrefix(options.main.statsUrlPrefix)));
}
});
@@ -236,7 +258,7 @@ public class SchedulerMain {
SchedulerMain scheduler = new SchedulerMain();
injector.injectMembers(scheduler);
try {
- scheduler.run();
+ scheduler.run(options.main);
} finally {
LOG.info("Application run() exited.");
}
@@ -248,42 +270,18 @@ public class SchedulerMain {
}
public static void main(String... args) {
- applyStaticArgumentValues(args);
+ CliOptions options = CommandLine.parseOptions(args);
List<Module> modules = ImmutableList.<Module>builder()
.add(
- new CommandLineDriverSettingsModule(ALLOW_GPU_RESOURCE.get()),
- new LibMesosLoadingModule(DRIVER_IMPL.get()),
- new MesosLogStreamModule(FlaggedZooKeeperConfig.create()),
- new LogStorageModule(),
- new TierModule(),
- new WebhookModule()
+ new CommandLineDriverSettingsModule(options.driver, options.main.allowGpuResource),
+ new LibMesosLoadingModule(options.main.driverImpl),
+ new MesosLogStreamModule(options.mesosLog, FlaggedZooKeeperConfig.create(options.zk)),
+ new LogStorageModule(options.logStorage, options.db.useDbTaskStore),
+ new TierModule(options.tiers),
+ new WebhookModule(options.webhook)
)
.build();
- flagConfiguredMain(Modules.combine(modules));
- }
-
- private static void exit(String message, Exception error) {
- LOG.error(message + "\n" + error, error);
- System.exit(1);
- }
-
- /**
- * Applies {@link CmdLine} arg values throughout the classpath. This must be invoked before
- * attempting to read any argument values in the system.
- *
- * @param args Command line arguments.
- */
- @VisibleForTesting
- public static void applyStaticArgumentValues(String... args) {
- try {
- if (!new ArgScanner().parse(Arrays.asList(args))) {
- System.exit(0);
- }
- } catch (ArgScanException e) {
- exit("Failed to scan arguments", e);
- } catch (IllegalArgumentException e) {
- exit("Failed to apply arguments", e);
- }
+ flagConfiguredMain(options, Modules.combine(modules));
}
}