fix: limiting what fields are hashed to identify compatible update jobs (#42623)

closes: #41014

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins 2025-09-22 13:03:06 -04:00 committed by GitHub
parent 2015e08e38
commit e789e3213f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 60 additions and 4 deletions

View File

@ -103,7 +103,7 @@ jobs:
run: |
SEP=""
PROJECTS=""
for i in `find -name '*Test.java' -type f | egrep -v './(testsuite|quarkus|docs|tests|test-framework)/' | sed 's|/src/test/java/.*||' | sort | uniq | sed 's|./||'`; do
for i in `find -name '*Test.java' -type f | egrep -v './(operator|testsuite|quarkus|docs|tests|test-framework)/' | sed 's|/src/test/java/.*||' | sort | uniq | sed 's|./||'`; do
PROJECTS="$PROJECTS$SEP$i"
SEP=","
done

View File

@ -30,8 +30,9 @@ public class KeycloakServiceMonitorDependentResource extends CRUDKubernetesDepen
public boolean isMet(DependentResource<Ingress, Keycloak> dependentResource, Keycloak primary,
Context<Keycloak> context) {
var opts = configuredOptions(primary);
if (Boolean.parseBoolean(opts.get(LEGACY_MANAGEMENT_ENABLED)) || !Boolean.parseBoolean(opts.getOrDefault(METRICS_ENABLED, "false")))
if (Boolean.parseBoolean(opts.get(LEGACY_MANAGEMENT_ENABLED)) || !Boolean.parseBoolean(opts.getOrDefault(METRICS_ENABLED, "false"))) {
return false;
}
return ServiceMonitorSpec.get(primary).isEnabled();
}
@ -46,6 +47,7 @@ public class KeycloakServiceMonitorDependentResource extends CRUDKubernetesDepen
.withNewMetadata()
.withName(meta.getName())
.withNamespace(meta.getNamespace())
.withLabels(Utils.allInstanceLabels(primary))
.endMetadata()
.withNewSpec()
.withNewNamespaceSelector()

View File

@ -32,6 +32,7 @@ import org.keycloak.operator.ContextUtils;
import org.keycloak.operator.Utils;
import org.keycloak.operator.crds.v2alpha1.CRDUtils;
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakSpecBuilder;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.UpdateSpec;
import io.fabric8.kubernetes.api.model.ContainerFluent;
@ -218,8 +219,12 @@ public class KeycloakUpdateJobDependentResource extends CRUDKubernetesDependentR
return Stream.concat(updateArgs.stream(), currentArgs.stream().filter(arg -> !arg.equals("start"))).toList();
}
private static String keycloakHash(Keycloak keycloak) {
return Utils.hash(List.of(keycloak.getSpec()));
static String keycloakHash(Keycloak keycloak) {
return Utils.hash(
List.of(new KeycloakSpecBuilder(keycloak.getSpec()).withInstances(null).withLivenessProbeSpec(null)
.withStartupProbeSpec(null).withReadinessProbeSpec(null).withResourceRequirements(null)
.withSchedulingSpec(null).withNetworkPolicySpec(null).withIngressSpec(null)
.withImagePullSecrets().withImportSpec(null).withServiceMonitorSpec(null).build()));
}
private static Map<String, String> getLabels(HasMetadata keycloak) {

View File

@ -0,0 +1,49 @@
/*
* Copyright 2025 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.operator.controllers;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import org.junit.jupiter.api.Test;
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakBuilder;
public class KeycloakUpdateJobDependentResourceTest {
@Test
void testKeycloakHashConsistency() {
Keycloak keycloak = new KeycloakBuilder().withNewSpec().withInstances(2).endSpec().build();
String hash1 = KeycloakUpdateJobDependentResource.keycloakHash(keycloak);
String hash2 = KeycloakUpdateJobDependentResource.keycloakHash(new KeycloakBuilder(keycloak).editSpec().withInstances(1).endSpec().build());
assertEquals(hash1, hash2, "Hashes should be equal for identical specs");
}
@Test
void testKeycloakHashDifference() {
Keycloak keycloak = new KeycloakBuilder().withNewSpec().withInstances(2).endSpec().build();
String hash1 = KeycloakUpdateJobDependentResource.keycloakHash(keycloak);
String hash2 = KeycloakUpdateJobDependentResource.keycloakHash(new KeycloakBuilder(keycloak).editSpec().withNewFeatureSpec().withEnabledFeatures("new-feature").endFeatureSpec().withInstances(1).endSpec().build());
assertNotEquals(hash1, hash2, "Hashes should be different");
}
}