Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public final class Constants {
public static final String KEYCLOAK_COMPONENT_LABEL = "operator.keycloak.org/component";
public static final String KEYCLOAK_WATCHED_SECRET_HASH_ANNOTATION = "operator.keycloak.org/watched-secret-hash";
public static final String KEYCLOAK_WATCHING_ANNOTATION = "operator.keycloak.org/watching-secrets";
public static final String KEYCLOAK_MISSING_SECRETS_ANNOTATION = "operator.keycloak.org/missing-secrets";

public static final String DEFAULT_LABELS_AS_STRING = "app=keycloak,app.kubernetes.io/managed-by=keycloak-operator";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ public UpdateControl<Keycloak> reconcile(Keycloak kc, Context<Keycloak> context)
updateControl = UpdateControl.updateStatus(kc);
}

if (!status.isReady()) {
if (!status.isReady() || context.getSecondaryResource(StatefulSet.class)
.map(s -> s.getMetadata().getAnnotations().get(Constants.KEYCLOAK_MISSING_SECRETS_ANNOTATION))
.filter(Boolean::valueOf).isPresent()) {
updateControl.rescheduleAfter(10, TimeUnit.SECONDS);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -103,14 +104,17 @@ public EventSource getWatchedSecretsEventSource() {
@Override
public void annotateDeployment(List<String> desiredWatchedSecretsNames, Keycloak keycloakCR, StatefulSet deployment) {
List<Secret> currentSecrets = fetchSecrets(desiredWatchedSecretsNames, keycloakCR.getMetadata().getNamespace());
deployment.getMetadata().getAnnotations().put(Constants.KEYCLOAK_MISSING_SECRETS_ANNOTATION,
Boolean.valueOf(currentSecrets.size() < desiredWatchedSecretsNames.size()).toString());
deployment.getMetadata().getAnnotations().put(Constants.KEYCLOAK_WATCHING_ANNOTATION, desiredWatchedSecretsNames.stream().collect(Collectors.joining(";")));
deployment.getSpec().getTemplate().getMetadata().getAnnotations().put(Constants.KEYCLOAK_WATCHED_SECRET_HASH_ANNOTATION, getSecretHash(currentSecrets));
}

private List<Secret> fetchSecrets(List<String> secretsNames, String namespace) {
return secretsNames.stream()
.map(n -> Optional.ofNullable(secrets).flatMap(cache -> cache.get(new ResourceID(n, namespace)))
.orElseGet(() -> client.secrets().inNamespace(namespace).withName(n).require()))
.orElseGet(() -> client.secrets().inNamespace(namespace).withName(n).get()))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.fabric8.kubernetes.api.model.apps.StatefulSet;
import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder;
import io.fabric8.kubernetes.api.model.apps.StatefulSetSpecBuilder;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.quarkus.logging.Log;
import io.quarkus.test.junit.QuarkusTest;

Expand Down Expand Up @@ -94,6 +95,26 @@ public void testBasicKeycloakDeploymentAndDeletion() {
.untilAsserted(() -> assertThat(k8sclient.apps().statefulSets().inNamespace(namespace).withName(deploymentName).get()).isNull());
}

@Test
public void testKeycloakDeploymentBeforeSecret() {
// CR
var kc = getTestKeycloakDeployment(true);
var deploymentName = kc.getMetadata().getName();
deployKeycloak(k8sclient, kc, false, false);

// Check Operator has deployed Keycloak and the statefulset exists, this allows for the watched secret to be picked up
Log.info("Checking Operator has deployed Keycloak deployment");
Resource<StatefulSet> stsResource = k8sclient.resources(StatefulSet.class).withName(deploymentName);
Resource<Keycloak> keycloakResource = k8sclient.resources(Keycloak.class).withName(deploymentName);
// expect no errors and not ready, which means we'll keep reconciling
Awaitility.await().untilAsserted(() -> {
assertThat(stsResource.get()).isNotNull();
Keycloak keycloak = keycloakResource.get();
CRAssert.assertKeycloakStatusCondition(keycloak, KeycloakStatusCondition.HAS_ERRORS, false);
CRAssert.assertKeycloakStatusCondition(keycloak, KeycloakStatusCondition.READY, false);
});
}

@Test
public void testCRFields() {
var kc = getTestKeycloakDeployment(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ public void testSecretChangesArePropagated() {
var kc = getTestKeycloakDeployment(false);
deployKeycloak(k8sclient, kc, true);

var prevRevision = getStatefulSet(kc).getStatus().getUpdateRevision();

var dbSecret = getDbSecret();

dbSecret.getData().put("username",
Expand Down