[KEYCLOAK-19380] - Import not running once schema is inited and requiring full server setup

This commit is contained in:
Pedro Igor 2021-09-23 13:35:18 -03:00
parent 69a146db7e
commit 6e8cd3262d
5 changed files with 50 additions and 47 deletions

View file

@ -19,11 +19,16 @@ package org.keycloak.cli;
import static org.keycloak.cli.Picocli.error;
import static org.keycloak.cli.Picocli.println;
import static org.keycloak.exportimport.ExportImportConfig.ACTION_EXPORT;
import static org.keycloak.exportimport.ExportImportConfig.ACTION_IMPORT;
import static org.keycloak.exportimport.Strategy.IGNORE_EXISTING;
import static org.keycloak.exportimport.Strategy.OVERWRITE_EXISTING;
import io.quarkus.bootstrap.runner.RunnerClassLoader;
import org.keycloak.configuration.KeycloakConfigSourceProvider;
import io.quarkus.bootstrap.runner.QuarkusEntryPoint;
import org.keycloak.util.Environment;
import picocli.CommandLine;
import picocli.CommandLine.Command;
@ -31,10 +36,6 @@ import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.Spec;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Map;
@Command(name = "keycloak",
usageHelpWidth = 150,
header = "Keycloak - Open Source Identity and Access Management\n\nFind more information at: https://www.keycloak.org/%n",
@ -109,8 +110,7 @@ public class MainCommand {
optionListHeading = "%nOptions%n",
parameterListHeading = "Available Commands%n")
public void startDev(@Option(names = "--verbose", description = "Print out more details when running this command.", required = false) Boolean verbose) {
System.setProperty("kc.profile", "dev");
System.setProperty("quarkus.profile", "dev");
setProfile("dev");
KeycloakMain.start(spec.commandLine());
}
@ -126,28 +126,13 @@ public class MainCommand {
@Option(names = "--users", arity = "1", description = "Set how users should be exported. Possible values are: skip, realm_file, same_file, different_files.", paramLabel = "<strategy>", defaultValue = "different_files") String users,
@Option(names = "--users-per-file", arity = "1", description = "Set the number of users per file. Its used only if --users=different_files.", paramLabel = "<number>", defaultValue = "50") Integer usersPerFile,
@Option(names = "--verbose", description = "Print out more details when running this command.", required = false) Boolean verbose) {
System.setProperty("keycloak.migration.action", "export");
if (toDir != null) {
System.setProperty("keycloak.migration.provider", "dir");
System.setProperty("keycloak.migration.dir", toDir);
} else if (toFile != null) {
System.setProperty("keycloak.migration.provider", "singleFile");
System.setProperty("keycloak.migration.file", toFile);
} else {
error(spec.commandLine(), "Must specify either --dir or --file options.");
}
System.setProperty("keycloak.migration.usersExportStrategy", users.toUpperCase());
if (usersPerFile != null) {
System.setProperty("keycloak.migration.usersPerFile", usersPerFile.toString());
}
if (realm != null) {
System.setProperty("keycloak.migration.realmName", realm);
}
KeycloakMain.start(spec.commandLine());
runImportExport(ACTION_EXPORT, toDir, toFile, realm, verbose);
}
@Command(name = "import",
@ -161,24 +146,9 @@ public class MainCommand {
@Option(names = "--realm", arity = "1", description = "Set the name of the realm to import", paramLabel = "<realm>") String realm,
@Option(names = "--override", arity = "1", description = "Set if existing data should be skipped or overridden.", paramLabel = "false", defaultValue = "true") boolean override,
@Option(names = "--verbose", description = "Print out more details when running this command.", required = false) Boolean verbose) {
System.setProperty("keycloak.migration.action", "import");
if (toDir != null) {
System.setProperty("keycloak.migration.provider", "dir");
System.setProperty("keycloak.migration.dir", toDir);
} else if (toFile != null) {
System.setProperty("keycloak.migration.provider", "singleFile");
System.setProperty("keycloak.migration.file", toFile);
} else {
error(spec.commandLine(), "Must specify either --dir or --file options.");
}
System.setProperty("keycloak.migration.strategy", override ? OVERWRITE_EXISTING.name() : IGNORE_EXISTING.name());
if (realm != null) {
System.setProperty("keycloak.migration.realmName", realm);
}
System.setProperty("keycloak.migration.strategy", override ? "OVERWRITE_EXISTING" : "IGNORE_EXISTING");
KeycloakMain.start(spec.commandLine());
runImportExport(ACTION_IMPORT, toDir, toFile, realm, verbose);
}
@Command(name = "start",
@ -212,4 +182,25 @@ public class MainCommand {
System.setProperty("kc.show.config", filter);
KeycloakMain.start(spec.commandLine());
}
private void runImportExport(String action, String toDir, String toFile, String realm, Boolean verbose) {
System.setProperty("keycloak.migration.action", action);
if (toDir != null) {
System.setProperty("keycloak.migration.provider", "dir");
System.setProperty("keycloak.migration.dir", toDir);
} else if (toFile != null) {
System.setProperty("keycloak.migration.provider", "singleFile");
System.setProperty("keycloak.migration.file", toFile);
} else {
error(spec.commandLine(), "Must specify either --dir or --file options.");
}
if (realm != null) {
System.setProperty("keycloak.migration.realmName", realm);
}
setProfile(Environment.IMPORT_EXPORT_MODE);
start(null, verbose);
}
}

View file

@ -54,7 +54,8 @@ public final class PropertyMappers {
Boolean enabled = Boolean.valueOf(value);
ConfigValue proxy = context.proceed(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX + "proxy");
if (Environment.isDevMode() || (proxy != null && "edge".equalsIgnoreCase(proxy.getValue()))) {
if (Environment.isDevMode() || Environment.isImportExportMode()
|| (proxy != null && "edge".equalsIgnoreCase(proxy.getValue()))) {
enabled = true;
}

View file

@ -74,6 +74,7 @@ import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.transaction.JtaTransactionManagerLookup;
import org.keycloak.util.Environment;
import org.keycloak.util.JsonSerialization;
/**
@ -144,20 +145,20 @@ public final class QuarkusJpaConnectionProviderFactory implements JpaConnectionP
emf = instance.get();
KeycloakSession session = factory.create();
boolean initSchema;
boolean schemaChanged;
try (Connection connection = getConnection()) {
createOperationalInfo(connection);
addSpecificNamedQueries(session, connection);
initSchema = createOrUpdateSchema(getSchema(), connection, session);
schemaChanged = createOrUpdateSchema(getSchema(), connection, session);
} catch (SQLException cause) {
throw new RuntimeException("Failed to update database.", cause);
} finally {
session.close();
}
if (initSchema || ExportImportConfig.ACTION_EXPORT.equals(ExportImportConfig.getAction())) {
runJobInTransaction(factory, this::initSchemaOrExport);
if (schemaChanged || Environment.isImportExportMode()) {
runJobInTransaction(factory, this::initSchema);
}
}
@ -201,7 +202,7 @@ public final class QuarkusJpaConnectionProviderFactory implements JpaConnectionP
}
}
private void initSchemaOrExport(KeycloakSession session) {
private void initSchema(KeycloakSession session) {
ExportImportManager exportImportManager = new ExportImportManager(session);
/*

View file

@ -26,6 +26,8 @@ import org.keycloak.configuration.Configuration;
public final class Environment {
public static final String IMPORT_EXPORT_MODE = "import_export";
public static Boolean isRebuild() {
return Boolean.valueOf(System.getProperty("quarkus.launch.rebuild"));
}
@ -90,6 +92,10 @@ public final class Environment {
return ProfileManager.getLaunchMode() == LaunchMode.DEVELOPMENT;
}
public static boolean isImportExportMode() {
return IMPORT_EXPORT_MODE.equalsIgnoreCase(getProfile());
}
public static boolean isWindows() {
return SystemUtils.IS_OS_WINDOWS;
}

View file

@ -19,6 +19,10 @@ spi.theme.folder.dir=${kc.home.dir:}/themes
%dev.spi.theme.cache-templates=false
%dev.spi.theme.static-max-age=-1
# The default configuration when running in import or export mode
%import_export.http.enabled=true
%import_export.cluster=local
# Logging configuration. INFO is the default level for most of the categories
#quarkus.log.level = DEBUG
quarkus.log.category."org.jboss.resteasy.resteasy_jaxrs.i18n".level=WARN