diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 0311da4f42b9..d55c7fdd91aa 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -8,11 +8,19 @@ JAVA_OPTS=${JAVA_OPTS:-"-Xmx1024M -DloggerPath=conf/log4j.properties"} cli="${GEN_DIR}/modules/openapi-generator-cli" codegen="${cli}/target/openapi-generator-cli.jar" -cmdsrc="${cli}/src/main/java/org/openapitools/codegen/cmd" -pattern="@Command(name = \"$1\"" -if expr "x$1" : 'x[a-z][a-z-]*$' > /dev/null && fgrep -qe "$pattern" "$cmdsrc"/*.java || expr "$1" = 'help' > /dev/null; then - # If ${GEN_DIR} has been mapped elsewhere from default, and that location has not been built +# We code in a list of commands here as source processing is potentially buggy (requires undocumented conventional use of annotations). +# A list of known commands helps us determine if we should compile CLI. There's an edge-case where a new command not added to this +# list won't be considered a "real" command. We can get around that a bit by checking CLI completions beforehand if it exists. +commands="list,generate,meta,langs,help,config-help,validate,version" + +# if CLI jar exists, check $1 against completions available in the CLI +if [[ -f "${codegen}" && -n "$(java ${JAVA_OPTS} -jar "${codegen}" completion | grep "^$1\$" )" ]]; then + command=$1 + shift + exec java ${JAVA_OPTS} -jar "${codegen}" "${command}" "$@" +elif [[ -n "$(echo commands | tr ',' '\n' | grep "^$1\$" )" ]]; then + # If CLI jar does not exist, and $1 is a known CLI command, build the CLI jar and run that command. if [[ ! -f "${codegen}" ]]; then (cd "${GEN_DIR}" && exec mvn -am -pl "modules/openapi-generator-cli" -Duser.home=$(dirname $MAVEN_CONFIG) package) fi @@ -20,5 +28,6 @@ if expr "x$1" : 'x[a-z][a-z-]*$' > /dev/null && fgrep -qe "$pattern" "$cmdsrc"/* shift exec java ${JAVA_OPTS} -jar "${codegen}" "${command}" "$@" else + # Pass args as linux commands. This allows us to do something like: docker run -it (-e…, -v…) image ls -la exec "$@" fi diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/OpenAPIGenerator.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/OpenAPIGenerator.java index 85b6379857fe..105320166095 100644 --- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/OpenAPIGenerator.java +++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/OpenAPIGenerator.java @@ -23,8 +23,6 @@ import io.airlift.airline.ParseOptionMissingValueException; import org.openapitools.codegen.cmd.*; -import java.util.Arrays; - /** * User: lanwen Date: 24.03.15 Time: 17:56 *
@@ -52,21 +50,23 @@ public static void main(String[] args) {
Help.class,
ConfigHelp.class,
Validate.class,
- Version.class
+ Version.class,
+ CompletionCommand.class
);
- // If CLI is run without a command, consider this an error.
- // We can check against empty args because unrecognized arguments/commands result in an exception.
- // This is useful to exit with status 1, for example, so that misconfigured scripts fail fast.
- // We don't want the default command to exit internally with status 1 because when the default command is something like "list",
- // it would prevent scripting using the command directly. Example:
- // java -jar cli.jar list --short | tr ',' '\n' | xargs -I{} echo "Doing something with {}"
- if (args.length == 0) {
- System.exit(1);
- }
-
try {
builder.build().parse(args).run();
+
+ // If CLI is run without a command, consider this an error. This exists after initial parse/run
+ // so we can present the configured "default command".
+ // We can check against empty args because unrecognized arguments/commands result in an exception.
+ // This is useful to exit with status 1, for example, so that misconfigured scripts fail fast.
+ // We don't want the default command to exit internally with status 1 because when the default command is something like "list",
+ // it would prevent scripting using the command directly. Example:
+ // java -jar cli.jar list --short | tr ',' '\n' | xargs -I{} echo "Doing something with {}"
+ if (args.length == 0) {
+ System.exit(1);
+ }
} catch (ParseOptionMissingException | ParseOptionMissingValueException e) {
System.err.printf("[error] %s%n", e.getMessage());
System.exit(1);
diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/CompletionCommand.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/CompletionCommand.java
new file mode 100644
index 000000000000..4116fe5c1d69
--- /dev/null
+++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/CompletionCommand.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 the original author or authors.
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ *
+ * 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.
+ */
+/*
+ * NOTICE: File originally taken from:
+ * https://github.com/airlift/airline/blob/fc7a55e34b6361cb97235de5a1b21cba9b508f4b/src/main/java/io/airlift/airline/SuggestCommand.java#L1
+ * Modifications have been made to fit the needs of OpenAPI Tools CLI.
+ */
+package org.openapitools.codegen.cmd;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import io.airlift.airline.*;
+import io.airlift.airline.model.*;
+
+import javax.inject.Inject;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static io.airlift.airline.ParserUtil.createInstance;
+
+@Command(name = "completion", description = "Complete commands (for using in tooling such as Bash Completions).", hidden = true)
+public class CompletionCommand
+ implements Runnable, Callable