Aligning kc.bat with latest changes to kc.sh
Closes #11185 Closes #13472
This commit is contained in:
parent
ec384702a9
commit
0d3ca438ed
6 changed files with 87 additions and 67 deletions
42
quarkus/dist/src/main/content/bin/kc.bat
vendored
42
quarkus/dist/src/main/content/bin/kc.bat
vendored
|
@ -57,14 +57,15 @@ if not "%KEY:~0,2%"=="--" if "%KEY:~0,2%"=="-D" (
|
||||||
if not "%KEY:~0,2%"=="--" if not "%KEY:~0,1%"=="-" (
|
if not "%KEY:~0,2%"=="--" if not "%KEY:~0,1%"=="-" (
|
||||||
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY%"
|
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY%"
|
||||||
)
|
)
|
||||||
if "%KEY:~0,2%"=="--" if not "%KEY:~0,2%"=="-D" if "%KEY:~0,1%"=="-" (
|
if not "%KEY:~0,2%"=="-D" (
|
||||||
if "%~2"=="" (
|
if "%KEY:~0,1%"=="-" (
|
||||||
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY%"
|
if "%~2"=="" (
|
||||||
) else (
|
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY%"
|
||||||
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY% %~2%"
|
) else (
|
||||||
|
set "CONFIG_ARGS=%CONFIG_ARGS% %KEY% %~2%"
|
||||||
|
)
|
||||||
|
shift
|
||||||
)
|
)
|
||||||
|
|
||||||
shift
|
|
||||||
)
|
)
|
||||||
shift
|
shift
|
||||||
goto READ-ARGS
|
goto READ-ARGS
|
||||||
|
@ -129,14 +130,33 @@ set "JAVA_RUN_OPTS=%JAVA_OPTS% -Dkc.home.dir="%DIRNAME%.." -Djboss.server.config
|
||||||
|
|
||||||
SetLocal EnableDelayedExpansion
|
SetLocal EnableDelayedExpansion
|
||||||
|
|
||||||
set "ONLY_BUILD_OPTION= build"
|
set "OPTIMIZED_OPTION=--optimized"
|
||||||
set "NO_AUTO_BUILD_OPTION=optimized"
|
set "HELP_LONG_OPTION=--help"
|
||||||
|
set "BUILD_OPTION= build"
|
||||||
|
set IS_HELP_SHORT=false
|
||||||
|
|
||||||
|
echo "%CONFIG_ARGS%" | findstr /r "\<-h\>" > nul
|
||||||
|
|
||||||
|
if not errorlevel == 1 (
|
||||||
|
set IS_HELP_SHORT=true
|
||||||
|
)
|
||||||
|
|
||||||
|
set START_SERVER=true
|
||||||
|
|
||||||
|
if "!CONFIG_ARGS:%OPTIMIZED_OPTION%=!"=="!CONFIG_ARGS!" if "!CONFIG_ARGS:%BUILD_OPTION%=!"=="!CONFIG_ARGS!" if "!CONFIG_ARGS:%HELP_LONG_OPTION%=!"=="!CONFIG_ARGS!" if "%IS_HELP_SHORT%" == "false" (
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
if "!CONFIG_ARGS:%NO_AUTO_BUILD_OPTION%=!"=="!CONFIG_ARGS!" if "!CONFIG_ARGS:%ONLY_BUILD_OPTION%=!"=="!CONFIG_ARGS!" (
|
|
||||||
"%JAVA%" -Dkc.config.build-and-exit=true %JAVA_RUN_OPTS%
|
"%JAVA%" -Dkc.config.build-and-exit=true %JAVA_RUN_OPTS%
|
||||||
|
|
||||||
|
if not !errorlevel! == 0 (
|
||||||
|
set START_SERVER=false
|
||||||
|
)
|
||||||
|
|
||||||
set "JAVA_RUN_OPTS=-Dkc.config.built=true %JAVA_RUN_OPTS%"
|
set "JAVA_RUN_OPTS=-Dkc.config.built=true %JAVA_RUN_OPTS%"
|
||||||
)
|
)
|
||||||
|
|
||||||
"%JAVA%" %JAVA_RUN_OPTS%
|
if "%START_SERVER%" == "true" (
|
||||||
|
"%JAVA%" %JAVA_RUN_OPTS%
|
||||||
|
)
|
||||||
|
|
||||||
:END
|
:END
|
||||||
|
|
|
@ -35,7 +35,6 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -43,7 +42,6 @@ import java.util.Properties;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
@ -52,20 +50,22 @@ import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import io.quarkus.deployment.util.FileUtil;
|
||||||
import io.quarkus.fs.util.ZipUtils;
|
import io.quarkus.fs.util.ZipUtils;
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
|
|
||||||
import org.keycloak.common.Version;
|
import org.keycloak.common.Version;
|
||||||
import org.keycloak.it.junit5.extension.CLIResult;
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
import org.keycloak.quarkus.runtime.Environment;
|
|
||||||
import org.keycloak.quarkus.runtime.cli.command.Build;
|
import org.keycloak.quarkus.runtime.cli.command.Build;
|
||||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
|
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
|
||||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
|
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
|
||||||
|
|
||||||
import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE;
|
import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE;
|
||||||
|
import static org.keycloak.quarkus.runtime.Environment.isWindows;
|
||||||
|
|
||||||
public final class RawKeycloakDistribution implements KeycloakDistribution {
|
public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
|
|
||||||
|
private static final int DEFAULT_SHUTDOWN_TIMEOUT_SECONDS = 10;
|
||||||
|
|
||||||
private Process keycloak;
|
private Process keycloak;
|
||||||
private int exitCode = -1;
|
private int exitCode = -1;
|
||||||
private final Path distPath;
|
private final Path distPath;
|
||||||
|
@ -128,24 +128,14 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
try {
|
try {
|
||||||
if (Environment.isWindows()) {
|
// On Windows, we need to make sure sub-processes are terminated first
|
||||||
// On Windows, we're executing kc.bat in a runtime as "keycloak",
|
destroyDescendantsOnWindows(keycloak, false);
|
||||||
// so tha java process is an actual child process
|
|
||||||
// we have to kill first.
|
|
||||||
killChildProcessesOnWindows(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
keycloak.destroy();
|
keycloak.destroy();
|
||||||
keycloak.waitFor(10, TimeUnit.SECONDS);
|
keycloak.waitFor(DEFAULT_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||||
exitCode = keycloak.exitValue();
|
exitCode = keycloak.exitValue();
|
||||||
} catch (Exception cause) {
|
} catch (Exception cause) {
|
||||||
if (Environment.isWindows()) {
|
destroyDescendantsOnWindows(keycloak, true);
|
||||||
try {
|
|
||||||
killChildProcessesOnWindows(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Failed to stop the server", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keycloak.destroyForcibly();
|
keycloak.destroyForcibly();
|
||||||
throw new RuntimeException("Failed to stop the server", cause);
|
throw new RuntimeException("Failed to stop the server", cause);
|
||||||
}
|
}
|
||||||
|
@ -154,19 +144,36 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
shutdownOutputExecutor();
|
shutdownOutputExecutor();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void killChildProcessesOnWindows(boolean isForced) {
|
private void destroyDescendantsOnWindows(Process parent, boolean force) {
|
||||||
for (ProcessHandle childProcessHandle : keycloak.children().collect(Collectors.toList())) {
|
if (!isWindows()) {
|
||||||
CompletableFuture<ProcessHandle> onExit = childProcessHandle.onExit();
|
return;
|
||||||
if (isForced) {
|
}
|
||||||
childProcessHandle.destroyForcibly();
|
|
||||||
|
CompletableFuture allProcesses = CompletableFuture.completedFuture(null);
|
||||||
|
|
||||||
|
for (ProcessHandle process : parent.descendants().collect(Collectors.toList())) {
|
||||||
|
if (force) {
|
||||||
|
process.destroyForcibly();
|
||||||
} else {
|
} else {
|
||||||
childProcessHandle.destroy();
|
process.destroy();
|
||||||
}
|
}
|
||||||
//for whatever reason windows doesnt wait for the termination,
|
|
||||||
// and parent process returns immediately with exitCode 1 but is not exited, leading to
|
allProcesses = CompletableFuture.allOf(allProcesses, process.onExit());
|
||||||
// "failed to start the distribution" bc files that should be deleted
|
}
|
||||||
// are used by another process, so we need this here.
|
|
||||||
onExit.join();
|
try {
|
||||||
|
allProcesses.get(DEFAULT_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||||
|
} catch (Exception cause) {
|
||||||
|
throw new RuntimeException("Failed to terminate descendants processes", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// TODO: remove this. do not ask why, but on Windows we are here even though the process was previously terminated
|
||||||
|
// without this pause, tests re-installing dist before tests should fail
|
||||||
|
// looks like pausing the current thread let windows to cleanup processes?
|
||||||
|
// more likely it is env dependent
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +202,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
public String[] getCliArgs(List<String> arguments) {
|
public String[] getCliArgs(List<String> arguments) {
|
||||||
List<String> allArgs = new ArrayList<>();
|
List<String> allArgs = new ArrayList<>();
|
||||||
|
|
||||||
if (Environment.isWindows()) {
|
if (isWindows()) {
|
||||||
allArgs.add(distPath.resolve("bin") + File.separator + SCRIPT_CMD_INVOKABLE);
|
allArgs.add(distPath.resolve("bin") + File.separator + SCRIPT_CMD_INVOKABLE);
|
||||||
} else {
|
} else {
|
||||||
allArgs.add(SCRIPT_CMD_INVOKABLE);
|
allArgs.add(SCRIPT_CMD_INVOKABLE);
|
||||||
|
@ -340,13 +347,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
Path dPath = distRootPath.resolve(distDirName.substring(0, distDirName.lastIndexOf('.')));
|
Path dPath = distRootPath.resolve(distDirName.substring(0, distDirName.lastIndexOf('.')));
|
||||||
|
|
||||||
if (!inited || (reCreate || !dPath.toFile().exists())) {
|
if (!inited || (reCreate || !dPath.toFile().exists())) {
|
||||||
|
FileUtil.deleteDirectory(dPath);
|
||||||
if (!Environment.isWindows()) {
|
|
||||||
FileUtils.deleteDirectory(dPath.toFile());
|
|
||||||
} else {
|
|
||||||
deleteTempFilesOnWindows(dPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZipUtils.unzip(distFile.toPath(), distRootPath);
|
ZipUtils.unzip(distFile.toPath(), distRootPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,23 +364,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteTempFilesOnWindows(Path dPath) {
|
|
||||||
if (Files.exists(dPath)) {
|
|
||||||
try (Stream<Path> walk = Files.walk(dPath)) {
|
|
||||||
walk.sorted(Comparator.reverseOrder())
|
|
||||||
.forEach(s -> {
|
|
||||||
try {
|
|
||||||
Files.delete(s);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Could not delete temp directory for distribution", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Could not traverse temp directory for distribution to delete files", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readOutput() {
|
private void readOutput() {
|
||||||
try (
|
try (
|
||||||
BufferedReader outStream = new BufferedReader(new InputStreamReader(keycloak.getInputStream()));
|
BufferedReader outStream = new BufferedReader(new InputStreamReader(keycloak.getInputStream()));
|
||||||
|
|
|
@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.condition.OS;
|
||||||
import org.keycloak.it.cli.HelpCommandTest;
|
import org.keycloak.it.cli.HelpCommandTest;
|
||||||
import org.keycloak.it.junit5.extension.CLIResult;
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
|
@ -35,7 +36,13 @@ public class HelpCommandDistTest extends HelpCommandTest {
|
||||||
public void testHelpDoesNotStartReAugJvm(KeycloakDistribution dist) {
|
public void testHelpDoesNotStartReAugJvm(KeycloakDistribution dist) {
|
||||||
for (String helpCmd : List.of("-h", "--help", "--help-all")) {
|
for (String helpCmd : List.of("-h", "--help", "--help-all")) {
|
||||||
for (String cmd : List.of("", "start", "start-dev", "build")) {
|
for (String cmd : List.of("", "start", "start-dev", "build")) {
|
||||||
CLIResult run = dist.run("--debug", cmd, helpCmd);
|
String debugOption = "--debug";
|
||||||
|
|
||||||
|
if (OS.WINDOWS.isCurrentOs()) {
|
||||||
|
debugOption = "--debug=8787";
|
||||||
|
}
|
||||||
|
|
||||||
|
CLIResult run = dist.run(debugOption, cmd, helpCmd);
|
||||||
assertSingleJvmStarted(run);
|
assertSingleJvmStarted(run);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ package org.keycloak.it.cli.dist;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||||
|
import org.junit.jupiter.api.condition.OS;
|
||||||
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
||||||
import org.keycloak.it.junit5.extension.CLIResult;
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
|
@ -60,6 +62,7 @@ public class ImportAtStartupDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.")
|
||||||
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
||||||
@Launch({"start-dev", "--import-realm=some-file"})
|
@Launch({"start-dev", "--import-realm=some-file"})
|
||||||
void failSetValueToImportRealmOption(LaunchResult result) {
|
void failSetValueToImportRealmOption(LaunchResult result) {
|
||||||
|
|
|
@ -65,4 +65,11 @@ public class StartCommandDistTest extends StartCommandTest {
|
||||||
cliResult.assertStarted();
|
cliResult.assertStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Launch({ "start", "--optimized", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
|
||||||
|
void testStartUsingOptimizedDoesNotAllowBuildOptions(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
cliResult.assertError("Unknown option: '--cache'");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,4 +93,3 @@ Examples:
|
||||||
Change the relative path:
|
Change the relative path:
|
||||||
|
|
||||||
$ kc.bat build --http-relative-path=/auth
|
$ kc.bat build --http-relative-path=/auth
|
||||||
|
|
Loading…
Reference in a new issue