mostly updating the logic to newer fabric8 apis (#20825)

Closes #20822
This commit is contained in:
Steven Hawkins 2023-06-07 08:58:39 -04:00 committed by GitHub
parent 3b2dea64ac
commit d77041f177
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 90 additions and 69 deletions

View file

@ -119,7 +119,7 @@ public class KeycloakIngress extends OperatorManagedResource implements StatusUp
} }
protected void deleteExistingIngress() { protected void deleteExistingIngress() {
client.network().v1().ingresses().inNamespace(getNamespace()).delete(existingIngress); client.resource(existingIngress).delete();
} }
private boolean isExistingIngressFromSameOwnerReference() { private boolean isExistingIngressFromSameOwnerReference() {

View file

@ -54,6 +54,10 @@ public abstract class OperatorManagedResource {
setOwnerReferences(resource); setOwnerReferences(resource);
Log.debugf("Creating or updating resource: %s", resource); Log.debugf("Creating or updating resource: %s", resource);
// Until https://github.com/fabric8io/kubernetes-client/issues/5215 is resolved
// or event filtering is added, serverSideApply should not be used here
// resource.getMetadata().setResourceVersion(null);
// resource = client.resource(resource).inNamespace(getNamespace()).forceConflicts().serverSideApply();
resource = client.resource(resource).inNamespace(getNamespace()).createOrReplace(); resource = client.resource(resource).inNamespace(getNamespace()).createOrReplace();
Log.debugf("Successfully created or updated resource: %s", resource); Log.debugf("Successfully created or updated resource: %s", resource);
} catch (Exception e) { } catch (Exception e) {

View file

@ -166,13 +166,7 @@ public class WatchedSecretsStore extends OperatorManagedResource {
private Set<Secret> fetchCurrentSecrets(Set<String> secretsNames) { private Set<Secret> fetchCurrentSecrets(Set<String> secretsNames) {
return secretsNames.stream() return secretsNames.stream()
.map(n -> { .map(n -> client.secrets().inNamespace(getNamespace()).withName(n).require())
Secret secret = client.secrets().inNamespace(getNamespace()).withName(n).get();
if (secret == null) {
throw new IllegalStateException("Secret " + n + " not found");
}
return secret;
})
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }

View file

@ -16,10 +16,12 @@
*/ */
package org.keycloak.operator.crds.v2alpha1.deployment; package org.keycloak.operator.crds.v2alpha1.deployment;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.fabric8.kubernetes.api.model.LocalObjectReference; import io.fabric8.kubernetes.api.model.LocalObjectReference;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.DatabaseSpec; import org.keycloak.operator.crds.v2alpha1.deployment.spec.DatabaseSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.FeatureSpec; import org.keycloak.operator.crds.v2alpha1.deployment.spec.FeatureSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec; import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec;
@ -31,6 +33,7 @@ import org.keycloak.operator.crds.v2alpha1.deployment.spec.HostnameSpec;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class KeycloakSpec { public class KeycloakSpec {
@JsonPropertyDescription("Number of Keycloak instances in HA mode. Default is 1.") @JsonPropertyDescription("Number of Keycloak instances in HA mode. Default is 1.")

View file

@ -21,9 +21,12 @@ import io.fabric8.kubernetes.api.model.SecretKeySelector;
import java.util.Objects; import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonInclude;
/** /**
* @author Vaclav Muzikar <vmuzikar@redhat.com> * @author Vaclav Muzikar <vmuzikar@redhat.com>
*/ */
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ValueOrSecret { public class ValueOrSecret {
private String name; private String name;
private String value; private String value;

View file

@ -17,11 +17,13 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec; package org.keycloak.operator.crds.v2alpha1.deployment.spec;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.fabric8.kubernetes.api.model.SecretKeySelector; import io.fabric8.kubernetes.api.model.SecretKeySelector;
import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.Buildable;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") @Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
public class DatabaseSpec { public class DatabaseSpec {

View file

@ -17,6 +17,7 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec; package org.keycloak.operator.crds.v2alpha1.deployment.spec;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@ -25,6 +26,7 @@ import io.sundr.builder.annotations.Buildable;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") @Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
@JsonPropertyOrder({"enabled", "disabled"}) @JsonPropertyOrder({"enabled", "disabled"})
public class FeatureSpec implements Serializable { public class FeatureSpec implements Serializable {

View file

@ -17,11 +17,13 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec; package org.keycloak.operator.crds.v2alpha1.deployment.spec;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.Buildable;
import java.io.Serializable; import java.io.Serializable;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") @Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
public class HostnameSpec implements Serializable { public class HostnameSpec implements Serializable {

View file

@ -17,6 +17,7 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec; package org.keycloak.operator.crds.v2alpha1.deployment.spec;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.Buildable;
import org.keycloak.operator.Constants; import org.keycloak.operator.Constants;
@ -24,6 +25,7 @@ import org.keycloak.operator.Constants;
/** /**
* @author Vaclav Muzikar <vmuzikar@redhat.com> * @author Vaclav Muzikar <vmuzikar@redhat.com>
*/ */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") @Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
public class HttpSpec { public class HttpSpec {
@JsonPropertyDescription("A secret containing the TLS configuration for HTTPS. Reference: https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets.") @JsonPropertyDescription("A secret containing the TLS configuration for HTTPS. Reference: https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets.")

View file

@ -17,12 +17,14 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec; package org.keycloak.operator.crds.v2alpha1.deployment.spec;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.Buildable;
import java.util.Map; import java.util.Map;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") @Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
public class IngressSpec { public class IngressSpec {

View file

@ -17,11 +17,13 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec; package org.keycloak.operator.crds.v2alpha1.deployment.spec;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.Buildable;
import java.io.Serializable; import java.io.Serializable;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder") @Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
public class TransactionsSpec implements Serializable { public class TransactionsSpec implements Serializable {

View file

@ -17,11 +17,13 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec; package org.keycloak.operator.crds.v2alpha1.deployment.spec;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.fabric8.kubernetes.api.model.PodTemplateSpec; import io.fabric8.kubernetes.api.model.PodTemplateSpec;
import io.sundr.builder.annotations.Buildable; import io.sundr.builder.annotations.Buildable;
import io.sundr.builder.annotations.BuildableReference; import io.sundr.builder.annotations.BuildableReference;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder", @Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder",
lazyCollectionInitEnabled = false, refs = { lazyCollectionInitEnabled = false, refs = {
@BuildableReference(io.fabric8.kubernetes.api.model.ObjectMeta.class), @BuildableReference(io.fabric8.kubernetes.api.model.ObjectMeta.class),

View file

@ -22,8 +22,8 @@ import io.fabric8.kubernetes.api.model.NamespaceBuilder;
import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.javaoperatorsdk.operator.Operator; import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider; import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
@ -48,7 +48,6 @@ import java.io.FileNotFoundException;
import java.io.FileWriter; import java.io.FileWriter;
import java.time.Duration; import java.time.Duration;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.keycloak.operator.Utils.isOpenShift; import static org.keycloak.operator.Utils.isOpenShift;
@ -115,13 +114,13 @@ public abstract class BaseOperatorTest {
} }
private static void createK8sClient() { private static void createK8sClient() {
k8sclient = new DefaultKubernetesClient(new ConfigBuilder(Config.autoConfigure(null)).withNamespace(namespace).build()); k8sclient = new KubernetesClientBuilder().withConfig(new ConfigBuilder(Config.autoConfigure(null)).withNamespace(namespace).build()).build();
} }
private static void createRBACresourcesAndOperatorDeployment() throws FileNotFoundException { private static void createRBACresourcesAndOperatorDeployment() throws FileNotFoundException {
Log.info("Creating RBAC and Deployment into Namespace " + namespace); Log.info("Creating RBAC and Deployment into Namespace " + namespace);
k8sclient.load(new FileInputStream(TARGET_KUBERNETES_GENERATED_YML_FOLDER + deploymentTarget + ".yml")) k8sclient.load(new FileInputStream(TARGET_KUBERNETES_GENERATED_YML_FOLDER + deploymentTarget + ".yml"))
.inNamespace(namespace).createOrReplace(); .inNamespace(namespace).forceConflicts().serverSideApply();
} }
private static void cleanRBACresourcesAndOperatorDeployment() throws FileNotFoundException { private static void cleanRBACresourcesAndOperatorDeployment() throws FileNotFoundException {
@ -134,11 +133,9 @@ public abstract class BaseOperatorTest {
Log.info("Creating CRDs"); Log.info("Creating CRDs");
try { try {
var deploymentCRD = k8sclient.load(new FileInputStream(TARGET_KUBERNETES_GENERATED_YML_FOLDER + "keycloaks.k8s.keycloak.org-v1.yml")); var deploymentCRD = k8sclient.load(new FileInputStream(TARGET_KUBERNETES_GENERATED_YML_FOLDER + "keycloaks.k8s.keycloak.org-v1.yml"));
deploymentCRD.createOrReplace(); deploymentCRD.forceConflicts().serverSideApply();
deploymentCRD.waitUntilReady(5, TimeUnit.SECONDS);
var realmImportCRD = k8sclient.load(new FileInputStream(TARGET_KUBERNETES_GENERATED_YML_FOLDER + "keycloakrealmimports.k8s.keycloak.org-v1.yml")); var realmImportCRD = k8sclient.load(new FileInputStream(TARGET_KUBERNETES_GENERATED_YML_FOLDER + "keycloakrealmimports.k8s.keycloak.org-v1.yml"));
realmImportCRD.createOrReplace(); realmImportCRD.forceConflicts().serverSideApply();
realmImportCRD.waitUntilReady(5, TimeUnit.SECONDS);
} catch (Exception e) { } catch (Exception e) {
Log.warn("Failed to create Keycloak CRD, retrying", e); Log.warn("Failed to create Keycloak CRD, retrying", e);
createCRDs(); createCRDs();
@ -162,7 +159,7 @@ public abstract class BaseOperatorTest {
private static void createNamespace() { private static void createNamespace() {
Log.info("Creating Namespace " + namespace); Log.info("Creating Namespace " + namespace);
k8sclient.namespaces().create(new NamespaceBuilder().withNewMetadata().withName(namespace).endMetadata().build()); k8sclient.resource(new NamespaceBuilder().withNewMetadata().addToLabels("app","keycloak-test").withName(namespace).endMetadata().build()).create();
} }
private static void calculateNamespace() { private static void calculateNamespace() {
@ -172,7 +169,7 @@ public abstract class BaseOperatorTest {
protected static void deployDB() { protected static void deployDB() {
// DB // DB
Log.info("Creating new PostgreSQL deployment"); Log.info("Creating new PostgreSQL deployment");
k8sclient.load(BaseOperatorTest.class.getResourceAsStream("/example-postgres.yaml")).inNamespace(namespace).createOrReplace(); k8sclient.load(BaseOperatorTest.class.getResourceAsStream("/example-postgres.yaml")).inNamespace(namespace).forceConflicts().serverSideApply();
// Check DB has deployed and ready // Check DB has deployed and ready
Log.info("Checking Postgres is running"); Log.info("Checking Postgres is running");
@ -183,7 +180,7 @@ public abstract class BaseOperatorTest {
} }
protected static void deployDBSecret() { protected static void deployDBSecret() {
k8sclient.secrets().inNamespace(namespace).createOrReplace(getResourceFromFile("example-db-secret.yaml", Secret.class)); k8sclient.resource(getResourceFromFile("example-db-secret.yaml", Secret.class)).inNamespace(namespace).forceConflicts().serverSideApply();
} }
protected static void deleteDB() { protected static void deleteDB() {

View file

@ -55,11 +55,11 @@ public class ClusteringTest extends BaseOperatorTest {
var kcPodsSelector = k8sclient.pods().inNamespace(namespace).withLabel("app", "keycloak"); var kcPodsSelector = k8sclient.pods().inNamespace(namespace).withLabel("app", "keycloak");
Keycloak keycloak = crSelector.get();
// when scale it to 3 // when scale it to 3
crSelector.accept(keycloak -> {
keycloak.getMetadata().setResourceVersion(null);
keycloak.getSpec().setInstances(3); keycloak.getSpec().setInstances(3);
k8sclient.resources(Keycloak.class).inNamespace(namespace).createOrReplace(keycloak); });
Awaitility.await() Awaitility.await()
.atMost(1, MINUTES) .atMost(1, MINUTES)
@ -73,8 +73,10 @@ public class ClusteringTest extends BaseOperatorTest {
.untilAsserted(() -> assertThat(kcPodsSelector.list().getItems().size()).isEqualTo(3)); .untilAsserted(() -> assertThat(kcPodsSelector.list().getItems().size()).isEqualTo(3));
// when scale it down to 2 // when scale it down to 2
crSelector.accept(keycloak -> {
keycloak.getMetadata().setResourceVersion(null);
keycloak.getSpec().setInstances(2); keycloak.getSpec().setInstances(2);
k8sclient.resources(Keycloak.class).inNamespace(namespace).createOrReplace(keycloak); });
Awaitility.await() Awaitility.await()
.atMost(Duration.ofSeconds(180)) .atMost(Duration.ofSeconds(180))
.ignoreExceptions() .ignoreExceptions()
@ -119,11 +121,13 @@ public class ClusteringTest extends BaseOperatorTest {
.withName(kc.getMetadata().getName()); .withName(kc.getMetadata().getName());
K8sUtils.deployKeycloak(k8sclient, kc, false); K8sUtils.deployKeycloak(k8sclient, kc, false);
var targetInstances = 3; var targetInstances = 3;
kc.getSpec().setInstances(targetInstances); crSelector.accept(keycloak -> {
k8sclient.resources(Keycloak.class).inNamespace(namespace).createOrReplace(kc); keycloak.getMetadata().setResourceVersion(null);
var realm = k8sclient.resources(KeycloakRealmImport.class).inNamespace(namespace).load(getClass().getResourceAsStream("/token-test-realm.yaml")); keycloak.getSpec().setInstances(targetInstances);
});
var realm = k8sclient.load(getClass().getResourceAsStream("/token-test-realm.yaml")).inNamespace(namespace);
var realmImportSelector = k8sclient.resources(KeycloakRealmImport.class).inNamespace(namespace).withName("example-token-test-kc"); var realmImportSelector = k8sclient.resources(KeycloakRealmImport.class).inNamespace(namespace).withName("example-token-test-kc");
realm.createOrReplace(); realm.forceConflicts().serverSideApply();
Log.info("Waiting for a stable Keycloak Cluster"); Log.info("Waiting for a stable Keycloak Cluster");
Awaitility.await() Awaitility.await()

View file

@ -81,7 +81,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
// Delete CR // Delete CR
Log.info("Deleting Keycloak CR and watching cleanup"); Log.info("Deleting Keycloak CR and watching cleanup");
k8sclient.resources(Keycloak.class).delete(kc); k8sclient.resource(kc).delete();
Awaitility.await() Awaitility.await()
.untilAsserted(() -> assertThat(k8sclient.apps().statefulSets().inNamespace(namespace).withName(deploymentName).get()).isNull()); .untilAsserted(() -> assertThat(k8sclient.apps().statefulSets().inNamespace(namespace).withName(deploymentName).get()).isNull());
} catch (Exception e) { } catch (Exception e) {
@ -217,7 +217,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
deployment.getMetadata().getLabels().putAll(labels); deployment.getMetadata().getLabels().putAll(labels);
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(List.of(flandersEnvVar)); deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(List.of(flandersEnvVar));
k8sclient.apps().statefulSets().createOrReplace(deployment); k8sclient.resource(deployment).forceConflicts().serverSideApply();
Awaitility.await() Awaitility.await()
.atMost(5, MINUTES) .atMost(5, MINUTES)
@ -556,7 +556,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
.endMetadata() .endMetadata()
.addToStringData(keyName, "/barfoo") .addToStringData(keyName, "/barfoo")
.build(); .build();
k8sclient.secrets().inNamespace(namespace).createOrReplace(httpRelativePathSecret); k8sclient.resource(httpRelativePathSecret).forceConflicts().serverSideApply();
kc.getSpec().getAdditionalOptions().add(new ValueOrSecret(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY, kc.getSpec().getAdditionalOptions().add(new ValueOrSecret(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY,
new SecretKeySelectorBuilder() new SecretKeySelectorBuilder()
@ -651,7 +651,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
String secretDescriptorFilename) { String secretDescriptorFilename) {
Secret imagePullSecret = getResourceFromFile(secretDescriptorFilename, Secret.class); Secret imagePullSecret = getResourceFromFile(secretDescriptorFilename, Secret.class);
k8sclient.secrets().inNamespace(namespace).createOrReplace(imagePullSecret); k8sclient.resource(imagePullSecret).inNamespace(namespace).forceConflicts().serverSideApply();
LocalObjectReference localObjRefAsSecretTmp = new LocalObjectReferenceBuilder().withName(imagePullSecret.getMetadata().getName()).build(); LocalObjectReference localObjRefAsSecretTmp = new LocalObjectReferenceBuilder().withName(imagePullSecret.getMetadata().getName()).build();
keycloakCR.getSpec().setImagePullSecrets(Collections.singletonList(localObjRefAsSecretTmp)); keycloakCR.getSpec().setImagePullSecrets(Collections.singletonList(localObjRefAsSecretTmp));
} }

View file

@ -193,14 +193,14 @@ public class KeycloakIngressTest extends BaseOperatorTest {
Log.info("Trying to modify the ingress"); Log.info("Trying to modify the ingress");
var currentIngress = ingressSelector.get();
var labels = Map.of("address", "EvergreenTerrace742"); var labels = Map.of("address", "EvergreenTerrace742");
ingressSelector.accept(currentIngress -> {
currentIngress.getMetadata().setResourceVersion(null);
currentIngress.getSpec().getDefaultBackend().getService().setPort(new ServiceBackendPortBuilder().withName("foo").build()); currentIngress.getSpec().getDefaultBackend().getService().setPort(new ServiceBackendPortBuilder().withName("foo").build());
currentIngress.getMetadata().getAnnotations().clear(); currentIngress.getMetadata().getAnnotations().clear();
currentIngress.getMetadata().getLabels().putAll(labels); currentIngress.getMetadata().getLabels().putAll(labels);
});
ingressSelector.createOrReplace(currentIngress);
Awaitility.await() Awaitility.await()
.ignoreExceptions() .ignoreExceptions()
@ -396,7 +396,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
.endSpec() .endSpec()
.build(); .build();
customIngressCreated = k8sclient.network().v1().ingresses().inNamespace(targetNamespace).create(customIngressCreated); customIngressCreated = k8sclient.resource(customIngressCreated).create();
return customIngressCreated; return customIngressCreated;
} }

View file

@ -58,7 +58,8 @@ public class KeycloakServicesTest extends BaseOperatorTest {
currentService.getMetadata().getLabels().putAll(labels); currentService.getMetadata().getLabels().putAll(labels);
currentService.getSpec().setSessionAffinity("ClientIP"); currentService.getSpec().setSessionAffinity("ClientIP");
serviceSelector.createOrReplace(currentService); currentService.getMetadata().setResourceVersion(null);
k8sclient.resource(currentService).forceConflicts().serverSideApply();
Awaitility.await() Awaitility.await()
.untilAsserted(() -> { .untilAsserted(() -> {
@ -97,7 +98,7 @@ public class KeycloakServicesTest extends BaseOperatorTest {
currentDiscoveryService.getMetadata().getLabels().putAll(labels); currentDiscoveryService.getMetadata().getLabels().putAll(labels);
currentDiscoveryService.getSpec().setSessionAffinity("ClientIP"); currentDiscoveryService.getSpec().setSessionAffinity("ClientIP");
discoveryServiceSelector.createOrReplace(currentDiscoveryService); discoveryServiceSelector.edit(ignored -> currentDiscoveryService);
Awaitility.await() Awaitility.await()
.untilAsserted(() -> { .untilAsserted(() -> {

View file

@ -58,7 +58,7 @@ public class PodTemplateTest extends BaseOperatorTest {
.load(getClass().getResourceAsStream("/correct-podtemplate-keycloak.yml")); .load(getClass().getResourceAsStream("/correct-podtemplate-keycloak.yml"));
// Act // Act
keycloakWithPodTemplate.createOrReplace(); keycloakWithPodTemplate.forceConflicts().serverSideApply();
// Assert // Assert
Awaitility Awaitility
@ -99,7 +99,7 @@ public class PodTemplateTest extends BaseOperatorTest {
plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate); plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate);
// Act // Act
k8sclient.resource(plainKc).createOrReplace(); k8sclient.resource(plainKc).forceConflicts().serverSideApply();
// Assert // Assert
Log.info("Getting status of Keycloak"); Log.info("Getting status of Keycloak");
@ -123,7 +123,7 @@ public class PodTemplateTest extends BaseOperatorTest {
plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate); plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate);
// Act // Act
k8sclient.resource(plainKc).createOrReplace(); k8sclient.resource(plainKc).forceConflicts().serverSideApply();
// Assert // Assert
Log.info("Getting status of Keycloak"); Log.info("Getting status of Keycloak");
@ -149,7 +149,7 @@ public class PodTemplateTest extends BaseOperatorTest {
plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate); plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate);
// Act // Act
k8sclient.resource(plainKc).createOrReplace(); k8sclient.resource(plainKc).forceConflicts().serverSideApply();
// Assert // Assert
Log.info("Getting status of Keycloak"); Log.info("Getting status of Keycloak");
@ -175,7 +175,7 @@ public class PodTemplateTest extends BaseOperatorTest {
plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate); plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate);
// Act // Act
k8sclient.resource(plainKc).createOrReplace(); k8sclient.resource(plainKc).forceConflicts().serverSideApply();
// Assert // Assert
Log.info("Getting status of Keycloak"); Log.info("Getting status of Keycloak");
@ -193,7 +193,7 @@ public class PodTemplateTest extends BaseOperatorTest {
String secretDescriptorFilename = "test-docker-registry-secret.yaml"; String secretDescriptorFilename = "test-docker-registry-secret.yaml";
Secret imagePullSecret = getResourceFromFile(secretDescriptorFilename, Secret.class); Secret imagePullSecret = getResourceFromFile(secretDescriptorFilename, Secret.class);
k8sclient.secrets().inNamespace(namespace).createOrReplace(imagePullSecret); k8sclient.resource(imagePullSecret).inNamespace(namespace).forceConflicts().serverSideApply();
LocalObjectReference localObjRefAsSecretTmp = new LocalObjectReferenceBuilder().withName(imagePullSecret.getMetadata().getName()).build(); LocalObjectReference localObjRefAsSecretTmp = new LocalObjectReferenceBuilder().withName(imagePullSecret.getMetadata().getName()).build();
assertThat(localObjRefAsSecretTmp.getName()).isNotNull(); assertThat(localObjRefAsSecretTmp.getName()).isNotNull();
@ -209,7 +209,7 @@ public class PodTemplateTest extends BaseOperatorTest {
plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate); plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate);
// Act // Act
k8sclient.resource(plainKc).createOrReplace(); k8sclient.resource(plainKc).forceConflicts().serverSideApply();
// Assert // Assert
Log.info("Getting status of Keycloak"); Log.info("Getting status of Keycloak");

View file

@ -90,7 +90,7 @@ public class RealmImportTest extends BaseOperatorTest {
deployKeycloak(k8sclient, kc, false); deployKeycloak(k8sclient, kc, false);
// Act // Act
k8sclient.load(getClass().getResourceAsStream("/example-realm.yaml")).inNamespace(namespace).createOrReplace(); k8sclient.load(getClass().getResourceAsStream("/example-realm.yaml")).inNamespace(namespace).forceConflicts().serverSideApply();
// Assert // Assert
var crSelector = k8sclient var crSelector = k8sclient
@ -151,7 +151,7 @@ public class RealmImportTest extends BaseOperatorTest {
deployKeycloak(k8sclient, keycloak, false); deployKeycloak(k8sclient, keycloak, false);
// Act // Act
k8sclient.load(getClass().getResourceAsStream("/example-realm.yaml")).inNamespace(namespace).createOrReplace(); k8sclient.load(getClass().getResourceAsStream("/example-realm.yaml")).inNamespace(namespace).forceConflicts().serverSideApply();
// Assert // Assert
var crSelector = k8sclient var crSelector = k8sclient
@ -178,7 +178,7 @@ public class RealmImportTest extends BaseOperatorTest {
deployKeycloak(k8sclient, getDefaultKeycloakDeployment(), true); // make sure there are no errors due to missing KC Deployment deployKeycloak(k8sclient, getDefaultKeycloakDeployment(), true); // make sure there are no errors due to missing KC Deployment
// Act // Act
k8sclient.load(getClass().getResourceAsStream("/incorrect-realm.yaml")).inNamespace(namespace).createOrReplace(); k8sclient.load(getClass().getResourceAsStream("/incorrect-realm.yaml")).inNamespace(namespace).forceConflicts().serverSideApply();
// Assert // Assert
Awaitility.await() Awaitility.await()

View file

@ -18,6 +18,7 @@
package org.keycloak.operator.testsuite.integration; package org.keycloak.operator.testsuite.integration;
import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretBuilder;
import io.quarkus.logging.Log; import io.quarkus.logging.Log;
import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.QuarkusTest;
import org.awaitility.Awaitility; import org.awaitility.Awaitility;
@ -63,19 +64,19 @@ public class WatchedSecretsTest extends BaseOperatorTest {
Log.info("Updating DB Secret, expecting restart"); Log.info("Updating DB Secret, expecting restart");
testDeploymentRestarted(Set.of(kc), Set.of(), () -> { testDeploymentRestarted(Set.of(kc), Set.of(), () -> {
dbSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg="); dbSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg=");
k8sclient.secrets().createOrReplace(dbSecret); k8sclient.resource(dbSecret).forceConflicts().serverSideApply();
}); });
Log.info("Updating TLS Secret, expecting restart"); Log.info("Updating TLS Secret, expecting restart");
testDeploymentRestarted(Set.of(kc), Set.of(), () -> { testDeploymentRestarted(Set.of(kc), Set.of(), () -> {
tlsSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg="); tlsSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg=");
k8sclient.secrets().createOrReplace(tlsSecret); k8sclient.resource(tlsSecret).forceConflicts().serverSideApply();
}); });
Log.info("Updating DB Secret metadata, NOT expecting restart"); Log.info("Updating DB Secret metadata, NOT expecting restart");
testDeploymentRestarted(Set.of(), Set.of(kc), () -> { testDeploymentRestarted(Set.of(), Set.of(kc), () -> {
dbSecret.getMetadata().getLabels().put(UUID.randomUUID().toString(), "YmxhaGJsYWg"); dbSecret.getMetadata().getLabels().put(UUID.randomUUID().toString(), "YmxhaGJsYWg");
k8sclient.secrets().createOrReplace(dbSecret); k8sclient.resource(dbSecret).forceConflicts().serverSideApply();
}); });
} catch (Exception e) { } catch (Exception e) {
savePodLogs(); savePodLogs();
@ -97,7 +98,7 @@ public class WatchedSecretsTest extends BaseOperatorTest {
dbSecret.getData().put("username", dbSecret.getData().put("username",
Base64.getEncoder().encodeToString(username.getBytes())); Base64.getEncoder().encodeToString(username.getBytes()));
k8sclient.secrets().createOrReplace(dbSecret); k8sclient.resource(dbSecret).forceConflicts().serverSideApply();
Awaitility.await() Awaitility.await()
.ignoreExceptions() .ignoreExceptions()
@ -145,7 +146,7 @@ public class WatchedSecretsTest extends BaseOperatorTest {
testDeploymentRestarted(Set.of(), Set.of(kc), () -> { testDeploymentRestarted(Set.of(), Set.of(kc), () -> {
var dbSecret = getDbSecret(); var dbSecret = getDbSecret();
dbSecret.getMetadata().getLabels().put(UUID.randomUUID().toString(), "YmxhaGJsYWg"); dbSecret.getMetadata().getLabels().put(UUID.randomUUID().toString(), "YmxhaGJsYWg");
k8sclient.secrets().createOrReplace(dbSecret); k8sclient.resource(dbSecret).forceConflicts().serverSideApply();
}); });
Awaitility.await().untilAsserted(() -> { Awaitility.await().untilAsserted(() -> {
@ -179,7 +180,7 @@ public class WatchedSecretsTest extends BaseOperatorTest {
Log.info("Updating DB Secret, expecting restart of both KCs"); Log.info("Updating DB Secret, expecting restart of both KCs");
testDeploymentRestarted(Set.of(kc1, kc2), Set.of(), () -> { testDeploymentRestarted(Set.of(kc1, kc2), Set.of(), () -> {
dbSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg="); dbSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg=");
k8sclient.secrets().createOrReplace(dbSecret); k8sclient.resource(dbSecret).forceConflicts().serverSideApply();
}); });
Log.info("Updating KC1 to not to rely on DB Secret"); Log.info("Updating KC1 to not to rely on DB Secret");
@ -191,7 +192,7 @@ public class WatchedSecretsTest extends BaseOperatorTest {
Log.info("Updating DB Secret, expecting restart of just KC2"); Log.info("Updating DB Secret, expecting restart of just KC2");
testDeploymentRestarted(Set.of(kc2), Set.of(kc1), () -> { testDeploymentRestarted(Set.of(kc2), Set.of(kc1), () -> {
dbSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg="); dbSecret.getData().put(UUID.randomUUID().toString(), "YmxhaGJsYWg=");
k8sclient.secrets().createOrReplace(dbSecret); k8sclient.resource(dbSecret).forceConflicts().serverSideApply();
}); });
} }
catch (Exception e) { catch (Exception e) {
@ -264,11 +265,13 @@ public class WatchedSecretsTest extends BaseOperatorTest {
} }
private Secret getDbSecret() { private Secret getDbSecret() {
return k8sclient.secrets().inNamespace(namespace).withName("keycloak-db-secret").get(); return new SecretBuilder(k8sclient.secrets().inNamespace(namespace).withName("keycloak-db-secret").get())
.editMetadata().withResourceVersion(null).endMetadata().build();
} }
private Secret getTlsSecret() { private Secret getTlsSecret() {
return k8sclient.secrets().inNamespace(namespace).withName("example-tls-secret").get(); return new SecretBuilder(k8sclient.secrets().inNamespace(namespace).withName("example-tls-secret").get())
.editMetadata().withResourceVersion(null).endMetadata().build();
} }
private void hardcodeDBCredsInCR(Keycloak kc) { private void hardcodeDBCredsInCR(Keycloak kc) {

View file

@ -22,7 +22,6 @@ import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.extended.run.RunConfigBuilder;
import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil;
import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Serialization;
import io.quarkus.logging.Log; import io.quarkus.logging.Log;
@ -59,10 +58,10 @@ public final class K8sUtils {
} }
public static void deployKeycloak(KubernetesClient client, Keycloak kc, boolean waitUntilReady, boolean deployTlsSecret) { public static void deployKeycloak(KubernetesClient client, Keycloak kc, boolean waitUntilReady, boolean deployTlsSecret) {
client.resources(Keycloak.class).inNamespace(kc.getMetadata().getNamespace()).createOrReplace(kc); client.resource(kc).forceConflicts().serverSideApply();
if (deployTlsSecret) { if (deployTlsSecret) {
client.secrets().inNamespace(kc.getMetadata().getNamespace()).createOrReplace(getDefaultTlsSecret()); client.resource(getDefaultTlsSecret()).inNamespace(kc.getMetadata().getNamespace()).serverSideApply();
} }
if (waitUntilReady) { if (waitUntilReady) {
@ -100,12 +99,11 @@ public final class K8sUtils {
var podName = KubernetesResourceUtil.sanitizeName("curl-" + UUID.randomUUID()); var podName = KubernetesResourceUtil.sanitizeName("curl-" + UUID.randomUUID());
try { try {
Pod curlPod = k8sclient.run().inNamespace(namespace) Pod curlPod = k8sclient.run().inNamespace(namespace)
.withRunConfig(new RunConfigBuilder() .withNewRunConfig()
.withArgs(args) .withArgs(args)
.withName(podName) .withName(podName)
.withImage("curlimages/curl:7.78.0") .withImage("curlimages/curl:7.78.0")
.withRestartPolicy("Never") .withRestartPolicy("Never")
.build())
.done(); .done();
Log.info("Waiting for curl Pod to finish running"); Log.info("Waiting for curl Pod to finish running");
Awaitility.await().atMost(3, TimeUnit.MINUTES) Awaitility.await().atMost(3, TimeUnit.MINUTES)