converts the keycloak services to dependent resources (#22257)
Closes #22207
This commit is contained in:
parent
b4e876364a
commit
1d444ff862
10 changed files with 144 additions and 134 deletions
|
@ -41,6 +41,7 @@ import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatus;
|
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatus;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusAggregator;
|
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusAggregator;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -50,7 +51,9 @@ import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT
|
||||||
|
|
||||||
@ControllerConfiguration(namespaces = WATCH_CURRENT_NAMESPACE,
|
@ControllerConfiguration(namespaces = WATCH_CURRENT_NAMESPACE,
|
||||||
dependents = {
|
dependents = {
|
||||||
@Dependent(type = KeycloakAdminSecretDependentResource.class)
|
@Dependent(type = KeycloakAdminSecretDependentResource.class),
|
||||||
|
@Dependent(type = KeycloakServiceDependentResource.class, useEventSourceWithName = "serviceSource"),
|
||||||
|
@Dependent(type = KeycloakDiscoveryServiceDependentResource.class, useEventSourceWithName = "serviceSource")
|
||||||
})
|
})
|
||||||
public class KeycloakController implements Reconciler<Keycloak>, EventSourceInitializer<Keycloak>, ErrorStatusHandler<Keycloak> {
|
public class KeycloakController implements Reconciler<Keycloak>, EventSourceInitializer<Keycloak>, ErrorStatusHandler<Keycloak> {
|
||||||
|
|
||||||
|
@ -95,9 +98,11 @@ public class KeycloakController implements Reconciler<Keycloak>, EventSourceInit
|
||||||
EventSource servicesEvent = new InformerEventSource<>(servicesIC, context);
|
EventSource servicesEvent = new InformerEventSource<>(servicesIC, context);
|
||||||
EventSource ingressesEvent = new InformerEventSource<>(ingressesIC, context);
|
EventSource ingressesEvent = new InformerEventSource<>(ingressesIC, context);
|
||||||
|
|
||||||
return EventSourceInitializer.nameEventSources(statefulSetEvent,
|
Map<String, EventSource> sources = new HashMap<>();
|
||||||
servicesEvent,
|
sources.put("serviceSource", servicesEvent);
|
||||||
ingressesEvent, watchedSecrets.getWatchedSecretsEventSource());
|
sources.putAll(EventSourceInitializer.nameEventSources(statefulSetEvent,
|
||||||
|
ingressesEvent, watchedSecrets.getWatchedSecretsEventSource()));
|
||||||
|
return sources;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -121,11 +126,6 @@ public class KeycloakController implements Reconciler<Keycloak>, EventSourceInit
|
||||||
kcDeployment.createOrUpdateReconciled();
|
kcDeployment.createOrUpdateReconciled();
|
||||||
kcDeployment.updateStatus(statusAggregator);
|
kcDeployment.updateStatus(statusAggregator);
|
||||||
|
|
||||||
var kcService = new KeycloakService(client, kc);
|
|
||||||
kcService.createOrUpdateReconciled();
|
|
||||||
var kcDiscoveryService = new KeycloakDiscoveryService(client, kc);
|
|
||||||
kcDiscoveryService.createOrUpdateReconciled();
|
|
||||||
|
|
||||||
var kcIngress = new KeycloakIngress(client, kc);
|
var kcIngress = new KeycloakIngress(client, kc);
|
||||||
kcIngress.createOrUpdateReconciled();
|
kcIngress.createOrUpdateReconciled();
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ public class KeycloakDeployment extends OperatorManagedResource<StatefulSet> {
|
||||||
// probes
|
// probes
|
||||||
var tlsConfigured = isTlsConfigured(keycloakCR);
|
var tlsConfigured = isTlsConfigured(keycloakCR);
|
||||||
var protocol = !tlsConfigured ? "HTTP" : "HTTPS";
|
var protocol = !tlsConfigured ? "HTTP" : "HTTPS";
|
||||||
var kcPort = KeycloakService.getServicePort(keycloakCR);
|
var kcPort = KeycloakServiceDependentResource.getServicePort(keycloakCR);
|
||||||
|
|
||||||
// Relative path ends with '/'
|
// Relative path ends with '/'
|
||||||
var kcRelativePath = Optional.ofNullable(readConfigurationValue(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY))
|
var kcRelativePath = Optional.ofNullable(readConfigurationValue(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY))
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 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 io.fabric8.kubernetes.api.model.HasMetadata;
|
|
||||||
import io.fabric8.kubernetes.api.model.Service;
|
|
||||||
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
|
||||||
import io.fabric8.kubernetes.api.model.ServiceSpec;
|
|
||||||
import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
|
|
||||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
|
||||||
|
|
||||||
import org.keycloak.operator.Constants;
|
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class KeycloakDiscoveryService extends OperatorManagedResource {
|
|
||||||
|
|
||||||
public KeycloakDiscoveryService(KubernetesClient client, Keycloak keycloakCR) {
|
|
||||||
super(client, keycloakCR);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ServiceSpec getServiceSpec() {
|
|
||||||
return new ServiceSpecBuilder()
|
|
||||||
.addNewPort()
|
|
||||||
.withProtocol("TCP")
|
|
||||||
.withPort(Constants.KEYCLOAK_DISCOVERY_SERVICE_PORT)
|
|
||||||
.endPort()
|
|
||||||
.withSelector(getInstanceLabels())
|
|
||||||
.withClusterIP("None")
|
|
||||||
.withPublishNotReadyAddresses(Boolean.TRUE)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Optional<HasMetadata> getReconciledResource() {
|
|
||||||
return Optional.of(newService());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Service newService() {
|
|
||||||
Service service = new ServiceBuilder()
|
|
||||||
.withNewMetadata()
|
|
||||||
.withName(getName())
|
|
||||||
.withNamespace(getNamespace())
|
|
||||||
.endMetadata()
|
|
||||||
.withSpec(getServiceSpec())
|
|
||||||
.build();
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return cr.getMetadata().getName() + Constants.KEYCLOAK_DISCOVERY_SERVICE_SUFFIX;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 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 io.fabric8.kubernetes.api.model.Service;
|
||||||
|
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
||||||
|
import io.fabric8.kubernetes.api.model.ServiceSpec;
|
||||||
|
import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
|
||||||
|
import io.javaoperatorsdk.operator.api.reconciler.Context;
|
||||||
|
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
|
||||||
|
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
|
||||||
|
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
|
||||||
|
|
||||||
|
import org.keycloak.operator.Constants;
|
||||||
|
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@KubernetesDependent(labelSelector = Constants.DEFAULT_LABELS_AS_STRING, resourceDiscriminator = KeycloakDiscoveryServiceDependentResource.NameResourceDiscriminator.class)
|
||||||
|
public class KeycloakDiscoveryServiceDependentResource extends CRUDKubernetesDependentResource<Service, Keycloak> {
|
||||||
|
|
||||||
|
public static class NameResourceDiscriminator implements ResourceDiscriminator<Service, Keycloak> {
|
||||||
|
@Override
|
||||||
|
public Optional<Service> distinguish(Class<Service> resource, Keycloak primary, Context<Keycloak> context) {
|
||||||
|
return KeycloakServiceDependentResource.getService(KeycloakDiscoveryServiceDependentResource::getName, primary, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeycloakDiscoveryServiceDependentResource() {
|
||||||
|
super(Service.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServiceSpec getServiceSpec(Keycloak keycloak) {
|
||||||
|
return new ServiceSpecBuilder()
|
||||||
|
.addNewPort()
|
||||||
|
.withProtocol("TCP")
|
||||||
|
.withPort(Constants.KEYCLOAK_DISCOVERY_SERVICE_PORT)
|
||||||
|
.endPort()
|
||||||
|
.withSelector(OperatorManagedResource.allInstanceLabels(keycloak))
|
||||||
|
.withClusterIP("None")
|
||||||
|
.withPublishNotReadyAddresses(Boolean.TRUE)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Service desired(Keycloak primary, Context<Keycloak> context) {
|
||||||
|
Service service = new ServiceBuilder()
|
||||||
|
.withNewMetadata()
|
||||||
|
.withName(getName(primary))
|
||||||
|
.withNamespace(primary.getMetadata().getNamespace())
|
||||||
|
.addToLabels(OperatorManagedResource.allInstanceLabels(primary))
|
||||||
|
.endMetadata()
|
||||||
|
.withSpec(getServiceSpec(primary))
|
||||||
|
.build();
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getName(Keycloak keycloak) {
|
||||||
|
return keycloak.getMetadata().getName() + Constants.KEYCLOAK_DISCOVERY_SERVICE_SUFFIX;
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ public class KeycloakIngress extends OperatorManagedResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Ingress newIngress() {
|
private Ingress newIngress() {
|
||||||
var port = KeycloakService.getServicePort(keycloak);
|
var port = KeycloakServiceDependentResource.getServicePort(keycloak);
|
||||||
var annotations = new HashMap<String, String>();
|
var annotations = new HashMap<String, String>();
|
||||||
|
|
||||||
// set default annotations
|
// set default annotations
|
||||||
|
@ -80,7 +80,7 @@ public class KeycloakIngress extends OperatorManagedResource {
|
||||||
.withIngressClassName(optionalSpec.map(IngressSpec::getIngressClassName).orElse(null))
|
.withIngressClassName(optionalSpec.map(IngressSpec::getIngressClassName).orElse(null))
|
||||||
.withNewDefaultBackend()
|
.withNewDefaultBackend()
|
||||||
.withNewService()
|
.withNewService()
|
||||||
.withName(KeycloakService.getServiceName(keycloak))
|
.withName(KeycloakServiceDependentResource.getServiceName(keycloak))
|
||||||
.withNewPort()
|
.withNewPort()
|
||||||
.withNumber(port)
|
.withNumber(port)
|
||||||
.withName("") // for SSA to clear the name if already set
|
.withName("") // for SSA to clear the name if already set
|
||||||
|
@ -94,7 +94,7 @@ public class KeycloakIngress extends OperatorManagedResource {
|
||||||
.withPathType("ImplementationSpecific")
|
.withPathType("ImplementationSpecific")
|
||||||
.withNewBackend()
|
.withNewBackend()
|
||||||
.withNewService()
|
.withNewService()
|
||||||
.withName(KeycloakService.getServiceName(keycloak))
|
.withName(KeycloakServiceDependentResource.getServiceName(keycloak))
|
||||||
.withNewPort()
|
.withNewPort()
|
||||||
.withNumber(port)
|
.withNumber(port)
|
||||||
.withName("") // for SSA to clear the name if already set
|
.withName("") // for SSA to clear the name if already set
|
||||||
|
|
|
@ -21,26 +21,44 @@ import io.fabric8.kubernetes.api.model.Service;
|
||||||
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
||||||
import io.fabric8.kubernetes.api.model.ServiceSpec;
|
import io.fabric8.kubernetes.api.model.ServiceSpec;
|
||||||
import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
|
import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
|
||||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
import io.javaoperatorsdk.operator.api.reconciler.Context;
|
||||||
|
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
|
||||||
|
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
|
||||||
|
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
|
||||||
|
import io.javaoperatorsdk.operator.processing.event.ResourceID;
|
||||||
|
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
|
||||||
|
|
||||||
import org.keycloak.operator.Constants;
|
import org.keycloak.operator.Constants;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec;
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static org.keycloak.operator.crds.v2alpha1.CRDUtils.isTlsConfigured;
|
import static org.keycloak.operator.crds.v2alpha1.CRDUtils.isTlsConfigured;
|
||||||
|
|
||||||
public class KeycloakService extends OperatorManagedResource {
|
@KubernetesDependent(labelSelector = Constants.DEFAULT_LABELS_AS_STRING, resourceDiscriminator = KeycloakServiceDependentResource.NameResourceDiscriminator.class)
|
||||||
|
public class KeycloakServiceDependentResource extends CRUDKubernetesDependentResource<Service, Keycloak> {
|
||||||
|
|
||||||
private final Keycloak keycloak;
|
public static class NameResourceDiscriminator implements ResourceDiscriminator<Service, Keycloak> {
|
||||||
|
@Override
|
||||||
public KeycloakService(KubernetesClient client, Keycloak keycloakCR) {
|
public Optional<Service> distinguish(Class<Service> resource, Keycloak primary, Context<Keycloak> context) {
|
||||||
super(client, keycloakCR);
|
return getService(KeycloakServiceDependentResource::getServiceName, primary, context);
|
||||||
this.keycloak = keycloakCR;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceSpec getServiceSpec() {
|
public static Optional<Service> getService(Function<Keycloak, String> nameFunction, Keycloak primary, Context<Keycloak> context) {
|
||||||
|
InformerEventSource<Service, Keycloak> ies = (InformerEventSource<Service, Keycloak>) context
|
||||||
|
.eventSourceRetriever().getResourceEventSourceFor(Service.class);
|
||||||
|
|
||||||
|
return ies.get(new ResourceID(nameFunction.apply(primary), primary.getMetadata().getNamespace()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeycloakServiceDependentResource() {
|
||||||
|
super(Service.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServiceSpec getServiceSpec(Keycloak keycloak) {
|
||||||
String name = isTlsConfigured(keycloak) ? Constants.KEYCLOAK_HTTPS_PORT_NAME : Constants.KEYCLOAK_HTTP_PORT_NAME;
|
String name = isTlsConfigured(keycloak) ? Constants.KEYCLOAK_HTTPS_PORT_NAME : Constants.KEYCLOAK_HTTP_PORT_NAME;
|
||||||
return new ServiceSpecBuilder()
|
return new ServiceSpecBuilder()
|
||||||
.addNewPort()
|
.addNewPort()
|
||||||
|
@ -48,31 +66,23 @@ public class KeycloakService extends OperatorManagedResource {
|
||||||
.withName(name)
|
.withName(name)
|
||||||
.withProtocol(Constants.KEYCLOAK_SERVICE_PROTOCOL)
|
.withProtocol(Constants.KEYCLOAK_SERVICE_PROTOCOL)
|
||||||
.endPort()
|
.endPort()
|
||||||
.withSelector(getInstanceLabels())
|
.withSelector(OperatorManagedResource.allInstanceLabels(keycloak))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Optional<HasMetadata> getReconciledResource() {
|
protected Service desired(Keycloak primary, Context<Keycloak> context) {
|
||||||
return Optional.of(newService());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Service newService() {
|
|
||||||
Service service = new ServiceBuilder()
|
Service service = new ServiceBuilder()
|
||||||
.withNewMetadata()
|
.withNewMetadata()
|
||||||
.withName(getName())
|
.withName(getServiceName(primary))
|
||||||
.withNamespace(getNamespace())
|
.withNamespace(primary.getMetadata().getNamespace())
|
||||||
|
.addToLabels(OperatorManagedResource.allInstanceLabels(primary))
|
||||||
.endMetadata()
|
.endMetadata()
|
||||||
.withSpec(getServiceSpec())
|
.withSpec(getServiceSpec(primary))
|
||||||
.build();
|
.build();
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return getServiceName(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getServiceName(HasMetadata keycloak) {
|
public static String getServiceName(HasMetadata keycloak) {
|
||||||
return keycloak.getMetadata().getName() + Constants.KEYCLOAK_SERVICE_SUFFIX;
|
return keycloak.getMetadata().getName() + Constants.KEYCLOAK_SERVICE_SUFFIX;
|
||||||
}
|
}
|
|
@ -31,7 +31,7 @@ import io.restassured.RestAssured;
|
||||||
import org.awaitility.Awaitility;
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.keycloak.operator.Constants;
|
import org.keycloak.operator.Constants;
|
||||||
import org.keycloak.operator.controllers.KeycloakService;
|
import org.keycloak.operator.controllers.KeycloakServiceDependentResource;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusCondition;
|
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusCondition;
|
||||||
import org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImport;
|
import org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImport;
|
||||||
|
@ -172,8 +172,7 @@ public class ClusteringTest extends BaseOperatorTest {
|
||||||
.untilAsserted(() -> assertThat(crSelector.scale().getStatus().getReplicas()).isEqualTo(2));
|
.untilAsserted(() -> assertThat(crSelector.scale().getStatus().getReplicas()).isEqualTo(2));
|
||||||
|
|
||||||
// get the service
|
// get the service
|
||||||
var service = new KeycloakService(k8sclient, kc);
|
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT;
|
||||||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT;
|
|
||||||
|
|
||||||
Awaitility.await().atMost(5, MINUTES).untilAsserted(() -> {
|
Awaitility.await().atMost(5, MINUTES).untilAsserted(() -> {
|
||||||
Log.info("Starting curl Pod to test if the realm is available");
|
Log.info("Starting curl Pod to test if the realm is available");
|
||||||
|
@ -275,7 +274,7 @@ public class ClusteringTest extends BaseOperatorTest {
|
||||||
|
|
||||||
// This is to test passing through the "Service", not 100% deterministic, but a smoke test that things are working as expected
|
// This is to test passing through the "Service", not 100% deterministic, but a smoke test that things are working as expected
|
||||||
// Executed here to avoid paying the setup time again
|
// Executed here to avoid paying the setup time again
|
||||||
var service = new KeycloakService(k8sclient, kc);
|
String serviceName = KeycloakServiceDependentResource.getServiceName(kc);
|
||||||
Awaitility.await()
|
Awaitility.await()
|
||||||
.atMost(20, MINUTES)
|
.atMost(20, MINUTES)
|
||||||
.pollDelay(5, SECONDS)
|
.pollDelay(5, SECONDS)
|
||||||
|
@ -286,7 +285,7 @@ public class ClusteringTest extends BaseOperatorTest {
|
||||||
for (int i = 0; i < (targetInstances + 1); i++) {
|
for (int i = 0; i < (targetInstances + 1); i++) {
|
||||||
|
|
||||||
if (token2 == null) {
|
if (token2 == null) {
|
||||||
var tokenUrl = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/token-test/protocol/openid-connect/token";
|
var tokenUrl = "https://" + serviceName + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/token-test/protocol/openid-connect/token";
|
||||||
Log.info("Checking url: " + tokenUrl);
|
Log.info("Checking url: " + tokenUrl);
|
||||||
|
|
||||||
var tokenOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "--data", "grant_type=password&client_id=token-test-client&username=test&password=test&scope=openid", tokenUrl);
|
var tokenOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "--data", "grant_type=password&client_id=token-test-client&username=test&password=test&scope=openid", tokenUrl);
|
||||||
|
@ -296,7 +295,7 @@ public class ClusteringTest extends BaseOperatorTest {
|
||||||
token2 = tokenAnswer.get("access_token").asText();
|
token2 = tokenAnswer.get("access_token").asText();
|
||||||
}
|
}
|
||||||
|
|
||||||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/token-test/protocol/openid-connect/userinfo";
|
String url = "https://" + serviceName + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/token-test/protocol/openid-connect/userinfo";
|
||||||
Log.info("Checking url: " + url);
|
Log.info("Checking url: " + url);
|
||||||
|
|
||||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "-H", "Authorization: Bearer " + token2, url);
|
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "-H", "Authorization: Bearer " + token2, url);
|
||||||
|
|
|
@ -38,7 +38,7 @@ import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
|
||||||
import org.keycloak.operator.Constants;
|
import org.keycloak.operator.Constants;
|
||||||
import org.keycloak.operator.controllers.KeycloakAdminSecretDependentResource;
|
import org.keycloak.operator.controllers.KeycloakAdminSecretDependentResource;
|
||||||
import org.keycloak.operator.controllers.KeycloakDistConfigurator;
|
import org.keycloak.operator.controllers.KeycloakDistConfigurator;
|
||||||
import org.keycloak.operator.controllers.KeycloakService;
|
import org.keycloak.operator.controllers.KeycloakServiceDependentResource;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusCondition;
|
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusCondition;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret;
|
import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret;
|
||||||
|
@ -254,11 +254,10 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
var kc = getTestKeycloakDeployment(true);
|
var kc = getTestKeycloakDeployment(true);
|
||||||
deployKeycloak(k8sclient, kc, true);
|
deployKeycloak(k8sclient, kc, true);
|
||||||
|
|
||||||
var service = new KeycloakService(k8sclient, kc);
|
|
||||||
Awaitility.await()
|
Awaitility.await()
|
||||||
.ignoreExceptions()
|
.ignoreExceptions()
|
||||||
.untilAsserted(() -> {
|
.untilAsserted(() -> {
|
||||||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT;
|
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT;
|
||||||
Log.info("Checking url: " + url);
|
Log.info("Checking url: " + url);
|
||||||
|
|
||||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "-w", "%{certs}", url);
|
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "-w", "%{certs}", url);
|
||||||
|
@ -283,11 +282,10 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
var kc = getTestKeycloakDeployment(true);
|
var kc = getTestKeycloakDeployment(true);
|
||||||
deployKeycloak(k8sclient, kc, true);
|
deployKeycloak(k8sclient, kc, true);
|
||||||
|
|
||||||
var service = new KeycloakService(k8sclient, kc);
|
|
||||||
Awaitility.await()
|
Awaitility.await()
|
||||||
.ignoreExceptions()
|
.ignoreExceptions()
|
||||||
.untilAsserted(() -> {
|
.untilAsserted(() -> {
|
||||||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/admin/master/console/";
|
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/admin/master/console/";
|
||||||
Log.info("Checking url: " + url);
|
Log.info("Checking url: " + url);
|
||||||
|
|
||||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "-s", "--insecure", "-H", "Host: foo.bar", url);
|
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "-s", "--insecure", "-H", "Host: foo.bar", url);
|
||||||
|
@ -308,11 +306,10 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
|
|
||||||
deployKeycloak(k8sclient, kc, true);
|
deployKeycloak(k8sclient, kc, true);
|
||||||
|
|
||||||
var service = new KeycloakService(k8sclient, kc);
|
|
||||||
Awaitility.await()
|
Awaitility.await()
|
||||||
.ignoreExceptions()
|
.ignoreExceptions()
|
||||||
.untilAsserted(() -> {
|
.untilAsserted(() -> {
|
||||||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/admin/master/console/";
|
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/admin/master/console/";
|
||||||
Log.info("Checking url: " + url);
|
Log.info("Checking url: " + url);
|
||||||
|
|
||||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "-s", "--insecure", "-H", "Host: foo.bar", url);
|
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "-s", "--insecure", "-H", "Host: foo.bar", url);
|
||||||
|
@ -395,7 +392,6 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
deployDB();
|
deployDB();
|
||||||
deployKeycloak(k8sclient, kc, true);
|
deployKeycloak(k8sclient, kc, true);
|
||||||
var decoder = Base64.getDecoder();
|
var decoder = Base64.getDecoder();
|
||||||
var service = new KeycloakService(k8sclient, kc);
|
|
||||||
|
|
||||||
AtomicReference<String> adminUsername = new AtomicReference<>();
|
AtomicReference<String> adminUsername = new AtomicReference<>();
|
||||||
AtomicReference<String> adminPassword = new AtomicReference<>();
|
AtomicReference<String> adminPassword = new AtomicReference<>();
|
||||||
|
@ -412,7 +408,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
adminUsername.set(new String(decoder.decode(adminSecret.getData().get("username").getBytes(StandardCharsets.UTF_8))));
|
adminUsername.set(new String(decoder.decode(adminSecret.getData().get("username").getBytes(StandardCharsets.UTF_8))));
|
||||||
adminPassword.set(new String(decoder.decode(adminSecret.getData().get("password").getBytes(StandardCharsets.UTF_8))));
|
adminPassword.set(new String(decoder.decode(adminSecret.getData().get("password").getBytes(StandardCharsets.UTF_8))));
|
||||||
|
|
||||||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/master/protocol/openid-connect/token";
|
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/master/protocol/openid-connect/token";
|
||||||
Log.info("Checking url: " + url);
|
Log.info("Checking url: " + url);
|
||||||
|
|
||||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "--data", "grant_type=password&client_id=admin-cli&username=" + adminUsername.get() + "&password=" + adminPassword.get(), url);
|
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "--data", "grant_type=password&client_id=admin-cli&username=" + adminUsername.get() + "&password=" + adminPassword.get(), url);
|
||||||
|
@ -437,7 +433,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
|
|
||||||
var newPassword = new String(decoder.decode(adminSecret.getData().get("password").getBytes(StandardCharsets.UTF_8)));
|
var newPassword = new String(decoder.decode(adminSecret.getData().get("password").getBytes(StandardCharsets.UTF_8)));
|
||||||
|
|
||||||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/master/protocol/openid-connect/token";
|
String url = "https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT + "/realms/master/protocol/openid-connect/token";
|
||||||
Log.info("Checking url: " + url);
|
Log.info("Checking url: " + url);
|
||||||
|
|
||||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "--data", "grant_type=password&client_id=admin-cli&username=" + adminUsername.get() + "&password=" + adminPassword.get(), url);
|
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "--data", "grant_type=password&client_id=admin-cli&username=" + adminUsername.get() + "&password=" + adminPassword.get(), url);
|
||||||
|
@ -631,7 +627,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
||||||
.untilAsserted(() -> {
|
.untilAsserted(() -> {
|
||||||
String protocol = https ? "https" : "http";
|
String protocol = https ? "https" : "http";
|
||||||
|
|
||||||
String serviceName = KeycloakService.getServiceName(kc);
|
String serviceName = KeycloakServiceDependentResource.getServiceName(kc);
|
||||||
assertThat(k8sclient.resources(Service.class).withName(serviceName).require().getSpec().getPorts()
|
assertThat(k8sclient.resources(Service.class).withName(serviceName).require().getSpec().getPorts()
|
||||||
.stream().map(ServicePort::getName).anyMatch(protocol::equals));
|
.stream().map(ServicePort::getName).anyMatch(protocol::equals));
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,11 @@ package org.keycloak.operator.testsuite.integration;
|
||||||
import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
|
import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
|
||||||
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;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.keycloak.operator.controllers.KeycloakDiscoveryService;
|
import org.keycloak.operator.controllers.KeycloakDiscoveryServiceDependentResource;
|
||||||
import org.keycloak.operator.controllers.KeycloakService;
|
import org.keycloak.operator.controllers.KeycloakServiceDependentResource;
|
||||||
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -37,8 +38,8 @@ public class KeycloakServicesTest extends BaseOperatorTest {
|
||||||
public void testMainServiceDurability() {
|
public void testMainServiceDurability() {
|
||||||
var kc = getTestKeycloakDeployment(true);
|
var kc = getTestKeycloakDeployment(true);
|
||||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||||
var service = new KeycloakService(k8sclient, kc);
|
String serviceName = KeycloakServiceDependentResource.getServiceName(kc);
|
||||||
var serviceSelector = k8sclient.services().inNamespace(namespace).withName(service.getName());
|
var serviceSelector = k8sclient.services().inNamespace(namespace).withName(serviceName);
|
||||||
|
|
||||||
Log.info("Trying to delete the service");
|
Log.info("Trying to delete the service");
|
||||||
assertThat(serviceSelector.delete()).isNotNull();
|
assertThat(serviceSelector.delete()).isNotNull();
|
||||||
|
@ -61,7 +62,6 @@ public class KeycloakServicesTest extends BaseOperatorTest {
|
||||||
var origSpecs = new ServiceSpecBuilder(currentService.getSpec()).build(); // deep copy
|
var origSpecs = new ServiceSpecBuilder(currentService.getSpec()).build(); // deep copy
|
||||||
|
|
||||||
// a managed change
|
// a managed change
|
||||||
currentService.getSpec().getPorts().get(0).setProtocol("UDP");
|
|
||||||
currentService.getSpec().getPorts().get(0).setName(null);
|
currentService.getSpec().getPorts().get(0).setName(null);
|
||||||
|
|
||||||
currentService.getMetadata().getLabels().putAll(labels);
|
currentService.getMetadata().getLabels().putAll(labels);
|
||||||
|
@ -86,8 +86,7 @@ public class KeycloakServicesTest extends BaseOperatorTest {
|
||||||
public void testDiscoveryServiceDurability() {
|
public void testDiscoveryServiceDurability() {
|
||||||
var kc = getTestKeycloakDeployment(true);
|
var kc = getTestKeycloakDeployment(true);
|
||||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||||
var discoveryService = new KeycloakDiscoveryService(k8sclient, kc);
|
var discoveryServiceSelector = k8sclient.services().inNamespace(namespace).withName(KeycloakDiscoveryServiceDependentResource.getName(kc));
|
||||||
var discoveryServiceSelector = k8sclient.services().inNamespace(namespace).withName(discoveryService.getName());
|
|
||||||
|
|
||||||
Log.info("Trying to delete the discovery service");
|
Log.info("Trying to delete the discovery service");
|
||||||
assertThat(discoveryServiceSelector.delete()).isNotNull();
|
assertThat(discoveryServiceSelector.delete()).isNotNull();
|
||||||
|
@ -113,7 +112,7 @@ public class KeycloakServicesTest extends BaseOperatorTest {
|
||||||
var origDiscoverySpecs = new ServiceSpecBuilder(currentDiscoveryService.getSpec()).build(); // deep copy
|
var origDiscoverySpecs = new ServiceSpecBuilder(currentDiscoveryService.getSpec()).build(); // deep copy
|
||||||
|
|
||||||
// a managed change
|
// a managed change
|
||||||
currentDiscoveryService.getSpec().getPorts().get(0).setProtocol("UDP");
|
currentDiscoveryService.getSpec().getPorts().get(0).setName(null);
|
||||||
|
|
||||||
currentDiscoveryService.getMetadata().setResourceVersion(null);
|
currentDiscoveryService.getMetadata().setResourceVersion(null);
|
||||||
k8sclient.resource(currentDiscoveryService).update();
|
k8sclient.resource(currentDiscoveryService).update();
|
||||||
|
|
|
@ -26,10 +26,10 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestInfo;
|
import org.junit.jupiter.api.TestInfo;
|
||||||
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
|
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
|
||||||
|
import org.keycloak.operator.controllers.KeycloakServiceDependentResource;
|
||||||
|
import org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImport;
|
||||||
import org.keycloak.operator.testsuite.utils.CRAssert;
|
import org.keycloak.operator.testsuite.utils.CRAssert;
|
||||||
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
||||||
import org.keycloak.operator.controllers.KeycloakService;
|
|
||||||
import org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImport;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -39,11 +39,11 @@ import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.keycloak.operator.Constants.KEYCLOAK_HTTPS_PORT;
|
import static org.keycloak.operator.Constants.KEYCLOAK_HTTPS_PORT;
|
||||||
import static org.keycloak.operator.controllers.KeycloakDistConfigurator.getKeycloakOptionEnvVarName;
|
import static org.keycloak.operator.controllers.KeycloakDistConfigurator.getKeycloakOptionEnvVarName;
|
||||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.deployKeycloak;
|
|
||||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.inClusterCurl;
|
|
||||||
import static org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImportStatusCondition.DONE;
|
import static org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImportStatusCondition.DONE;
|
||||||
import static org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImportStatusCondition.HAS_ERRORS;
|
import static org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImportStatusCondition.HAS_ERRORS;
|
||||||
import static org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImportStatusCondition.STARTED;
|
import static org.keycloak.operator.crds.v2alpha1.realmimport.KeycloakRealmImportStatusCondition.STARTED;
|
||||||
|
import static org.keycloak.operator.testsuite.utils.K8sUtils.deployKeycloak;
|
||||||
|
import static org.keycloak.operator.testsuite.utils.K8sUtils.inClusterCurl;
|
||||||
|
|
||||||
@QuarkusTest
|
@QuarkusTest
|
||||||
public class RealmImportTest extends BaseOperatorTest {
|
public class RealmImportTest extends BaseOperatorTest {
|
||||||
|
@ -123,7 +123,7 @@ public class RealmImportTest extends BaseOperatorTest {
|
||||||
assertThat(job.getSpec().getTemplate().getSpec().getImagePullSecrets().get(0).getName()).isEqualTo("my-empty-secret");
|
assertThat(job.getSpec().getTemplate().getSpec().getImagePullSecrets().get(0).getName()).isEqualTo("my-empty-secret");
|
||||||
|
|
||||||
String url =
|
String url =
|
||||||
"https://" + KeycloakService.getServiceName(kc) + "." + namespace + ":" + KEYCLOAK_HTTPS_PORT + "/realms/count0";
|
"https://" + KeycloakServiceDependentResource.getServiceName(kc) + "." + namespace + ":" + KEYCLOAK_HTTPS_PORT + "/realms/count0";
|
||||||
|
|
||||||
Awaitility.await().atMost(10, MINUTES).ignoreExceptions().untilAsserted(() -> {
|
Awaitility.await().atMost(10, MINUTES).ignoreExceptions().untilAsserted(() -> {
|
||||||
Log.info("Starting curl Pod to test if the realm is available");
|
Log.info("Starting curl Pod to test if the realm is available");
|
||||||
|
|
Loading…
Reference in a new issue