diff --git a/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java b/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java index 8b5757201d..0e81227ff3 100644 --- a/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java +++ b/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java @@ -20,8 +20,9 @@ import io.fabric8.kubernetes.api.model.Container; import io.fabric8.kubernetes.api.model.EnvVar; import io.fabric8.kubernetes.api.model.EnvVarBuilder; import io.fabric8.kubernetes.api.model.EnvVarSourceBuilder; -import io.fabric8.kubernetes.api.model.ExecActionBuilder; +import io.fabric8.kubernetes.api.model.HTTPGetActionBuilder; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.IntOrString; import io.fabric8.kubernetes.api.model.PodTemplateSpec; import io.fabric8.kubernetes.api.model.ResourceRequirements; import io.fabric8.kubernetes.api.model.apps.StatefulSet; @@ -399,26 +400,23 @@ public class KeycloakDeployment extends OperatorManagedResource implements Statu var tlsConfigured = isTlsConfigured(keycloakCR); var userRelativePath = readConfigurationValue(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY); var kcRelativePath = (userRelativePath == null) ? "" : userRelativePath; - var protocol = !tlsConfigured ? "http" : "https"; + var protocol = !tlsConfigured ? "HTTP" : "HTTPS"; var kcPort = KeycloakService.getServicePort(keycloakCR); - var baseProbe = new ArrayList<>(List.of("curl", "--head", "--fail", "--silent")); - - if (tlsConfigured) { - baseProbe.add("--insecure"); - } - - var readyProbe = new ArrayList<>(baseProbe); - readyProbe.add(protocol + "://127.0.0.1:" + kcPort + kcRelativePath + "/health/ready"); - var liveProbe = new ArrayList<>(baseProbe); - liveProbe.add(protocol + "://127.0.0.1:" + kcPort + kcRelativePath + "/health/live"); - - container - .getReadinessProbe() - .setExec(new ExecActionBuilder().withCommand(readyProbe).build()); - container - .getLivenessProbe() - .setExec(new ExecActionBuilder().withCommand(liveProbe).build()); + container.getReadinessProbe().setHttpGet( + new HTTPGetActionBuilder() + .withScheme(protocol) + .withPort(new IntOrString(kcPort)) + .withPath(kcRelativePath + "/health/ready") + .build() + ); + container.getLivenessProbe().setHttpGet( + new HTTPGetActionBuilder() + .withScheme(protocol) + .withPort(new IntOrString(kcPort)) + .withPath(kcRelativePath + "/health/live") + .build() + ); return baseDeployment; } diff --git a/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java b/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java index 903bc8b94c..5de704a142 100644 --- a/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java +++ b/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java @@ -493,7 +493,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest { .list() .getItems(); - assertTrue(pods.get(0).getSpec().getContainers().get(0).getReadinessProbe().getExec().getCommand().stream().collect(Collectors.joining()).contains("foobar")); + assertTrue(pods.get(0).getSpec().getContainers().get(0).getReadinessProbe().getHttpGet().getPath().contains("foobar")); } catch (Exception e) { savePodLogs(); throw e; @@ -529,7 +529,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest { .list() .getItems(); - assertTrue(pods.get(0).getSpec().getContainers().get(0).getReadinessProbe().getExec().getCommand().stream().collect(Collectors.joining()).contains("barfoo")); + assertTrue(pods.get(0).getSpec().getContainers().get(0).getReadinessProbe().getHttpGet().getPath().contains("barfoo")); } catch (Exception e) { savePodLogs(); throw e; diff --git a/quarkus/container/Dockerfile b/quarkus/container/Dockerfile index d965cd3435..f7af70ad7c 100644 --- a/quarkus/container/Dockerfile +++ b/quarkus/container/Dockerfile @@ -1,9 +1,9 @@ -FROM registry.access.redhat.com/ubi8-minimal AS build-env +FROM registry.access.redhat.com/ubi8 AS ubi-micro-build ENV KEYCLOAK_VERSION 999-SNAPSHOT ARG KEYCLOAK_DIST=https://github.com/keycloak/keycloak/releases/download/$KEYCLOAK_VERSION/keycloak-$KEYCLOAK_VERSION.tar.gz -RUN microdnf install -y tar gzip +RUN dnf install -y tar gzip ADD $KEYCLOAK_DIST /tmp/keycloak/ @@ -14,17 +14,18 @@ RUN (cd /tmp/keycloak && \ rm /tmp/keycloak/keycloak-*.tar.gz) || true RUN mv /tmp/keycloak/keycloak-* /opt/keycloak && mkdir -p /opt/keycloak/data - RUN chmod -R g+rwX /opt/keycloak -FROM registry.access.redhat.com/ubi8-minimal +ADD ubi8-null.sh /tmp/ +RUN bash /tmp/ubi8-null.sh java-17-openjdk-headless glibc-langpack-en + +FROM registry.access.redhat.com/ubi8-micro ENV LANG en_US.UTF-8 -COPY --from=build-env --chown=1000:0 /opt/keycloak /opt/keycloak +COPY --from=ubi-micro-build /tmp/null/rootfs/ / +COPY --from=ubi-micro-build --chown=1000:0 /opt/keycloak /opt/keycloak -RUN microdnf update -y && \ - microdnf install -y --nodocs java-17-openjdk-headless glibc-langpack-en && microdnf clean all && rm -rf /var/cache/yum/* && \ - echo "keycloak:x:0:root" >> /etc/group && \ +RUN echo "keycloak:x:0:root" >> /etc/group && \ echo "keycloak:x:1000:0:keycloak user:/opt/keycloak:/sbin/nologin" >> /etc/passwd USER 1000 diff --git a/quarkus/container/ubi8-null.sh b/quarkus/container/ubi8-null.sh new file mode 100644 index 0000000000..73654f8e3a --- /dev/null +++ b/quarkus/container/ubi8-null.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +set -euo pipefail +#set -x + +dir="/tmp/null" +rm -rf "$dir" +mkdir "$dir" +cd "$dir" + +# Add all arguments as the initial core packages +printf '%s\n' "$@" > keep +# Packages required for a shell environment +cat >>keep <disallow < Installing packages into chroot" >&2 + +set -x +# Install requirements for this script (xargs and cmp) +dnf install -y findutils diffutils +# Install core packages to chroot +rootfs="$(realpath rootfs)" +mkdir -p "$rootfs" +/dev/null + +echo "==> Building dependency tree" >&2 +# Loop until we have the full dependency tree (no new packages found) +touch old +while ! cmp -s keep old +do + # 1. Get requirement names (not quite the same as package names) + # 2. Filter out any install-time requirements + # 3. Query which packages are being used to satisfy the requirements + # 4. Keep just their package names + # 5. Remove packages that are on the disallow list + # 6. Store result as an allowlist + new + + # Safely replace the keep list, appending the new names + mv keep old + cat old new > keep + # Sort and deduplicate so cmp will eventually return true + sort -u keep -o keep +done + +# Determine all packages that need to be removed +rpm -r "$rootfs" -qa | sed -r 's/^(.*)-.*-.*$/\1/' | sort -u > all +# Set complement (all - keep) +grep -vxF -f keep all > remove + +echo "==> $(wc -l remove | cut -d ' ' -f1) packages to erase:" >&2 +cat remove +echo "==> $(wc -l keep | cut -d ' ' -f1) packages to keep:" >&2 +cat keep +echo "" >&2 + +echo "==> Erasing packages" >&2 +# Delete all packages that aren't needed for the core packages +set -x +/dev/null + +echo "" >&2 +echo "==> Packages erased ok!" >&2 diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java b/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java index 6fd9d1eb43..f900ddfb80 100644 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java +++ b/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java @@ -30,6 +30,7 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution { private File distributionFile = new File("../../dist/target/keycloak-" + Version.VERSION + ".tar.gz"); private File dockerFile = new File("../../container/Dockerfile"); + private File dockerScriptFile = new File("../../container/ubi8-null.sh"); private GenericContainer keycloakContainer = null; private String containerId = null; @@ -48,6 +49,7 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution { return new GenericContainer( new ImageFromDockerfile("keycloak-under-test", false) .withFileFromFile("keycloak.tar.gz", distributionFile) + .withFileFromFile("ubi8-null.sh", dockerScriptFile) .withFileFromFile("Dockerfile", dockerFile) .withBuildArg("KEYCLOAK_DIST", "keycloak.tar.gz") )