Refine Ingress settings in Keycloak CR
Closes Keycloak#14407 Signed-off-by: Peter Zaoral <pzaoral@redhat.com>
This commit is contained in:
parent
76d9125c3f
commit
4dfbb42680
8 changed files with 102 additions and 34 deletions
|
@ -164,7 +164,7 @@ CONDITION: RollingUpdate
|
|||
=== Accessing the Keycloak Deployment
|
||||
|
||||
The Keycloak deployment is, by default, exposed through a basic nginx ingress and it will be accessible through the provided hostname.
|
||||
If the default ingress doesn't fit your use-case you can disable it by setting `disableDefaultIngress: true`:
|
||||
If the default ingress doesn't fit your use-case, disable it by setting `ingress` spec with `enabled` property to `false` value:
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
|
@ -175,7 +175,8 @@ metadata:
|
|||
name: example-kc
|
||||
spec:
|
||||
...
|
||||
disableDefaultIngress: true
|
||||
ingress:
|
||||
enabled: false
|
||||
EOF
|
||||
kubectl apply -f example-kc.yaml
|
||||
----
|
||||
|
|
|
@ -21,6 +21,7 @@ import io.fabric8.kubernetes.api.model.networking.v1.IngressBuilder;
|
|||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
|
||||
import org.keycloak.operator.Constants;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusBuilder;
|
||||
|
||||
|
@ -42,7 +43,8 @@ public class KeycloakIngress extends OperatorManagedResource implements StatusUp
|
|||
|
||||
@Override
|
||||
protected Optional<HasMetadata> getReconciledResource() {
|
||||
if (keycloak.getSpec().isDisableDefaultIngress()) {
|
||||
IngressSpec ingressSpec = keycloak.getSpec().getIngressSpec();
|
||||
if (ingressSpec != null && !ingressSpec.isIngressEnabled()) {
|
||||
if (existingIngress != null) {
|
||||
deleteExistingIngress();
|
||||
}
|
||||
|
@ -121,9 +123,13 @@ public class KeycloakIngress extends OperatorManagedResource implements StatusUp
|
|||
}
|
||||
|
||||
public void updateStatus(KeycloakStatusBuilder status) {
|
||||
if (!keycloak.getSpec().isDisableDefaultIngress() && existingIngress == null) {
|
||||
IngressSpec ingressSpec = keycloak.getSpec().getIngressSpec();
|
||||
if (ingressSpec == null) {
|
||||
ingressSpec = new IngressSpec();
|
||||
ingressSpec.setIngressEnabled(true);
|
||||
}
|
||||
if (ingressSpec.isIngressEnabled() && existingIngress == null) {
|
||||
status.addNotReadyMessage("No existing Keycloak Ingress found, waiting for creating a new one");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.keycloak.operator.Constants;
|
|||
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.UnsupportedSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TransactionsSpec;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
@ -54,14 +55,16 @@ public class KeycloakSpec {
|
|||
@JsonPropertyDescription("In this section you can configure Keycloak features related to HTTP and HTTPS")
|
||||
private HttpSpec httpSpec;
|
||||
|
||||
@JsonPropertyDescription("Disable the default ingress.")
|
||||
private boolean disableDefaultIngress;
|
||||
|
||||
@JsonPropertyDescription(
|
||||
"In this section you can configure podTemplate advanced features, not production-ready, and not supported settings.\n" +
|
||||
"Use at your own risk and open an issue with your use-case if you don't find an alternative way.")
|
||||
private UnsupportedSpec unsupported;
|
||||
|
||||
@JsonProperty("ingress")
|
||||
@JsonPropertyDescription("The deployment is, by default, exposed through a basic ingress.\n" +
|
||||
"You can change this behaviour by setting the enabled property to false.")
|
||||
private IngressSpec ingressSpec;
|
||||
|
||||
@JsonProperty("features")
|
||||
@JsonPropertyDescription("In this section you can configure Keycloak features, which should be enabled/disabled.")
|
||||
private FeatureSpec featureSpec;
|
||||
|
@ -91,14 +94,6 @@ public class KeycloakSpec {
|
|||
this.httpSpec = httpSpec;
|
||||
}
|
||||
|
||||
public void setDisableDefaultIngress(boolean value) {
|
||||
this.disableDefaultIngress = value;
|
||||
}
|
||||
|
||||
public boolean isDisableDefaultIngress() {
|
||||
return this.disableDefaultIngress;
|
||||
}
|
||||
|
||||
public UnsupportedSpec getUnsupported() {
|
||||
return unsupported;
|
||||
}
|
||||
|
@ -123,6 +118,14 @@ public class KeycloakSpec {
|
|||
this.transactionsSpec = transactionsSpec;
|
||||
}
|
||||
|
||||
public IngressSpec getIngressSpec() {
|
||||
return ingressSpec;
|
||||
}
|
||||
|
||||
public void setIngressSpec(IngressSpec ingressSpec) {
|
||||
this.ingressSpec = ingressSpec;
|
||||
}
|
||||
|
||||
public int getInstances() {
|
||||
return instances;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2022 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.crds.v2alpha1.deployment.spec;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.sundr.builder.annotations.Buildable;
|
||||
|
||||
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
|
||||
public class IngressSpec {
|
||||
|
||||
@JsonProperty("enabled")
|
||||
private boolean enabled = true;
|
||||
|
||||
public boolean isIngressEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setIngressEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import io.restassured.RestAssured;
|
|||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.operator.Constants;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
|
||||
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
||||
import org.keycloak.operator.controllers.KeycloakIngress;
|
||||
|
||||
|
@ -126,6 +127,8 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testMainIngressDurability() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
kc.getSpec().setIngressSpec(new IngressSpec());
|
||||
kc.getSpec().getIngressSpec().setIngressEnabled(true);
|
||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
var ingress = new KeycloakIngress(k8sclient, kc);
|
||||
|
@ -165,7 +168,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
});
|
||||
|
||||
// Delete the ingress
|
||||
kc.getSpec().setDisableDefaultIngress(true);
|
||||
kc.getSpec().getIngressSpec().setIngressEnabled(false);
|
||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
Awaitility.await()
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.List;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
public class CRSerializationTest {
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class CRSerializationTest {
|
|||
assertEquals("my-hostname", keycloak.getSpec().getHostname());
|
||||
assertEquals("my-image", keycloak.getSpec().getImage());
|
||||
assertEquals("my-tls-secret", keycloak.getSpec().getHttpSpec().getTlsSecret());
|
||||
assertTrue(keycloak.getSpec().isDisableDefaultIngress());
|
||||
assertFalse(keycloak.getSpec().getIngressSpec().isIngressEnabled());
|
||||
|
||||
final TransactionsSpec transactionsSpec = keycloak.getSpec().getTransactionsSpec();
|
||||
assertThat(transactionsSpec, notNullValue());
|
||||
|
|
|
@ -21,6 +21,7 @@ import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
|
|||
import io.fabric8.kubernetes.api.model.networking.v1.IngressBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.operator.controllers.KeycloakIngress;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
||||
|
||||
|
@ -31,21 +32,24 @@ public class IngressLogicTest {
|
|||
|
||||
static class MockKeycloakIngress extends KeycloakIngress {
|
||||
|
||||
private static Keycloak getKeycloak(boolean defaultIngressDisabled) {
|
||||
private static Keycloak getKeycloak(Boolean defaultIngressEnabled, boolean ingressSpecDefined) {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
kc.getSpec().setDisableDefaultIngress(defaultIngressDisabled);
|
||||
if (ingressSpecDefined) {
|
||||
kc.getSpec().setIngressSpec(new IngressSpec());
|
||||
if (defaultIngressEnabled != null) kc.getSpec().getIngressSpec().setIngressEnabled(defaultIngressEnabled);
|
||||
}
|
||||
return kc;
|
||||
}
|
||||
|
||||
public static MockKeycloakIngress build(boolean defaultIngressDisabled, boolean ingressExists) {
|
||||
public static MockKeycloakIngress build(Boolean defaultIngressEnabled, boolean ingressExists, boolean ingressSpecDefined) {
|
||||
MockKeycloakIngress.ingressExists = ingressExists;
|
||||
return new MockKeycloakIngress(defaultIngressDisabled);
|
||||
return new MockKeycloakIngress(defaultIngressEnabled, ingressSpecDefined);
|
||||
}
|
||||
|
||||
public static boolean ingressExists = false;
|
||||
private boolean deleted = false;
|
||||
public MockKeycloakIngress(boolean defaultIngressDisabled) {
|
||||
super(null, getKeycloak(defaultIngressDisabled));
|
||||
public MockKeycloakIngress(Boolean defaultIngressEnabled, boolean ingressSpecDefined) {
|
||||
super(null, getKeycloak(defaultIngressEnabled, ingressSpecDefined));
|
||||
}
|
||||
|
||||
public boolean reconciled() {
|
||||
|
@ -72,29 +76,43 @@ public class IngressLogicTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIngressEnabledExisting() {
|
||||
var kc = MockKeycloakIngress.build(true, true);
|
||||
public void testIngressDisabledExisting() {
|
||||
var kc = MockKeycloakIngress.build(false, true, true);
|
||||
assertFalse(kc.reconciled());
|
||||
assertTrue(kc.deleted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIngressEnabledNotExisting() {
|
||||
var kc = MockKeycloakIngress.build(true, false);
|
||||
public void testIngressDisabledNotExisting() {
|
||||
var kc = MockKeycloakIngress.build(false, false, true);
|
||||
assertFalse(kc.reconciled());
|
||||
assertFalse(kc.deleted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIngressDisabledExisting() {
|
||||
var kc = MockKeycloakIngress.build(false, true);
|
||||
public void testIngressEnabledExisting() {
|
||||
var kc = MockKeycloakIngress.build(true, true, true);
|
||||
assertTrue(kc.reconciled());
|
||||
assertFalse(kc.deleted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIngressDisabledNotExisting() {
|
||||
var kc = MockKeycloakIngress.build(false, false);
|
||||
public void testIngressEnabledNotExisting() {
|
||||
var kc = MockKeycloakIngress.build(true, false, true);
|
||||
assertTrue(kc.reconciled());
|
||||
assertFalse(kc.deleted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIngressEnabledNotSpecified() {
|
||||
var kc = MockKeycloakIngress.build(true, false, false);
|
||||
assertTrue(kc.reconciled());
|
||||
assertFalse(kc.deleted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIngressSpecDefinedWithoutProperty() {
|
||||
var kc = MockKeycloakIngress.build(null, false, true);
|
||||
assertTrue(kc.reconciled());
|
||||
assertFalse(kc.deleted());
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ spec:
|
|||
- name: features
|
||||
value: docker
|
||||
hostname: my-hostname
|
||||
ingress:
|
||||
enabled: false
|
||||
http:
|
||||
httpEnabled: true
|
||||
httpPort: 123
|
||||
|
@ -23,7 +25,6 @@ spec:
|
|||
disabled:
|
||||
- admin
|
||||
- step-up-authentication
|
||||
disableDefaultIngress: true
|
||||
transaction:
|
||||
xaEnabled: false
|
||||
unsupported:
|
||||
|
|
Loading…
Reference in a new issue