diff --git a/gdk/buildSrc/src/main/groovy/gdk-cli.gradle b/gdk/buildSrc/src/main/groovy/gdk-cli.gradle
new file mode 100644
index 0000000..e0235ea
--- /dev/null
+++ b/gdk/buildSrc/src/main/groovy/gdk-cli.gradle
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2024 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id 'gdk-module'
+ id 'io.micronaut.application'
+ id 'com.github.johnrengelman.shadow'
+}
+
+dependencies {
+ annotationProcessor mnLibs.picocli.codegen
+
+ compileOnly mnLibs.graal
+
+ implementation projects.gdkCliCore
+
+ runtimeOnly libs.bouncycastle.bcpkix
+ runtimeOnly libs.bouncycastle.bcprov
+ runtimeOnly libs.jansi
+ runtimeOnly libs.jline
+ runtimeOnly libs.slf4j.nop
+}
+
+configurations.configureEach {
+ exclude module: 'logback-classic'
+}
+
+micronaut {
+ version libs.micronaut.starter.api.get().version
+ processing {
+ incremental true
+ annotations 'cloud.graal.gdk.*'
+ }
+}
+
+tasks.named('shadowJar') {
+ mergeServiceFiles()
+}
+
+tasks.named('shadowDistZip') {
+ enabled = false
+}
+tasks.named('shadowDistTar') {
+ enabled = false
+}
+
+tasks.register('copyShadowJar', Sync) {
+ from shadowJar.outputs
+ into "${project.rootProject.buildDir}/libs"
+ rename { String fileName -> 'cli.jar' }
+}
diff --git a/gdk/buildSrc/src/main/groovy/gdk-module-public.gradle b/gdk/buildSrc/src/main/groovy/gdk-module-public.gradle
new file mode 100644
index 0000000..a672a30
--- /dev/null
+++ b/gdk/buildSrc/src/main/groovy/gdk-module-public.gradle
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2024 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id 'gdk-module'
+ id 'com.diffplug.spotless'
+}
+
+spotless {
+ java {
+ licenseHeaderFile rootProject.file('config/spotless.license.java')
+ target 'src/main/java/**'
+ targetExclude '**/*.rocker.raw', '**/GdkBaseCommand.java', '**/GdkStarter.java', '**/AbstractStarter.java'
+ }
+ format 'javaMisc', {
+ target 'src/main/**/package-info.java', 'src/main/**/module-info.java'
+ licenseHeaderFile rootProject.file('config/spotless.license.java'), '\\/\\*\\*'
+ }
+}
+
diff --git a/gdk/buildSrc/src/main/groovy/gdk-module.gradle b/gdk/buildSrc/src/main/groovy/gdk-module.gradle
index 4146a44..63f77bf 100644
--- a/gdk/buildSrc/src/main/groovy/gdk-module.gradle
+++ b/gdk/buildSrc/src/main/groovy/gdk-module.gradle
@@ -17,19 +17,6 @@
plugins {
id 'gdk-base'
id 'checkstyle'
- id 'com.diffplug.spotless'
-}
-
-spotless {
- java {
- licenseHeaderFile rootProject.file('config/spotless.license.java')
- target 'src/main/java/**'
- targetExclude '**/*.rocker.raw', '**/GdkBaseCommand.java', '**/GdkStarter.java'
- }
- format 'javaMisc', {
- target 'src/main/**/package-info.java', 'src/main/**/module-info.java'
- licenseHeaderFile rootProject.file('config/spotless.license.java'), '\\/\\*\\*'
- }
}
publishing {
diff --git a/gdk/buildSrc/src/main/groovy/gdk-testing.gradle b/gdk/buildSrc/src/main/groovy/gdk-testing.gradle
new file mode 100644
index 0000000..1313487
--- /dev/null
+++ b/gdk/buildSrc/src/main/groovy/gdk-testing.gradle
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id 'groovy'
+ id 'com.adarshr.test-logger'
+ id 'io.micronaut.library'
+}
+
+micronaut {
+ testRuntime 'spock2'
+}
+
+test {
+ maxHeapSize = '16G'
+}
+
+testlogger {
+ theme 'standard-parallel'
+ showFullStackTraces true
+ showStandardStreams true
+ showPassedStandardStreams false
+ showSkippedStandardStreams false
+ showFailedStandardStreams true
+}
diff --git a/gdk/gdk-cli-core/README.adoc b/gdk/gdk-cli-core/README.adoc
new file mode 100644
index 0000000..7cf0732
--- /dev/null
+++ b/gdk/gdk-cli-core/README.adoc
@@ -0,0 +1,3 @@
+= gdk-cli-core
+
+This submodule is a reusable library contains most of the code for the CLI except for the main class and the build configuration to enable running the CLI.
diff --git a/gdk/gdk-cli-core/build.gradle b/gdk/gdk-cli-core/build.gradle
new file mode 100644
index 0000000..c273c48
--- /dev/null
+++ b/gdk/gdk-cli-core/build.gradle
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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.
+ */
+
+plugins {
+ id 'gdk-module-public'
+ id 'io.micronaut.library'
+}
+
+dependencies {
+ annotationProcessor mnLibs.picocli.codegen
+
+ // not in libs.versions.toml to keep Micronaut version in one place
+ api(libs.micronaut.starter.cli) {
+ exclude group: 'io.micronaut', module: 'micronaut-buffer-netty'
+ exclude group: 'io.micronaut', module: 'micronaut-http-client'
+ exclude group: 'io.micronaut', module: 'micronaut-http-client-core'
+ exclude group: 'io.micronaut', module: 'micronaut-http-netty'
+ exclude group: 'io.micronaut', module: 'micronaut-websocket'
+ exclude group: 'io.micronaut.testresources', module: 'micronaut-test-resources-build-tools'
+ exclude group: 'io.netty', module: 'netty-buffer'
+ exclude group: 'io.netty', module: 'netty-codec'
+ exclude group: 'io.netty', module: 'netty-codec-http'
+ exclude group: 'io.netty', module: 'netty-codec-http2'
+ exclude group: 'io.netty', module: 'netty-codec-socks'
+ exclude group: 'io.netty', module: 'netty-common'
+ exclude group: 'io.netty', module: 'netty-handler'
+ exclude group: 'io.netty', module: 'netty-handler-proxy'
+ exclude group: 'io.netty', module: 'netty-resolver'
+ exclude group: 'io.netty', module: 'netty-transport'
+ exclude group: 'io.swagger.core.v3', module: 'swagger-annotations'
+ exclude group: 'org.eclipse.jgit', module: 'org.eclipse.jgit'
+ exclude group: 'org.jline', module: 'jline'
+ }
+ api mnLibs.micronaut.picocli
+ api mnLibs.picocli
+ api mnLibs.micronaut.jackson.databind
+ api mnLibs.micronaut.validation
+ api projects.gdkCore
+}
+
+micronaut {
+ version libs.micronaut.starter.api.get().version
+ processing {
+ incremental true
+ annotations 'cloud.graal.gdk.*'
+ }
+}
diff --git a/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/AbstractStarter.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/AbstractStarter.java
new file mode 100644
index 0000000..5b39fb5
--- /dev/null
+++ b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/AbstractStarter.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017-2022 original authors
+ * Copyright 2024 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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 cloud.graal.gdk;
+
+import cloud.graal.gdk.command.GdkBaseCommand;
+import io.micronaut.context.ApplicationContext;
+import io.micronaut.context.BeanContext;
+import io.micronaut.inject.BeanDefinition;
+import io.micronaut.starter.cli.CodeGenConfig;
+import io.micronaut.starter.cli.InteractiveShell;
+import io.micronaut.starter.cli.MicronautFactory;
+import io.micronaut.starter.cli.command.CodeGenCommand;
+import io.micronaut.starter.io.ConsoleOutput;
+import picocli.CommandLine;
+import picocli.CommandLine.ParameterException;
+
+import java.util.function.BiFunction;
+
+/**
+ * Base class for CLI main classes. Starts an interactive shell if passed no
+ * arguments, otherwise instantiates the requested command class.
+ *
+ * Based on io.micronaut.starter.cli.MicronautStarter.
+ */
+public abstract class AbstractStarter extends GdkBaseCommand {
+
+ protected static final BiFunction EXCEPTION_HANDLER = (e, commandLine) -> {
+ GdkBaseCommand command = commandLine.getCommand();
+ command.err(e.getMessage());
+ if (command.showStacktrace()) {
+ e.printStackTrace(commandLine.getErr());
+ }
+ return 1;
+ };
+
+ protected boolean interactiveShell = false;
+
+ protected CommandLine createCommandLine() {
+ boolean noOpConsole = interactiveShell;
+ try (BeanContext beanContext = ApplicationContext.builder().deduceEnvironment(false).start()) {
+ return createCommandLine(beanContext, noOpConsole);
+ }
+ }
+
+ protected int execute(String[] args) {
+ boolean noOpConsole = args.length > 0 && args[0].startsWith("update-cli-config");
+ try (BeanContext beanContext = ApplicationContext.builder().deduceEnvironment(false).start()) {
+ return createCommandLine(beanContext, noOpConsole).execute(args);
+ }
+ }
+
+ protected CommandLine createCommandLine(BeanContext beanContext, boolean noOpConsole) {
+ CommandLine commandLine = new CommandLine(this, new MicronautFactory(beanContext));
+ commandLine.setExecutionExceptionHandler((ex, commandLine1, parseResult) -> EXCEPTION_HANDLER.apply(ex, commandLine1));
+ commandLine.setUsageHelpWidth(100);
+
+ addCodegenCommands(beanContext, noOpConsole, commandLine);
+
+ return commandLine;
+ }
+
+ protected void addCodegenCommands(BeanContext beanContext, boolean noOpConsole, CommandLine commandLine) {
+ CodeGenConfig codeGenConfig = CodeGenConfig.load(beanContext, noOpConsole ? ConsoleOutput.NOOP : this);
+ if (codeGenConfig != null) {
+ beanContext.getBeanDefinitions(CodeGenCommand.class).stream()
+ .map(BeanDefinition::getBeanType)
+ .map(bt -> beanContext.createBean(bt, codeGenConfig))
+ .filter(CodeGenCommand::applies)
+ .forEach(commandLine::addSubcommand);
+ }
+ }
+
+ /**
+ * @return the name of the cli, for use in the interactive shell.
+ */
+ protected String getCliName() {
+ return "gdk";
+ }
+
+ protected void startShell() {
+ CommandLine commandLine = createCommandLine();
+ interactiveShell = true;
+ new InteractiveShell(commandLine, this::execute, EXCEPTION_HANDLER, "@|blue " + getCliName() + ">|@ ").start();
+ }
+
+ @Override
+ public Integer call() {
+ throw new ParameterException(spec.commandLine(), "No command specified");
+ }
+}
diff --git a/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/AbstractExternalCommand.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/AbstractExternalCommand.java
new file mode 100644
index 0000000..9c5c344
--- /dev/null
+++ b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/AbstractExternalCommand.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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 cloud.graal.gdk.command;
+
+/**
+ * Convenience base class for external commands.
+ */
+public abstract class AbstractExternalCommand extends GdkBaseCommand implements ExternalCommand {
+}
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/CloudTypeConverter.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/CloudTypeConverter.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/CloudTypeConverter.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/CloudTypeConverter.java
diff --git a/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/ExternalCommand.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/ExternalCommand.java
new file mode 100644
index 0000000..6740553
--- /dev/null
+++ b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/ExternalCommand.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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 cloud.graal.gdk.command;
+
+/**
+ * Marker interface for addon commands, e.g. extensions created by users.
+ */
+public interface ExternalCommand {
+}
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkBaseCommand.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkBaseCommand.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkBaseCommand.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkBaseCommand.java
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCommonOptionsMixin.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCommonOptionsMixin.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCommonOptionsMixin.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCommonOptionsMixin.java
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateAppCommand.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateAppCommand.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateAppCommand.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateAppCommand.java
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateCommand.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateCommand.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateCommand.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateCommand.java
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateFunctionCommand.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateFunctionCommand.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateFunctionCommand.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateFunctionCommand.java
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateGatewayFunctionCommand.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateGatewayFunctionCommand.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/GdkCreateGatewayFunctionCommand.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/GdkCreateGatewayFunctionCommand.java
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/ServiceTypeConverter.java b/gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/ServiceTypeConverter.java
similarity index 100%
rename from gdk/gdk-cli/src/main/java/cloud/graal/gdk/command/ServiceTypeConverter.java
rename to gdk/gdk-cli-core/src/main/java/cloud/graal/gdk/command/ServiceTypeConverter.java
diff --git a/gdk/gdk-cli/src/main/resources/micronaut-starter-cli/resource-config.json b/gdk/gdk-cli-core/src/main/resources/micronaut-starter-cli/resource-config.json
similarity index 100%
rename from gdk/gdk-cli/src/main/resources/micronaut-starter-cli/resource-config.json
rename to gdk/gdk-cli-core/src/main/resources/micronaut-starter-cli/resource-config.json
diff --git a/gdk/gdk-cli/src/main/resources/org/fusesource/jansi/jansi.properties b/gdk/gdk-cli-core/src/main/resources/org/fusesource/jansi/jansi.properties
similarity index 100%
rename from gdk/gdk-cli/src/main/resources/org/fusesource/jansi/jansi.properties
rename to gdk/gdk-cli-core/src/main/resources/org/fusesource/jansi/jansi.properties
diff --git a/gdk/gdk-cli/README.adoc b/gdk/gdk-cli/README.adoc
index 9cb3662..b1eb1c9 100644
--- a/gdk/gdk-cli/README.adoc
+++ b/gdk/gdk-cli/README.adoc
@@ -1,6 +1,6 @@
= gdk-cli
-This submodule generates the GDK CLI application which is compiled to a native executable `gdk`, which works similarly to the Micronaut `mn` CLI with the addition of being able to generate GDK applications by specifying clouds and services.
+This submodule generates the GDK CLI application which is compiled to a native executable `gdk`, which works similarly to the Micronaut `mn` CLI with the addition of being able to generate GDK applications by specifying clouds and services. It depends on the `gdk-cli-core` submodule which contains most of the code.
== GdkStarter
diff --git a/gdk/gdk-cli/build.gradle b/gdk/gdk-cli/build.gradle
index 5320a76..790317c 100644
--- a/gdk/gdk-cli/build.gradle
+++ b/gdk/gdk-cli/build.gradle
@@ -15,66 +15,14 @@
*/
plugins {
- id 'gdk-module'
- id 'io.micronaut.application'
- id 'com.github.johnrengelman.shadow'
-}
-
-dependencies {
- annotationProcessor mnLibs.picocli.codegen
-
- compileOnly mnLibs.graal
-
- // not in libs.versions.toml to keep Micronaut version in 1 place (micronautVersion.txt)
- implementation(libs.micronaut.starter.cli) {
- exclude group: 'io.micronaut', module: 'micronaut-buffer-netty'
- exclude group: 'io.micronaut', module: 'micronaut-http-client'
- exclude group: 'io.micronaut', module: 'micronaut-http-client-core'
- exclude group: 'io.micronaut', module: 'micronaut-http-netty'
- exclude group: 'io.micronaut', module: 'micronaut-websocket'
- exclude group: 'io.micronaut.testresources', module: 'micronaut-test-resources-build-tools'
- exclude group: 'io.netty', module: 'netty-buffer'
- exclude group: 'io.netty', module: 'netty-codec'
- exclude group: 'io.netty', module: 'netty-codec-http'
- exclude group: 'io.netty', module: 'netty-codec-http2'
- exclude group: 'io.netty', module: 'netty-codec-socks'
- exclude group: 'io.netty', module: 'netty-common'
- exclude group: 'io.netty', module: 'netty-handler'
- exclude group: 'io.netty', module: 'netty-handler-proxy'
- exclude group: 'io.netty', module: 'netty-resolver'
- exclude group: 'io.netty', module: 'netty-transport'
- exclude group: 'io.swagger.core.v3', module: 'swagger-annotations'
- exclude group: 'org.eclipse.jgit', module: 'org.eclipse.jgit'
- exclude group: 'org.jline', module: 'jline'
- }
- runtimeOnly libs.bouncycastle.bcpkix
- runtimeOnly libs.bouncycastle.bcprov
- runtimeOnly libs.jansi
- runtimeOnly libs.jline
- runtimeOnly libs.slf4j.nop
- implementation mnLibs.micronaut.jackson.databind
- implementation mnLibs.micronaut.picocli
- implementation mnLibs.micronaut.validation
- implementation mnLibs.picocli
- implementation projects.gdkCore
-}
-
-configurations.all {
- exclude module: 'logback-classic'
+ id 'gdk-cli'
+ id 'gdk-module-public'
}
application {
mainClass.set 'cloud.graal.gdk.GdkStarter'
}
-micronaut {
- version libs.micronaut.starter.api.get().version
- processing {
- incremental true
- annotations 'cloud.graal.gdk.*'
- }
-}
-
graalvmNative {
binaries {
main {
@@ -86,20 +34,3 @@ graalvmNative {
startScripts {
applicationName = 'gdk'
}
-
-tasks.named('shadowJar') {
- mergeServiceFiles()
-}
-
-tasks.named('shadowDistZip') {
- enabled = false
-}
-tasks.named('shadowDistTar') {
- enabled = false
-}
-
-tasks.register('copyShadowJar', Sync) {
- from shadowJar.outputs
- into "${project.rootProject.buildDir}/libs"
- rename { String fileName -> 'cli.jar' }
-}
diff --git a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/GdkStarter.java b/gdk/gdk-cli/src/main/java/cloud/graal/gdk/GdkStarter.java
index 8ab8eec..de15231 100644
--- a/gdk/gdk-cli/src/main/java/cloud/graal/gdk/GdkStarter.java
+++ b/gdk/gdk-cli/src/main/java/cloud/graal/gdk/GdkStarter.java
@@ -16,33 +16,20 @@
*/
package cloud.graal.gdk;
-import cloud.graal.gdk.command.GdkBaseCommand;
import cloud.graal.gdk.command.GdkCommonOptionsMixin;
import cloud.graal.gdk.command.GdkCreateAppCommand;
import cloud.graal.gdk.command.GdkCreateFunctionCommand;
import cloud.graal.gdk.command.GdkCreateGatewayFunctionCommand;
-import io.micronaut.context.ApplicationContext;
-import io.micronaut.context.BeanContext;
import io.micronaut.context.annotation.Prototype;
import io.micronaut.core.annotation.TypeHint;
-import io.micronaut.inject.BeanDefinition;
-import io.micronaut.starter.cli.CodeGenConfig;
-import io.micronaut.starter.cli.InteractiveShell;
-import io.micronaut.starter.cli.MicronautFactory;
import io.micronaut.starter.cli.command.BuildToolCandidates;
import io.micronaut.starter.cli.command.BuildToolConverter;
-import io.micronaut.starter.cli.command.CodeGenCommand;
import io.micronaut.starter.cli.command.LanguageCandidates;
import io.micronaut.starter.cli.command.LanguageConverter;
import io.micronaut.starter.cli.command.TestFrameworkCandidates;
import io.micronaut.starter.cli.command.TestFrameworkConverter;
import io.micronaut.starter.cli.feature.acme.AcmeServerOption;
-import io.micronaut.starter.io.ConsoleOutput;
-import picocli.CommandLine;
import picocli.CommandLine.Command;
-import picocli.CommandLine.ParameterException;
-
-import java.util.function.BiFunction;
/**
* The main class for the library. Starts an interactive shell if passed no
@@ -79,20 +66,9 @@
AcmeServerOption.class
})
@Prototype
-public class GdkStarter extends GdkBaseCommand {
+public class GdkStarter extends AbstractStarter {
// TODO disable commands create-test / create-command / feature-diff / create-bean / create-job
- private static boolean interactiveShell = false;
-
- private static final BiFunction EXCEPTION_HANDLER = (e, commandLine) -> {
- GdkBaseCommand command = commandLine.getCommand();
- command.err(e.getMessage());
- if (command.showStacktrace()) {
- e.printStackTrace(commandLine.getErr());
- }
- return 1;
- };
-
/**
* Entry point for the CLI. Starts an interactive shell if passed no
* arguments, otherwise instantiates the requested command class and
@@ -102,54 +78,12 @@ public class GdkStarter extends GdkBaseCommand {
*/
public static void main(String[] args) {
GdkUtils.configureJdkVersions();
+ GdkStarter starter = new GdkStarter();
if (args.length == 0) {
// The first command line isn't technically in the shell yet so this is called before setting the static flag
- startShell();
+ starter.startShell();
} else {
- System.exit(execute(args));
- }
- }
-
- private static CommandLine createCommandLine() {
- boolean noOpConsole = GdkStarter.interactiveShell;
- try (BeanContext beanContext = ApplicationContext.builder().deduceEnvironment(false).start()) {
- return createCommandLine(beanContext, noOpConsole);
- }
- }
-
- private static int execute(String[] args) {
- boolean noOpConsole = args.length > 0 && args[0].startsWith("update-cli-config");
- try (BeanContext beanContext = ApplicationContext.builder().deduceEnvironment(false).start()) {
- return createCommandLine(beanContext, noOpConsole).execute(args);
+ System.exit(starter.execute(args));
}
}
-
- private static CommandLine createCommandLine(BeanContext beanContext, boolean noOpConsole) {
- GdkStarter starter = beanContext.getBean(GdkStarter.class);
- CommandLine commandLine = new CommandLine(starter, new MicronautFactory(beanContext));
- commandLine.setExecutionExceptionHandler((ex, commandLine1, parseResult) -> EXCEPTION_HANDLER.apply(ex, commandLine1));
- commandLine.setUsageHelpWidth(100);
-
- CodeGenConfig codeGenConfig = CodeGenConfig.load(beanContext, noOpConsole ? ConsoleOutput.NOOP : starter);
- if (codeGenConfig != null) {
- beanContext.getBeanDefinitions(CodeGenCommand.class).stream()
- .map(BeanDefinition::getBeanType)
- .map(bt -> beanContext.createBean(bt, codeGenConfig))
- .filter(CodeGenCommand::applies)
- .forEach(commandLine::addSubcommand);
- }
-
- return commandLine;
- }
-
- private static void startShell() {
- CommandLine commandLine = createCommandLine();
- GdkStarter.interactiveShell = true;
- new InteractiveShell(commandLine, GdkStarter::execute, EXCEPTION_HANDLER, "@|blue gdk>|@ ").start();
- }
-
- @Override
- public Integer call() {
- throw new ParameterException(spec.commandLine(), "No command specified");
- }
}
diff --git a/gdk/gdk-core/build.gradle b/gdk/gdk-core/build.gradle
index 95be116..c1e3d37 100644
--- a/gdk/gdk-core/build.gradle
+++ b/gdk/gdk-core/build.gradle
@@ -15,7 +15,7 @@
*/
plugins {
- id 'gdk-module'
+ id 'gdk-module-public'
id 'gdk.rocker'
id 'gdk-dependencies'
id 'io.micronaut.library'
@@ -44,6 +44,19 @@ dependencies {
exclude group: 'org.eclipse.jgit', module: 'org.eclipse.jgit'
}
implementation(mnLibs.micronaut.http.client)
+ implementation(libs.boms.netty)
+ implementation(libs.netty.buffer)
+ implementation(libs.netty.codec.http)
+ implementation(libs.netty.codec.http2)
+ implementation(libs.netty.common)
+ implementation(libs.netty.incubator.codec.http3)
+ implementation(libs.netty.handler)
+ implementation(libs.netty.handler.proxy)
+ implementation(libs.netty.transport.native.epoll)
+ implementation(libs.netty.transport.native.kqueue)
+ implementation(libs.netty.transport.native.iouring)
+ implementation(libs.netty.transport.native.unix.common)
+ implementation(libs.netty.tcnative.boringssl.static)
}
def writeVersions = tasks.register('writeVersions', cloud.graal.gdk.util.WriteVersionsTask) {
diff --git a/gdk/gdk-core/src/main/java/cloud/graal/gdk/feature/replaced/GdkMicronautBuildPlugin.java b/gdk/gdk-core/src/main/java/cloud/graal/gdk/feature/replaced/GdkMicronautBuildPlugin.java
new file mode 100644
index 0000000..2b9a3f7
--- /dev/null
+++ b/gdk/gdk-core/src/main/java/cloud/graal/gdk/feature/replaced/GdkMicronautBuildPlugin.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2023 Oracle and/or its affiliates
+ *
+ * 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
+ *
+ * https://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 cloud.graal.gdk.feature.replaced;
+
+import io.micronaut.context.annotation.Replaces;
+import io.micronaut.starter.application.ApplicationType;
+import io.micronaut.starter.application.generator.GeneratorContext;
+import io.micronaut.starter.build.dependencies.CoordinateResolver;
+import io.micronaut.starter.feature.build.MicronautBuildPlugin;
+import io.micronaut.starter.feature.build.gradle.Dockerfile;
+import io.micronaut.starter.feature.build.gradle.MicronautApplicationGradlePlugin;
+import io.micronaut.starter.feature.function.awslambda.AwsLambda;
+import io.micronaut.starter.options.JdkVersion;
+import jakarta.inject.Singleton;
+
+import static io.micronaut.starter.feature.graalvm.GraalVM.FEATURE_NAME_GRAALVM;
+
+/**
+ * Fix MicronautBuildPlugin by removing baseImage from build.gradle.
+ *
+ * @since 4.7
+ */
+@Replaces(MicronautBuildPlugin.class)
+@Singleton
+public class GdkMicronautBuildPlugin extends MicronautBuildPlugin {
+
+ public GdkMicronautBuildPlugin(CoordinateResolver coordinateResolver) {
+ super(coordinateResolver);
+ }
+
+ @Override
+ protected MicronautApplicationGradlePlugin.Builder micronautGradleApplicationPluginBuilder(GeneratorContext generatorContext) {
+ MicronautApplicationGradlePlugin.Builder builder = micronautGradleApplicationPluginBuilder(generatorContext, MicronautApplicationGradlePlugin.Builder.APPLICATION);
+ if (generatorContext.getFeatures().contains(AwsLambda.FEATURE_NAME_AWS_LAMBDA) && (
+ (generatorContext.getApplicationType() == ApplicationType.FUNCTION && generatorContext.getFeatures().contains(FEATURE_NAME_GRAALVM)) ||
+ (generatorContext.getApplicationType() == ApplicationType.DEFAULT))) {
+ builder.dockerNative(Dockerfile.builder()
+ .javaVersion(generatorContext.getJdkVersion().asString())
+ .arg("-XX:MaximumHeapSizePercent=80")
+ .arg("-Dio.netty.allocator.numDirectArenas=0")
+ .arg("-Dio.netty.noPreferDirect=true")
+ .build());
+ } else if (generatorContext.getJdkVersion() != JdkVersion.JDK_17) {
+ builder.dockerNative(Dockerfile.builder().javaVersion(generatorContext.getJdkVersion().asString()).build());
+ }
+ return builder;
+ }
+
+}
diff --git a/gdk/gdk-core/src/main/java/cloud/graal/gdk/model/GdkCloud.java b/gdk/gdk-core/src/main/java/cloud/graal/gdk/model/GdkCloud.java
index c58de07..c0547e6 100644
--- a/gdk/gdk-core/src/main/java/cloud/graal/gdk/model/GdkCloud.java
+++ b/gdk/gdk-core/src/main/java/cloud/graal/gdk/model/GdkCloud.java
@@ -52,13 +52,18 @@ public enum GdkCloud {
*/
NONE(null, "", "NONE", ROOT, ""),
+ /**
+ * Used when all supported clouds is selected for testing, not used as supported option.
+ */
+ ALL(null, "", "", "all", ""),
+
/**
* For testing.
*/
TESTING("testing", "-testing", "TESTING", "testing", "");
private static final GdkCloud[] SUPPORTED = Arrays.stream(values())
- .filter(c -> c != GdkCloud.TESTING && c != GdkCloud.NONE)
+ .filter(c -> c != GdkCloud.TESTING && c != GdkCloud.ALL && c != GdkCloud.NONE)
.toArray(GdkCloud[]::new);
private final String environmentName;
diff --git a/gdk/gdk-core/src/main/java/cloud/graal/gdk/template/MavenPomPostProcessor.java b/gdk/gdk-core/src/main/java/cloud/graal/gdk/template/MavenPomPostProcessor.java
index d5ea674..5f73081 100644
--- a/gdk/gdk-core/src/main/java/cloud/graal/gdk/template/MavenPomPostProcessor.java
+++ b/gdk/gdk-core/src/main/java/cloud/graal/gdk/template/MavenPomPostProcessor.java
@@ -101,13 +101,6 @@ public String process(@NonNull String pom) {
if (libModule) {
pom = fixArtifactId(pom);
pom = fixProcessingModule(pom);
- } else {
- if (applicationType == ApplicationType.DEFAULT && !isGatewayFunction) {
- pom = addDefaultDockerImageName(pom);
- }
- }
- if (libModule || cloud != GdkCloud.NONE) {
- pom = fixName(pom);
}
return pom;
@@ -139,10 +132,6 @@ private String fixParent(@NonNull String pom) {
return top + parent + bottom;
}
- private String fixName(@NonNull String pom) {
- return pom.replace("${packaging}", "${packaging}\n " + artifactId + "-${project.artifactId}");
- }
-
@NonNull
private String fixVersion(@NonNull String pom) {
return pom.replaceFirst("0.1", "1.0-SNAPSHOT");
@@ -181,25 +170,6 @@ private String fixProcessingModule(@NonNull String pom) {
return top + LIB_MODULE + bottom;
}
- @NonNull
- private String addDefaultDockerImageName(@NonNull String pom) {
- if (!pom.contains(PLUGINS_START)) {
- return pom;
- }
-
- pom = pom.replace(PLUGINS_START, PLUGINS_START +
- " \n" +
- " com.google.cloud.tools\n" +
- " jib-maven-plugin\n" +
- " \n" +
- " \n" +
- " ${project.name}\n" +
- " \n" +
- " \n" +
- " \n");
- return pom;
- }
-
@NonNull
private String fixMicronautVersion(@NonNull String pom) {
diff --git a/gdk/gradle/libs.versions.toml b/gdk/gradle/libs.versions.toml
index a38613e..28156ca 100644
--- a/gdk/gradle/libs.versions.toml
+++ b/gdk/gradle/libs.versions.toml
@@ -23,6 +23,10 @@ jline = '3.26.3'
logback = '1.5.8'
micronaut-plugins = '4.4.2'
micronaut-starter = '4.6.1'
+netty = "4.1.115.Final"
+netty-iouring = "0.0.25.Final"
+netty-http3 = "0.0.28.Final"
+netty-tcnative = "2.0.69.Final"
reflections = '0.10.2'
rocker = '1.4.0'
shadow = '8.1.1'
@@ -48,6 +52,19 @@ micronaut-application = { module = 'io.micronaut.gradle:micronaut-gradle-plugin'
micronaut-library = { module = 'io.micronaut.gradle:micronaut-gradle-plugin', version.ref = 'micronaut-plugins' }
micronaut-starter-api = { module = 'io.micronaut.starter:micronaut-starter-api', version.ref = 'micronaut-starter' }
micronaut-starter-cli = { module = 'io.micronaut.starter:micronaut-cli', version.ref = 'micronaut-starter' }
+boms-netty = { module = "io.netty:netty-bom", version.ref = "netty" }
+netty-buffer = { module = "io.netty:netty-buffer", version.ref = "netty" }
+netty-codec-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
+netty-codec-http2 = { module = "io.netty:netty-codec-http2", version.ref = "netty" }
+netty-common = { module = "io.netty:netty-common", version.ref = "netty" }
+netty-incubator-codec-http3 = { module = "io.netty.incubator:netty-incubator-codec-http3", version.ref = "netty-http3" }
+netty-handler = { module = "io.netty:netty-handler", version.ref = "netty" }
+netty-handler-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
+netty-transport-native-epoll = { module = "io.netty:netty-transport-native-epoll", version.ref = "netty" }
+netty-transport-native-kqueue = { module = "io.netty:netty-transport-native-kqueue", version.ref = "netty" }
+netty-transport-native-iouring = { module = "io.netty.incubator:netty-incubator-transport-native-io_uring", version.ref = "netty-iouring" }
+netty-transport-native-unix-common = { module = "io.netty:netty-transport-native-unix-common", version.ref = "netty" }
+netty-tcnative-boringssl-static = { module = "io.netty:netty-tcnative-boringssl-static", version.ref = "netty-tcnative" }
reflections = { module = 'org.reflections:reflections', version.ref = 'reflections' }
rocker = { module = 'com.fizzed:rocker-compiler', version.ref = 'rocker' }
shadow = { module = 'com.github.johnrengelman:shadow', version.ref = 'shadow' }
diff --git a/gdk/gradle/templates.versions.toml b/gdk/gradle/templates.versions.toml
index 238d482..b3aa1a6 100644
--- a/gdk/gradle/templates.versions.toml
+++ b/gdk/gradle/templates.versions.toml
@@ -26,17 +26,17 @@ io-spring-gradle-dependency-management-plugin = "1.1.6"
kotlin = "1.8.22"
logback = "1.5.8"
micronaut-cache = "5.0.1-oracle-00001"
-micronaut-core = "4.6.5-oracle-00001"
+micronaut-core = "4.6.8-oracle-00001"
micronaut-data = "4.9.2-oracle-00001"
micronaut-discovery = "4.4.0-oracle-00001"
micronaut-email = "2.6.0-oracle-00001"
micronaut-flyway = "7.4.0-oracle-00001"
-micronaut-gradle-plugin = "4.4.2"
+micronaut-gradle-plugin = "4.4.4"
micronaut-jaxrs = "4.6.0-oracle-00001"
micronaut-kafka = "5.6.0-oracle-00001"
micronaut-kubernetes = "6.1.0-oracle-00001"
micronaut-liquibase = "6.5.0-oracle-00001"
-micronaut-maven-plugin = "4.6.3"
+micronaut-maven-plugin = "4.7.0"
micronaut-maven-test-resources-plugin = "2.6.0"
micronaut-micrometer = "5.8.0-oracle-00001"
micronaut-mongo = "5.4.0-oracle-00001"
@@ -53,6 +53,8 @@ micronaut-sql = "5.8.1-oracle-00001"
micronaut-tracing = "6.8.0-oracle-00001"
micronaut-validation = "4.7.0-oracle-00001"
micronaut-views = "5.5.0-oracle-00001"
+netty = "4.1.115.Final"
+netty-tcnative = "2.0.69.Final"
okhttp = "4.12.0"
opentelemetry-semconv = "1.30.1-alpha"
org-springframework-boot-spring-boot-starter-parent = "3.3.3"
@@ -137,6 +139,17 @@ io-micronaut-tracing-micronaut-tracing-bom = { module = 'io.micronaut.tracing:mi
io-micronaut-validation-micronaut-validation-bom = { module = 'io.micronaut.validation:micronaut-validation-bom', version.ref = 'micronaut-validation'}
io-micronaut-views-micronaut-views-core = { module = 'io.micronaut.views:micronaut-views-core', version.ref = 'micronaut-views'}
io-micronaut-views-micronaut-views-jte = { module = 'io.micronaut.views:micronaut-views-jte', version.ref = 'micronaut-views'}
+boms-netty = { module = "io.netty:netty-bom", version.ref = "netty" }
+netty-buffer = { module = "io.netty:netty-buffer", version.ref = "netty" }
+netty-codec-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
+netty-codec-http2 = { module = "io.netty:netty-codec-http2", version.ref = "netty" }
+netty-common = { module = "io.netty:netty-common", version.ref = "netty" }
+netty-handler = { module = "io.netty:netty-handler", version.ref = "netty" }
+netty-handler-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" }
+netty-transport-native-epoll = { module = "io.netty:netty-transport-native-epoll", version.ref = "netty" }
+netty-transport-native-kqueue = { module = "io.netty:netty-transport-native-kqueue", version.ref = "netty" }
+netty-transport-native-unix-common = { module = "io.netty:netty-transport-native-unix-common", version.ref = "netty" }
+netty-tcnative-boringssl-static = { module = "io.netty:netty-tcnative-boringssl-static", version.ref = "netty-tcnative" }
io-opentelemetry-opentelemetry-semconv = { module = 'io.opentelemetry:opentelemetry-semconv', version.ref = 'opentelemetry-semconv'}
org-apache-commons-commons-compress = { module = 'org.apache.commons:commons-compress', version.ref = 'apache-commons-compress'}
org-bouncycastle-bcpkix-jdk15to18 = { module = 'org.bouncycastle:bcpkix-jdk15to18', version.ref = 'bouncycastle'}