Add 'imagePullSecret' field to the Keycloak CR
This commit is contained in:
parent
aec8e6af50
commit
4594243a33
5 changed files with 113 additions and 0 deletions
|
@ -30,6 +30,7 @@ import io.fabric8.kubernetes.api.model.apps.StatefulSet;
|
|||
import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.quarkus.logging.Log;
|
||||
import org.keycloak.common.util.CollectionUtil;
|
||||
import org.keycloak.operator.Config;
|
||||
import org.keycloak.operator.Constants;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||
|
@ -152,6 +153,11 @@ public class KeycloakDeployment extends OperatorManagedResource implements Statu
|
|||
overlayTemplate.getSpec().getContainers().get(0).getImage() != null) {
|
||||
status.addWarningMessage("The image of the keycloak container cannot be modified using podTemplate");
|
||||
}
|
||||
|
||||
if (overlayTemplate.getSpec() != null &&
|
||||
CollectionUtil.isNotEmpty(overlayTemplate.getSpec().getImagePullSecrets())) {
|
||||
status.addWarningMessage("The imagePullSecrets of the keycloak container cannot be modified using podTemplate");
|
||||
}
|
||||
}
|
||||
|
||||
private <T, V> void mergeMaps(Map<T, V> map1, Map<T, V> map2, Consumer<Map<T, V>> consumer) {
|
||||
|
@ -523,6 +529,10 @@ public class KeycloakDeployment extends OperatorManagedResource implements Statu
|
|||
container.getArgs().add("--optimized");
|
||||
}
|
||||
|
||||
if (CollectionUtil.isNotEmpty(keycloakCR.getSpec().getImagePullSecrets())) {
|
||||
baseDeployment.getSpec().getTemplate().getSpec().setImagePullSecrets(keycloakCR.getSpec().getImagePullSecrets());
|
||||
}
|
||||
|
||||
container.setImagePullPolicy(config.keycloak().imagePullPolicy());
|
||||
|
||||
container.setEnv(getEnvVars());
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.operator.crds.v2alpha1.deployment;
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.LocalObjectReference;
|
||||
import org.keycloak.operator.Constants;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
@ -30,6 +31,8 @@ public class KeycloakSpec {
|
|||
private int instances = 1;
|
||||
@JsonPropertyDescription("Custom Keycloak image to be used.")
|
||||
private String image;
|
||||
@JsonPropertyDescription("Secret(s) that might be used when pulling an image from a private container image registry or repository.")
|
||||
private List<LocalObjectReference> imagePullSecrets;
|
||||
@JsonPropertyDescription("Configuration of the Keycloak server.\n" +
|
||||
"expressed as a keys (reference: https://www.keycloak.org/server/all-config) and values that can be either direct values or references to secrets.")
|
||||
private List<ValueOrSecret> serverConfiguration; // can't use Set due to a bug in Sundrio https://github.com/sundrio/sundrio/issues/316
|
||||
|
@ -110,6 +113,14 @@ public class KeycloakSpec {
|
|||
this.image = image;
|
||||
}
|
||||
|
||||
public List<LocalObjectReference> getImagePullSecrets() {
|
||||
return this.imagePullSecrets;
|
||||
}
|
||||
|
||||
public void setImagePullSecrets(List<LocalObjectReference> imagePullSecrets) {
|
||||
this.imagePullSecrets = imagePullSecrets;
|
||||
}
|
||||
|
||||
public List<ValueOrSecret> getServerConfiguration() {
|
||||
return serverConfiguration;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
package org.keycloak.operator.testsuite.integration;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.EnvVarBuilder;
|
||||
import io.fabric8.kubernetes.api.model.LocalObjectReference;
|
||||
import io.fabric8.kubernetes.api.model.LocalObjectReferenceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder;
|
||||
import io.fabric8.kubernetes.api.model.SecretKeySelectorBuilder;
|
||||
import io.fabric8.kubernetes.api.model.apps.StatefulSetSpecBuilder;
|
||||
|
@ -38,6 +41,7 @@ import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
@ -52,6 +56,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
import static org.keycloak.operator.testsuite.utils.CRAssert.assertKeycloakStatusCondition;
|
||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.deployKeycloak;
|
||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.getDefaultKeycloakDeployment;
|
||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.getResourceFromFile;
|
||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.waitForKeycloakToBeReady;
|
||||
|
||||
@QuarkusTest
|
||||
|
@ -397,6 +402,37 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIfSystemProperty(named = OPERATOR_CUSTOM_IMAGE, matches = ".+")
|
||||
public void testCustomImageWithImagePullSecrets() {
|
||||
String imagePullSecretName = "docker-regcred-custom-kc-imagepullsecret-01";
|
||||
String secretDescriptorFilename = "test-docker-registry-secret.yaml";
|
||||
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
kc.getSpec().setImage(customImage);
|
||||
|
||||
handleFakeImagePullSecretCreation(kc, secretDescriptorFilename);
|
||||
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
var pods = k8sclient
|
||||
.pods()
|
||||
.inNamespace(namespace)
|
||||
.withLabels(Constants.DEFAULT_LABELS)
|
||||
.list()
|
||||
.getItems();
|
||||
|
||||
assertThat(pods.get(0).getSpec().getContainers().get(0).getArgs()).containsExactly("start", "--optimized");
|
||||
assertThat(pods.get(0).getSpec().getImagePullSecrets().size()).isEqualTo(1);
|
||||
assertThat(pods.get(0).getSpec().getImagePullSecrets().get(0).getName()).isEqualTo(imagePullSecretName);
|
||||
|
||||
} catch (Exception e) {
|
||||
savePodLogs();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpRelativePathWithPlainValue() {
|
||||
try {
|
||||
|
@ -498,4 +534,12 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleFakeImagePullSecretCreation(Keycloak keycloakCR,
|
||||
String secretDescriptorFilename) {
|
||||
|
||||
Secret imagePullSecret = getResourceFromFile(secretDescriptorFilename, Secret.class);
|
||||
k8sclient.secrets().inNamespace(namespace).createOrReplace(imagePullSecret);
|
||||
LocalObjectReference localObjRefAsSecretTmp = new LocalObjectReferenceBuilder().withName(imagePullSecret.getMetadata().getName()).build();
|
||||
keycloakCR.getSpec().setImagePullSecrets(Collections.singletonList(localObjRefAsSecretTmp));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
|
||||
package org.keycloak.operator.testsuite.integration;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.LocalObjectReference;
|
||||
import io.fabric8.kubernetes.api.model.LocalObjectReferenceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.client.dsl.Resource;
|
||||
import io.fabric8.kubernetes.client.utils.Serialization;
|
||||
import io.quarkus.logging.Log;
|
||||
|
@ -27,9 +30,12 @@ import org.junit.jupiter.api.Test;
|
|||
import org.keycloak.operator.testsuite.utils.CRAssert;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusCondition.HAS_ERRORS;
|
||||
import static org.keycloak.operator.testsuite.utils.K8sUtils.getResourceFromFile;
|
||||
|
||||
@QuarkusTest
|
||||
public class PodTemplateTest extends BaseOperatorTest {
|
||||
|
@ -181,4 +187,39 @@ public class PodTemplateTest extends BaseOperatorTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPodTemplateIncorrectImagePullSecretsConfig() {
|
||||
String imagePullSecretName = "docker-regcred-custom-kc-imagepullsecret-01";
|
||||
String secretDescriptorFilename = "test-docker-registry-secret.yaml";
|
||||
|
||||
Secret imagePullSecret = getResourceFromFile(secretDescriptorFilename, Secret.class);
|
||||
k8sclient.secrets().inNamespace(namespace).createOrReplace(imagePullSecret);
|
||||
LocalObjectReference localObjRefAsSecretTmp = new LocalObjectReferenceBuilder().withName(imagePullSecret.getMetadata().getName()).build();
|
||||
|
||||
assertThat(localObjRefAsSecretTmp.getName()).isNotNull();
|
||||
assertThat(localObjRefAsSecretTmp.getName()).isEqualTo(imagePullSecretName);
|
||||
|
||||
var podTemplate = new PodTemplateSpecBuilder()
|
||||
.withNewSpec()
|
||||
.addAllToImagePullSecrets(Collections.singletonList(localObjRefAsSecretTmp))
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
var plainKc = getEmptyPodTemplateKeycloak();
|
||||
plainKc.getSpec().getUnsupported().setPodTeplate(podTemplate);
|
||||
|
||||
// Act
|
||||
k8sclient.resource(plainKc).createOrReplace();
|
||||
|
||||
// Assert
|
||||
Log.info("Getting status of Keycloak");
|
||||
Awaitility
|
||||
.await()
|
||||
.ignoreExceptions()
|
||||
.atMost(3, MINUTES).untilAsserted(() -> {
|
||||
CRAssert.assertKeycloakStatusCondition(getCrSelector().get(), HAS_ERRORS, false, "imagePullSecrets");
|
||||
CRAssert.assertKeycloakStatusCondition(getCrSelector().get(), HAS_ERRORS, false, "cannot be modified");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
data:
|
||||
.dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJrZXljbG9hazR0ZXN0IiwicGFzc3dvcmQiOiJ2S2xRJWMyNDY5RUBMIiwiZW1haWwiOiJhbmFzY2ltZUByZWRoYXQuY29tIiwiYXV0aCI6ImEyVjVZMnh2WVdzMGRHVnpkRHAyUzJ4UkpXTXlORFk1UlVCTSJ9fX0=
|
||||
metadata:
|
||||
name: docker-regcred-custom-kc-imagepullsecret-01
|
||||
type: kubernetes.io/dockerconfigjson
|
Loading…
Reference in a new issue