-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Adding database suppliers #31073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding database suppliers #31073
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unreported flaky test detected, please review
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.federation.ldap.LDAPReadOnlyTest#testReadOnlyUserGetsPermanentlyLocked |
| @Override | ||
| public InstanceWrapper<KeycloakTestServer, KeycloakIntegrationTest> getValue(Registry registry, KeycloakIntegrationTest annotation) { | ||
| KeycloakTestServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config()); | ||
| DatabaseConfig databaseConfig = annotation.dbconfig() != null ? SupplierHelpers.getInstance(annotation.dbconfig()) : new DefaultDatabaseConfig(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it can be left like this because the dbconfig() returns the default value (DefaultDatabaseConfig.class) if it is not entered.
| DatabaseConfig databaseConfig = annotation.dbconfig() != null ? SupplierHelpers.getInstance(annotation.dbconfig()) : new DefaultDatabaseConfig(); | |
| DatabaseConfig databaseConfig = SupplierHelpers.getInstance(annotation.dbconfig()); |
9ca00b2 to
93f632e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I had in mind is close to this, but not quite.
My idea was that we would have multiple database suppliers:
- PostgresDatabaseSupplier
- MySQLDatabaseSupplier
- DevFileDatabaseSupplier
- DevMemDatabaseSupplier
Each supplier would supply a TestDatabase with start/stop methods, and a getConfig() method.
You'd select which DB supplier to use with #30609 in the same way as we would select a different server run-mode or browser.
TestDatabase would be responsible for starting/stopping the DB container using test containers.
For now it's fine that DBs are not configurable (we just let it auto configure itself to some sensible defaults), and that we don't support connecting to external DBs, we can do that as a follow-up.
18f01af to
cf6eae4
Compare
20c5a3f to
a7f61f5
Compare
db709fe to
9869df8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of this class?
| @Override | ||
| public InstanceWrapper<KeycloakTestServer, KeycloakIntegrationTest> getValue(Registry registry, KeycloakIntegrationTest annotation) { | ||
| KeycloakTestServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config()); | ||
| DatabaseSupplier databaseSupplier = new DevMemDatabaseSupplier(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not create the database supplier, but it should just use the registry to look it up:
TestDatabase database = registry.getDependency(TestDatabase.class, wrapper);
See
keycloak/test-poc/framework/src/main/java/org/keycloak/test/framework/realm/RealmSupplier.java
Lines 29 to 50 in 9247029
| InstanceWrapper<RealmResource, TestRealm> wrapper = new InstanceWrapper<>(this, annotation); | |
| LifeCycle lifecycle = annotation.lifecycle(); | |
| Keycloak adminClient = registry.getDependency(Keycloak.class, wrapper); | |
| RealmConfig config = SupplierHelpers.getInstance(annotation.config()); | |
| RealmRepresentation realmRepresentation = config.getRepresentation(); | |
| if (realmRepresentation.getRealm() == null) { | |
| String realmName = lifecycle.equals(LifeCycle.GLOBAL) ? config.getClass().getSimpleName() : registry.getCurrentContext().getRequiredTestClass().getSimpleName(); | |
| realmRepresentation.setRealm(realmName); | |
| } | |
| String realmName = realmRepresentation.getRealm(); | |
| wrapper.addNote(REALM_NAME_KEY, realmName); | |
| adminClient.realms().create(realmRepresentation); | |
| RealmResource realmResource = adminClient.realm(realmRepresentation.getRealm()); | |
| wrapper.setValue(realmResource, lifecycle); | |
| return wrapper; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather then getting supplier I am thinking of fully manged DB called within the KeycloakIntegrationTest annotation as a prerequisite, do you think @stianst it makes sense?
| @@ -0,0 +1,4 @@ | |||
| package org.keycloak.test.framework.database; | |||
|
|
|||
| public class DevMemDatabaseConfig implements DatabaseConfig { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you want to introduce rather DefaultDatabaseConfig class?
|
|
||
| import java.lang.annotation.Annotation; | ||
|
|
||
| public abstract class DatabaseSupplier implements Supplier<TestDatabase, Annotation> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you consider some TestManagedDatabase annotation which will be reused within KeycloakIntegrationTest annotation for ServiceLoader injection?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| @Override | ||
| public void start(KeycloakTestServerConfig serverConfig) { | ||
| public void start(KeycloakTestServerConfig serverConfig, TestDatabase testDatabase) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it would be cleaner to just pass the DatabaseConfig? Makes it clear that it shouldn't be stopping/starting the db or anything like that ;)
...ork/src/main/java/org/keycloak/test/framework/server/AbstractKeycloakTestServerSupplier.java
Show resolved
Hide resolved
...c/framework/src/main/java/org/keycloak/test/framework/server/EmbeddedKeycloakTestServer.java
Outdated
Show resolved
Hide resolved
...c/framework/src/main/java/org/keycloak/test/framework/server/EmbeddedKeycloakTestServer.java
Outdated
Show resolved
Hide resolved
|
|
||
| public abstract class DatabaseSupplier implements Supplier<TestDatabase, Annotation> { | ||
|
|
||
| protected static TestDatabase testDatabase = new TestDatabase(new DevMemDatabaseConfig()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the annotation introduction this could be then omitted and used like this: https://github.com/keycloak/keycloak/blob/main/test-poc/framework/src/main/java/org/keycloak/test/framework/KeycloakIntegrationTest.java#L15
173da6f to
053a1a2
Compare
| import java.util.Collections; | ||
| import java.util.Map; | ||
|
|
||
| public interface DatabaseConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to provide default implementations here? Or would all database providers have to implement this? Perhaps we can provide something else than an empty string such as null or Optional.empty()?
| default String vendor() { | ||
| return ""; | ||
| } | ||
|
|
||
| default String containerImage() { | ||
| return ""; | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both vendor and containerImage are not used anywhere, perhaps remove these until we need them to support a functionality?
| default String vendor() { | |
| return ""; | |
| } | |
| default String containerImage() { | |
| return ""; | |
| } |
| public TestDatabase getTestDatabase() { | ||
| return testDatabase; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is never used anywhere.
| public TestDatabase getTestDatabase() { | |
| return testDatabase; | |
| } |
...-poc/framework/src/main/java/org/keycloak/test/framework/database/DefaultDatabaseConfig.java
Outdated
Show resolved
Hide resolved
...oc/framework/src/main/java/org/keycloak/test/framework/database/DefaultDatabaseSupplier.java
Outdated
Show resolved
Hide resolved
| public void start() { | ||
|
|
||
| } | ||
|
|
||
| public void stop() { | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None of these methods currently do anything? Is there a place where we actually need to start a database and tear it down? Also it seems that stop() is never called.
| serverConfig.adminUserName().ifPresent(username -> rawOptions.add("--bootstrap-admin-username=" + username)); | ||
| serverConfig.adminUserPassword().ifPresent(password -> rawOptions.add("--bootstrap-admin-password=" + password)); | ||
|
|
||
| serverConfig.adminUserName().ifPresent(username -> System.setProperty("keycloakAdmin", username)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signed-off-by: Miquel Simon <[email protected]>
* Closes keycloak#30616. Added database suppliers. Signed-off-by: Miquel Simon <[email protected]> Co-authored-by: stianst <[email protected]>
Closes #30616