Skip to content

Commit

Permalink
Add capability to use --optimized option (#170)
Browse files Browse the repository at this point in the history
* Add capability to use --optimized option

Signed-off-by: Robin Meese <[email protected]>

* Fixes comments on PR

Signed-off-by: Robin Meese <[email protected]>

* Add Documentation and remove todo´s

Signed-off-by: Robin Meese <[email protected]>

* add implicit call for .withProductionMode()

Signed-off-by: Robin Meese <[email protected]>

* slightly adjusted and moved documentation to proper chapter

Signed-off-by: Niko Köbler <[email protected]>

---------

Signed-off-by: Robin Meese <[email protected]>
Signed-off-by: Niko Köbler <[email protected]>
Co-authored-by: Niko Köbler <[email protected]>
  • Loading branch information
robson90 and dasniko authored Jan 29, 2025
1 parent 4cd17e0 commit 91cbf4b
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 4 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,21 @@ KeycloakContainer keycloak = new KeycloakContainer()
.withProductionMode();
```

### Optimized flag

It is possible that you use your own pre-build image with the `--optimized` flag.
Setting this option will implicitly enable production mode!

```java
@Container
KeycloakContainer keycloak = new KeycloakContainer("<YOUR_IMAGE>" + ":<YOUR_TAG>")
.withOptimizedFlag();
```

NOTE: If you don't enable the health endpoint, the container will not be healthy.
In this case please provide your own waitStrategy.
Check out the tests at [`KeycloakContainerOptimizedTest`](./src/test/java/dasniko/testcontainers/keycloak/KeycloakContainerOptimizedTest.java).

## Testing Custom Extensions

To ease extension testing, you can tell the Keycloak Testcontainer to detect extensions in a given classpath folder.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public abstract class ExtendableKeycloakContainer<SELF extends ExtendableKeycloa
private List<String> customCommandParts;

private boolean bootstrapAdmin = true;
private boolean optimizeFlag = false;

/**
* Create a KeycloakContainer with default image and version tag
Expand Down Expand Up @@ -199,10 +200,17 @@ protected void configure() {
});
withEnv("KC_TRUSTSTORE_PATHS", String.join(",", truststorePaths));
}
withEnv("KC_HTTPS_CLIENT_AUTH", httpsClientAuth.toString());
withEnv("KC_HTTPS_MANAGEMENT_CLIENT_AUTH", HttpsClientAuth.NONE.toString());

withEnv("KC_METRICS_ENABLED", Boolean.toString(metricsEnabled));
if (!this.optimizeFlag) {
// here are all default build options listed, that would prevent Keycloak from starting, without a new build
withEnv("KC_HTTPS_CLIENT_AUTH", httpsClientAuth.toString());
withEnv("KC_HTTPS_MANAGEMENT_CLIENT_AUTH", HttpsClientAuth.NONE.toString());

withEnv("KC_METRICS_ENABLED", Boolean.toString(metricsEnabled));
} else {
commandParts.add("--optimized");
}

withEnv("KC_HEALTH_ENABLED", Boolean.toString(Boolean.TRUE));
if (!customWaitStrategySet) {
HttpWaitStrategy waitStrategy = Wait.forHttp(contextPath + "/health/started").forPort(KEYCLOAK_PORT_MGMT);
Expand Down Expand Up @@ -526,6 +534,17 @@ public SELF withBootstrapAdminDisabled() {
return self();
}

/**
* Will add the "--optimized" flag to Keycloak startup command.
* It will ignore all build time options, that have been set.
* For example: KC_HTTPS_CLIENT_AUTH, KC_HTTPS_MANAGEMENT_CLIENT_AUTH
*
*/
public SELF withOptimizedFlag() {
this.optimizeFlag = true;
return self().withProductionMode();
}

/**
* Returns the keycloak admin. Note that this may not return a functioning admin client
* if the master realm including users were imported.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package dasniko.testcontainers.keycloak;

import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.images.builder.ImageFromDockerfile;

import java.nio.file.Paths;

import static io.restassured.RestAssured.given;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;

public class KeycloakContainerOptimizedTest {

public static final String UPDATING_THE_CONFIGURATION = "Updating the configuration and installing your custom providers, if any. Please wait.";
private KeycloakContainer keycloakContainer;

@BeforeEach
void setUp() {
try (GenericContainer<?> container = new GenericContainer<>(
new ImageFromDockerfile("temporary-keycloak-image", false)
.withDockerfile(Paths.get("src/test/resources/Dockerfile"))
.withTarget("builder"))) {
try (KeycloakContainer keycloak = new KeycloakContainer(container.getDockerImageName() + ":latest")
.useTls()
.withEnv("KC_HOSTNAME_STRICT", "false")
.withOptimizedFlag()) {
keycloakContainer = keycloak;
}
}
}

@Test
public void shouldBeAvailableOnHTTPS() {
keycloakContainer.start();
RestAssured.useRelaxedHTTPSValidation();
assertThat(keycloakContainer.getAuthServerUrl(), startsWith("https://"));
given()
.when().get(keycloakContainer.getAuthServerUrl())
.then().statusCode(200);
}

@Test
public void shouldBeAvailableWithProfileProd() {
keycloakContainer.start();
assertThat(keycloakContainer.getLogs(), containsString("Profile prod activated."));
}

@Test
public void shouldBeAvailableWithoutInstallingProviderLogMessage() {
keycloakContainer.start();
assertThat(keycloakContainer.getLogs(),
not(containsString(UPDATING_THE_CONFIGURATION)));
}

@Test
public void shouldStartWithProviderInstallationLogMessageWhenOptimizedIsNotSet() {
try (KeycloakContainer keycloak = new KeycloakContainer()) {
keycloak.start();
assertThat(keycloak.getLogs(),
containsString(UPDATING_THE_CONFIGURATION));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -230,5 +230,4 @@ private void testDebugPortAvailable(final String debugHost, final int debugPort)
}
}
}

}
16 changes: 16 additions & 0 deletions src/test/resources/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM quay.io/keycloak/keycloak:nightly AS builder

# copied from: https://www.keycloak.org/server/containers
# DISCLAIMER THIS IS ONLY FOR TESTING PURPOSE. DO NOT, I REAPEAT DO NOT USE THIS Dockerfile IN PRODUCTION

ENV KC_HEALTH_ENABLED=true

WORKDIR /opt/keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:nightly
COPY --from=builder /opt/keycloak/ /opt/keycloak/

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

0 comments on commit 91cbf4b

Please sign in to comment.