This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 7aa849dd04ea7e2a3293965a6ed0e8ab97727e6c Author: Alex Heneveld <[email protected]> AuthorDate: Thu Sep 14 16:31:50 2023 +0100 better handling for quotes when passing container args; also support list --- .../tasks/kubectl/ContainerWorkflowStep.java | 21 +++++++++++++++++---- .../brooklyn/util/text/QuotedStringTokenizer.java | 2 +- .../util/text/QuotedStringTokenizerTest.java | 10 ++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/software/base/src/main/java/org/apache/brooklyn/tasks/kubectl/ContainerWorkflowStep.java b/software/base/src/main/java/org/apache/brooklyn/tasks/kubectl/ContainerWorkflowStep.java index 5ff670d8d0..1d5938f4ab 100644 --- a/software/base/src/main/java/org/apache/brooklyn/tasks/kubectl/ContainerWorkflowStep.java +++ b/software/base/src/main/java/org/apache/brooklyn/tasks/kubectl/ContainerWorkflowStep.java @@ -30,10 +30,12 @@ import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer; import org.apache.brooklyn.util.core.predicates.DslPredicates; import org.apache.brooklyn.util.core.task.DynamicTasks; +import org.apache.brooklyn.util.javalang.Boxing; import org.apache.brooklyn.util.text.QuotedStringTokenizer; import org.apache.brooklyn.util.text.Strings; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -45,7 +47,7 @@ public class ContainerWorkflowStep extends WorkflowStepDefinition { public static final ConfigKey<String> IMAGE = ConfigKeys.newStringConfigKey("image"); public static final ConfigKey<String> COMMAND = ConfigKeys.newStringConfigKey("command"); - public static final ConfigKey<String> ARGS = ConfigKeys.newStringConfigKey("args"); + public static final ConfigKey<Object> ARGS = ConfigKeys.newConfigKey(Object.class, "args", "Arguments as a string, split into words respecting quoted phrases, or as a list of strings"); public static final ConfigKey<List<String>> COMMANDS = ConfigKeys.newConfigKey(new TypeToken<List<String>>() {}, "commands"); public static final ConfigKey<List<String>> RAW_COMMAND = ConfigKeys.newConfigKey(new TypeToken<List<String>>() {}, "raw_command"); public static final ConfigKey<PullPolicy> PULL_POLICY = ConfigKeys.newConfigKey(PullPolicy.class, "pull_policy", ContainerCommons.CONTAINER_IMAGE_PULL_POLICY.getDescription(), ContainerCommons.CONTAINER_IMAGE_PULL_POLICY.getDefaultValue()); @@ -94,9 +96,20 @@ public class ContainerWorkflowStep extends WorkflowStepDefinition { throw new IllegalStateException("Incompatible command specification, max 1, received: "+commandTypesSet); } - String args = context.getInput(ARGS); - if (Strings.isNonBlank(args)) { - tf.arguments(new QuotedStringTokenizer(args).remainderAsList()); + Object args = context.getInput(ARGS); + if (args instanceof String && Strings.isNonBlank((String)args)) { + // unquote things here since we convert it to a list + tf.arguments(QuotedStringTokenizer.builder().includeQuotes(false).keepInternalQuotes(true).buildList((String)args)); + } else if (args instanceof Collection) { + List<String> result = MutableList.of(); + ((Collection)args).forEach(x -> { + if (x instanceof String) result.add((String)x); + else if (Boxing.isPrimitiveOrBoxedObject(x)) result.add(x.toString()); + else throw new IllegalArgumentException("Argument '"+x+"' not supported; should be a string"); + }); + tf.arguments(result); + } else if (args!=null) { + throw new IllegalArgumentException("args must be a string or a list"); } Map<String, Object> env = context.getInput(ENV); diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/QuotedStringTokenizer.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/QuotedStringTokenizer.java index dbd1d928e4..9fe05eff38 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/text/QuotedStringTokenizer.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/QuotedStringTokenizer.java @@ -93,7 +93,7 @@ public class QuotedStringTokenizer { return new QuotedStringTokenizer(stringToTokenize, quoteChars, includeQuotes, delimiterChars, includeDelimiters, expectQuotesDelimited, failOnOpenQuote); } public List<String> buildList(String stringToTokenize) { - return new QuotedStringTokenizer(stringToTokenize, quoteChars, includeQuotes, delimiterChars, includeDelimiters, expectQuotesDelimited, failOnOpenQuote).remainderAsList(); + return build(stringToTokenize).remainderAsList(); } public Builder quoteChars(String quoteChars) { this.quoteChars = quoteChars; return this; } diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/text/QuotedStringTokenizerTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/text/QuotedStringTokenizerTest.java index 3f1230a6a9..241b2add61 100644 --- a/utils/common/src/test/java/org/apache/brooklyn/util/text/QuotedStringTokenizerTest.java +++ b/utils/common/src/test/java/org/apache/brooklyn/util/text/QuotedStringTokenizerTest.java @@ -204,4 +204,14 @@ public class QuotedStringTokenizerTest { // note: backslashed escapes are not handled at present; ideally it would give us back this: //MutableList.of("This", "is", "a", "test\\ of", "spaces", "and", "\"some in quotes\"", "too")); } + + @Test + public void testForArgsList() throws Exception { + // per above, ideally note: backslashed escapes are not handled at present; ideally it would give us back this: + Asserts.assertEquals(new QuotedStringTokenizer("test \"quoted phrases\" and [\"embedded_quotes\"]", false).remainderAsList(), + MutableList.of("test", "quoted phrases", "and", "[embedded_quotes]")); + // above is the same as includeQuotes below; but for args lists we will usually want to keepInternalQuotes + Asserts.assertEquals(QuotedStringTokenizer.builder().includeQuotes(false).keepInternalQuotes(true).buildList("test \"quoted phrases\" and [\"embedded_quotes\"]"), + MutableList.of("test", "quoted phrases", "and", "[\"embedded_quotes\"]")); + } }
