parent
4b36da03db
commit
819d33411a
9 changed files with 200 additions and 156 deletions
|
@ -20,6 +20,8 @@ package org.keycloak.operator.testsuite.integration;
|
|||
import io.fabric8.kubernetes.api.model.HasMetadata;
|
||||
import io.fabric8.kubernetes.api.model.NamespaceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.PodSpecFluent.ContainersNested;
|
||||
import io.fabric8.kubernetes.api.model.PodTemplateSpecFluent.SpecNested;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.ConfigBuilder;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
|
@ -41,6 +43,9 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.keycloak.operator.Constants;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakSpecBuilder;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakSpecFluent.UnsupportedNested;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.UnsupportedSpecFluent.PodTemplateNested;
|
||||
import org.keycloak.operator.testsuite.utils.K8sUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -80,7 +85,6 @@ public abstract class BaseOperatorTest {
|
|||
private static Operator operator;
|
||||
protected static boolean isOpenShift;
|
||||
|
||||
|
||||
@BeforeAll
|
||||
public static void before() throws FileNotFoundException {
|
||||
configuration = CDI.current().select(QuarkusConfigurationService.class).get();
|
||||
|
@ -263,4 +267,45 @@ public abstract class BaseOperatorTest {
|
|||
public static String getCurrentNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public static String getTestCustomImage() {
|
||||
return customImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default deployment modified/optimized by operator test settings
|
||||
* @param disableProbes when true the unsupported template will be used to effectively
|
||||
* disable the probes, which will speed up testing for scenarios that don't interact
|
||||
* with the underlying keycloak
|
||||
* @return
|
||||
*/
|
||||
public static Keycloak getTestKeycloakDeployment(boolean disableProbes) {
|
||||
Keycloak kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
kc.getMetadata().setNamespace(getCurrentNamespace());
|
||||
String image = getTestCustomImage();
|
||||
if (image != null) {
|
||||
kc.getSpec().setImage(image);
|
||||
}
|
||||
if (disableProbes) {
|
||||
return disableProbes(kc);
|
||||
}
|
||||
return kc;
|
||||
}
|
||||
|
||||
public static Keycloak disableProbes(Keycloak keycloak) {
|
||||
KeycloakSpecBuilder specBuilder = new KeycloakSpecBuilder(keycloak.getSpec());
|
||||
var podTemplateSpecBuilder = specBuilder.editOrNewUnsupported().editOrNewPodTemplate().editOrNewSpec();
|
||||
ContainersNested<SpecNested<PodTemplateNested<UnsupportedNested<KeycloakSpecBuilder>>>> containerBuilder = null;
|
||||
if (podTemplateSpecBuilder.hasContainers()) {
|
||||
containerBuilder = podTemplateSpecBuilder.editContainer(0);
|
||||
} else {
|
||||
containerBuilder = podTemplateSpecBuilder.addNewContainer();
|
||||
}
|
||||
keycloak.setSpec(containerBuilder.withNewLivenessProbe().withNewExec().addToCommand("true").endExec()
|
||||
.endLivenessProbe().withNewReadinessProbe().withNewExec().addToCommand("true").endExec()
|
||||
.endReadinessProbe().withNewStartupProbe().withNewExec().addToCommand("true").endExec()
|
||||
.endStartupProbe().endContainer().endSpec().endPodTemplate().endUnsupported().build());
|
||||
return keycloak;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,11 +54,11 @@ public class ClusteringTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testMultipleDeployments() throws InterruptedException {
|
||||
// given
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
|
||||
// another instance running off the same database
|
||||
// - should eventually give this a separate schema
|
||||
var kc1 = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc1 = getTestKeycloakDeployment(true);
|
||||
kc1.getMetadata().setName("another-example");
|
||||
kc1.getSpec().getHostnameSpec().setHostname("another-example.com");
|
||||
// this is using the wrong tls-secret, but simply removing http spec renders the pod unstartable
|
||||
|
@ -109,7 +109,7 @@ public class ClusteringTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testKeycloakScaleAsExpected() {
|
||||
// given
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
var crSelector = k8sclient.resource(kc);
|
||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
|
@ -196,7 +196,7 @@ public class ClusteringTest extends BaseOperatorTest {
|
|||
public void testKeycloakCacheIsConnected() throws Exception {
|
||||
// given
|
||||
Log.info("Setup");
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
var crSelector = k8sclient.resource(kc);
|
||||
K8sUtils.deployKeycloak(k8sclient, kc, false);
|
||||
var targetInstances = 3;
|
||||
|
|
|
@ -62,7 +62,6 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
|||
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;
|
||||
|
||||
|
@ -73,7 +72,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
try {
|
||||
// CR
|
||||
Log.info("Creating new Keycloak CR example");
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var deploymentName = kc.getMetadata().getName();
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
|
@ -103,7 +102,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testCRFields() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var deploymentName = kc.getMetadata().getName();
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
|
@ -137,7 +136,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testConfigInCRTakesPrecedence() {
|
||||
try {
|
||||
var defaultKCDeploy = getDefaultKeycloakDeployment();
|
||||
var defaultKCDeploy = getTestKeycloakDeployment(true);
|
||||
|
||||
var valueSecretHealthProp = new ValueOrSecret("health-enabled", "false");
|
||||
var valueSecretProxyProp = new ValueOrSecret("proxy", "reencrypt");
|
||||
|
@ -209,7 +208,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testDeploymentDurability() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var deploymentName = kc.getMetadata().getName();
|
||||
|
||||
// create a dummy StatefulSet representing the pre-multiinstance state that we'll be forced to delete
|
||||
|
@ -274,7 +273,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testTlsUsesCorrectSecret() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
var service = new KeycloakService(k8sclient, kc);
|
||||
|
@ -284,10 +283,10 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
String url = "https://" + service.getName() + "." + namespace + ":" + Constants.KEYCLOAK_HTTPS_PORT;
|
||||
Log.info("Checking url: " + url);
|
||||
|
||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "-v", url);
|
||||
var curlOutput = K8sUtils.inClusterCurl(k8sclient, namespace, "--insecure", "-s", "-w", "%{certs}", url);
|
||||
Log.info("Curl Output: " + curlOutput);
|
||||
|
||||
assertTrue(curlOutput.contains("issuer: O=mkcert development CA; OU=aperuffo@aperuffo-mac (Andrea Peruffo); CN=mkcert aperuffo@aperuffo-mac (Andrea Peruffo)"));
|
||||
assertTrue(curlOutput.contains("Issuer:O = mkcert development CA, OU = aperuffo@aperuffo-mac (Andrea Peruffo), CN = mkcert aperuffo@aperuffo-mac (Andrea Peruffo)"));
|
||||
});
|
||||
} catch (Exception e) {
|
||||
savePodLogs();
|
||||
|
@ -298,7 +297,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testTlsDisabled() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().getHttpSpec().setTlsSecret(null);
|
||||
kc.getSpec().getHttpSpec().setHttpEnabled(true);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
@ -313,7 +312,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testHostnameStrict() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
var service = new KeycloakService(k8sclient, kc);
|
||||
|
@ -337,7 +336,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testHostnameStrictDisabled() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var hostnameSpec = new HostnameSpecBuilder()
|
||||
.withStrict(false)
|
||||
.withStrictBackchannel(false)
|
||||
|
@ -369,7 +368,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
try {
|
||||
final int httpsPort = 8543;
|
||||
final int httpPort = 8180;
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().getHttpSpec().setHttpsPort(httpsPort);
|
||||
kc.getSpec().getHttpSpec().setHttpPort(httpPort);
|
||||
|
||||
|
@ -393,7 +392,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
try {
|
||||
final int httpsPort = 8543;
|
||||
final int httpPort = 8180;
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().getHttpSpec().setHttpsPort(httpsPort);
|
||||
kc.getSpec().getHttpSpec().setHttpPort(httpPort);
|
||||
kc.getSpec().getHttpSpec().setTlsSecret(null);
|
||||
|
@ -419,7 +418,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testInitialAdminUser() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var kcAdminSecret = new KeycloakAdminSecret(k8sclient, kc);
|
||||
|
||||
k8sclient
|
||||
|
@ -510,7 +509,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@EnabledIfSystemProperty(named = OPERATOR_CUSTOM_IMAGE, matches = ".+")
|
||||
public void testCustomImage() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().setImage(customImage);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
|
@ -535,7 +534,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
String secretDescriptorFilename = "test-docker-registry-secret.yaml";
|
||||
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().setImage(customImage);
|
||||
|
||||
handleFakeImagePullSecretCreation(kc, secretDescriptorFilename);
|
||||
|
@ -563,7 +562,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
public void testInvalidCustomImageHasErrorMessage() {
|
||||
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().setImage("does-not-exist");
|
||||
|
||||
deployKeycloak(k8sclient, kc, false);
|
||||
|
@ -587,7 +586,8 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testHttpRelativePathWithPlainValue() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
kc.getSpec().setImage(null); // doesn't seem to become ready with the custom image
|
||||
kc.getSpec().getAdditionalOptions().add(new ValueOrSecret(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY, "/foobar"));
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
|
@ -608,7 +608,8 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testHttpRelativePathWithSecretValue() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
kc.getSpec().setImage(null); // doesn't seem to become ready with the custom image
|
||||
var secretName = "my-http-relative-path";
|
||||
var keyName = "rel-path";
|
||||
var httpRelativePathSecret = new SecretBuilder()
|
||||
|
@ -644,7 +645,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testUpgradeRecreatesPods() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().setInstances(3);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
|
@ -691,7 +692,7 @@ public class KeycloakDeploymentTest extends BaseOperatorTest {
|
|||
"Skipping the test when Operator deployed remotely to keep stuff simple, it's just SmallRye, we don't need to retest it");
|
||||
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
// labels are set in test/resources/application.properties
|
||||
|
|
|
@ -63,7 +63,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
|
||||
@Test
|
||||
public void testIngressOnHTTP() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
kc.getSpec().getHttpSpec().setTlsSecret(null);
|
||||
kc.getSpec().getHttpSpec().setHttpEnabled(true);
|
||||
var hostnameSpecBuilder = new HostnameSpecBuilder()
|
||||
|
@ -89,7 +89,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
|
||||
@Test
|
||||
public void testIngressOnHTTPS() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
var hostnameSpecBuilder = new HostnameSpecBuilder()
|
||||
.withStrict(false)
|
||||
.withStrictBackchannel(false);
|
||||
|
@ -142,7 +142,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
|
||||
@Test
|
||||
public void testIngressHostname() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
var hostnameSpec = new HostnameSpecBuilder().withHostname("foo.bar").build();
|
||||
kc.getSpec().setHostnameSpec(hostnameSpec);
|
||||
|
||||
|
@ -170,7 +170,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
|
||||
@Test
|
||||
public void testMainIngressDurability() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().setIngressSpec(new IngressSpec());
|
||||
kc.getSpec().getIngressSpec().setIngressEnabled(true);
|
||||
kc.getSpec().getIngressSpec().setAnnotations(Map.of("haproxy.router.openshift.io/disable_cookies", "true"));
|
||||
|
@ -226,8 +226,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
|
||||
@Test
|
||||
public void testCustomIngressDeletion() {
|
||||
|
||||
Keycloak defaultKeycloakDeployment = K8sUtils.getDefaultKeycloakDeployment();
|
||||
Keycloak defaultKeycloakDeployment = getTestKeycloakDeployment(true);
|
||||
String kcDeploymentName = defaultKeycloakDeployment.getMetadata().getName();
|
||||
Resource<Ingress> customIngressDeployedManuallySelector = null;
|
||||
Ingress customIngressCreatedManually;
|
||||
|
@ -271,10 +270,10 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCustomIngressClassName() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().setIngressSpec(new IngressSpecBuilder().withIngressClassName("nginx").build());
|
||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
|
@ -307,7 +306,7 @@ public class KeycloakIngressTest extends BaseOperatorTest {
|
|||
|
||||
@Test
|
||||
public void testCustomIngressAnnotations() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
kc.getSpec().setIngressSpec(new IngressSpec());
|
||||
kc.getSpec().getIngressSpec().setIngressEnabled(true);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
public class KeycloakServicesTest extends BaseOperatorTest {
|
||||
@Test
|
||||
public void testMainServiceDurability() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||
var service = new KeycloakService(k8sclient, kc);
|
||||
var serviceSelector = k8sclient.services().inNamespace(namespace).withName(service.getName());
|
||||
|
@ -84,7 +84,7 @@ public class KeycloakServicesTest extends BaseOperatorTest {
|
|||
|
||||
@Test
|
||||
public void testDiscoveryServiceDurability() {
|
||||
var kc = K8sUtils.getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
K8sUtils.deployKeycloak(k8sclient, kc, true);
|
||||
var discoveryService = new KeycloakDiscoveryService(k8sclient, kc);
|
||||
var discoveryServiceSelector = k8sclient.services().inNamespace(namespace).withName(discoveryService.getName());
|
||||
|
|
|
@ -40,7 +40,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.keycloak.operator.Constants.KEYCLOAK_HTTPS_PORT;
|
||||
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.getDefaultKeycloakDeployment;
|
||||
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.HAS_ERRORS;
|
||||
|
@ -81,7 +80,8 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testWorkingRealmImport() {
|
||||
// Arrange
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
kc.getSpec().setImage(null); // checks the job args for the base, not custom image
|
||||
kc.getSpec().setImagePullSecrets(Arrays.asList(new LocalObjectReferenceBuilder().withName("my-empty-secret").build()));
|
||||
deployKeycloak(k8sclient, kc, false);
|
||||
|
||||
|
@ -98,9 +98,10 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
.pollDelay(1, SECONDS)
|
||||
.ignoreExceptions()
|
||||
.untilAsserted(() -> {
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), DONE, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), STARTED, true);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), HAS_ERRORS, false);
|
||||
KeycloakRealmImport cr = crSelector.get();
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, DONE, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, STARTED, true);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, HAS_ERRORS, false);
|
||||
});
|
||||
|
||||
Awaitility.await()
|
||||
|
@ -108,9 +109,10 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
.pollDelay(1, SECONDS)
|
||||
.ignoreExceptions()
|
||||
.untilAsserted(() -> {
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), DONE, true);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), STARTED, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), HAS_ERRORS, false);
|
||||
KeycloakRealmImport cr = crSelector.get();
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, DONE, true);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, STARTED, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, HAS_ERRORS, false);
|
||||
});
|
||||
var job = k8sclient.batch().v1().jobs().inNamespace(namespace).withName("example-count0-kc").get();
|
||||
assertThat(job.getSpec().getTemplate().getMetadata().getLabels().get("app")).isEqualTo("keycloak-realm-import");
|
||||
|
@ -120,11 +122,10 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
assertThat(job.getSpec().getTemplate().getSpec().getImagePullSecrets().size()).isEqualTo(1);
|
||||
assertThat(job.getSpec().getTemplate().getSpec().getImagePullSecrets().get(0).getName()).isEqualTo("my-empty-secret");
|
||||
|
||||
var service = new KeycloakService(k8sclient, getDefaultKeycloakDeployment());
|
||||
String url =
|
||||
"https://" + service.getName() + "." + namespace + ":" + KEYCLOAK_HTTPS_PORT + "/realms/count0";
|
||||
"https://" + KeycloakService.getServiceName(kc) + "." + namespace + ":" + KEYCLOAK_HTTPS_PORT + "/realms/count0";
|
||||
|
||||
Awaitility.await().atMost(10, MINUTES).untilAsserted(() -> {
|
||||
Awaitility.await().atMost(10, MINUTES).ignoreExceptions().untilAsserted(() -> {
|
||||
Log.info("Starting curl Pod to test if the realm is available");
|
||||
Log.info("Url: '" + url + "'");
|
||||
String curlOutput = inClusterCurl(k8sclient, namespace, url);
|
||||
|
@ -139,7 +140,7 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
@EnabledIfSystemProperty(named = OPERATOR_CUSTOM_IMAGE, matches = ".+")
|
||||
public void testWorkingRealmImportWithCustomImage() {
|
||||
// Arrange
|
||||
var keycloak = getDefaultKeycloakDeployment();
|
||||
var keycloak = getTestKeycloakDeployment(false);
|
||||
keycloak.getSpec().setImage(customImage);
|
||||
// Removing the Database so that a subsequent build will by default act on h2
|
||||
// TODO: uncomment the following line after resolution of: https://github.com/keycloak/keycloak/issues/11767
|
||||
|
@ -160,9 +161,10 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
.pollDelay(5, SECONDS)
|
||||
.ignoreExceptions()
|
||||
.untilAsserted(() -> {
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), DONE, true);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), STARTED, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), HAS_ERRORS, false);
|
||||
KeycloakRealmImport cr = crSelector.get();
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, DONE, true);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, STARTED, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, HAS_ERRORS, false);
|
||||
});
|
||||
|
||||
assertThat(getJobArgs()).doesNotContain("build");
|
||||
|
@ -171,7 +173,7 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testNotWorkingRealmImport() {
|
||||
// Arrange
|
||||
deployKeycloak(k8sclient, getDefaultKeycloakDeployment(), true); // make sure there are no errors due to missing KC Deployment
|
||||
deployKeycloak(k8sclient, getTestKeycloakDeployment(false), true); // make sure there are no errors due to missing KC Deployment
|
||||
|
||||
// Act
|
||||
K8sUtils.set(k8sclient, getClass().getResourceAsStream("/incorrect-realm.yaml"));
|
||||
|
@ -186,10 +188,10 @@ public class RealmImportTest extends BaseOperatorTest {
|
|||
.resources(KeycloakRealmImport.class)
|
||||
.inNamespace(namespace)
|
||||
.withName("example-count0-kc");
|
||||
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), DONE, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), STARTED, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(crSelector.get(), HAS_ERRORS, true);
|
||||
KeycloakRealmImport cr = crSelector.get();
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, DONE, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, STARTED, false);
|
||||
CRAssert.assertKeycloakRealmImportStatusCondition(cr, HAS_ERRORS, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,13 @@
|
|||
|
||||
package org.keycloak.operator.testsuite.integration;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder;
|
||||
import io.fabric8.kubernetes.api.model.apps.StatefulSet;
|
||||
import io.quarkus.logging.Log;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -31,18 +34,19 @@ import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusCondition;
|
|||
import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HostnameSpecBuilder;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
|
@ -52,7 +56,7 @@ public class WatchedSecretsTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testSecretsAreWatched() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
Secret dbSecret = getDbSecret();
|
||||
|
@ -89,10 +93,10 @@ public class WatchedSecretsTest extends BaseOperatorTest {
|
|||
try {
|
||||
final String username = "HomerSimpson";
|
||||
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(false);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
var prevPodNames = getPodNamesForCrs(Set.of(kc));
|
||||
var prevRevision = getStatefulSet(kc).getStatus().getUpdateRevision();
|
||||
|
||||
var dbSecret = getDbSecret();
|
||||
|
||||
|
@ -100,40 +104,29 @@ public class WatchedSecretsTest extends BaseOperatorTest {
|
|||
Base64.getEncoder().encodeToString(username.getBytes()));
|
||||
k8sclient.resource(dbSecret).update();
|
||||
|
||||
Awaitility.await()
|
||||
.ignoreExceptions()
|
||||
.untilAsserted(() -> {
|
||||
Log.info("Checking pod logs for DB auth failures");
|
||||
var podlogs = getPodNamesForCrs(Set.of(kc)).stream()
|
||||
.filter(n -> !prevPodNames.contains(n)) // checking just new pods
|
||||
.map(n -> {
|
||||
var name = k8sclient
|
||||
.pods()
|
||||
.inNamespace(namespace)
|
||||
.list()
|
||||
.getItems()
|
||||
.stream()
|
||||
.filter(p -> (p.getMetadata().getName() + p.getMetadata().getCreationTimestamp()).equals(n))
|
||||
.findAny()
|
||||
.get()
|
||||
.getMetadata()
|
||||
.getName();
|
||||
Pod pod = k8sclient.pods().withName(kc.getMetadata().getName() + "-0").waitUntilCondition(
|
||||
p -> p != null && !prevRevision.equals(p.getMetadata().getLabels().get("controller-revision-hash")),
|
||||
30, TimeUnit.SECONDS);
|
||||
|
||||
return k8sclient.pods().inNamespace(namespace).withName(name).getLog();
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
assertThat(podlogs).anyMatch(l -> l.contains("password authentication failed for user \"" + username + "\""));
|
||||
});
|
||||
ByteArrayOutputStream logBytes = new ByteArrayOutputStream();
|
||||
try (var ignored = k8sclient.pods().resource(pod).watchLog(logBytes)) {
|
||||
Awaitility.await().atMost(1, TimeUnit.MINUTES).until(() -> logBytes.toString(StandardCharsets.UTF_8)
|
||||
.contains("password authentication failed for user \"" + username + "\""));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
savePodLogs();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private StatefulSet getStatefulSet(Keycloak kc) {
|
||||
return k8sclient.apps().statefulSets().withName(kc.getMetadata().getName()).require();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecretsCanBeUnWatched() {
|
||||
try {
|
||||
var kc = getDefaultKeycloakDeployment();
|
||||
var kc = getTestKeycloakDeployment(true);
|
||||
deployKeycloak(k8sclient, kc, true);
|
||||
|
||||
Log.info("Updating KC to not to rely on DB Secret");
|
||||
|
@ -162,12 +155,12 @@ public class WatchedSecretsTest extends BaseOperatorTest {
|
|||
@Test
|
||||
public void testSingleSecretMultipleKeycloaks() {
|
||||
try {
|
||||
var kc1 = getDefaultKeycloakDeployment();
|
||||
var kc1 = getTestKeycloakDeployment(true);
|
||||
var kc1Hostname = new HostnameSpecBuilder().withHostname("kc1.local").build();
|
||||
kc1.getMetadata().setName(kc1.getMetadata().getName() + "-1");
|
||||
kc1.getSpec().setHostnameSpec(kc1Hostname);
|
||||
|
||||
var kc2 = getDefaultKeycloakDeployment();
|
||||
var kc2 = getTestKeycloakDeployment(true);
|
||||
var kc2Hostname = new HostnameSpecBuilder().withHostname("kc2.local").build();
|
||||
kc2.getMetadata().setName(kc2.getMetadata().getName() + "-2");
|
||||
kc2.getSpec().setHostnameSpec(kc2Hostname); // to prevent Ingress conflicts
|
||||
|
@ -204,12 +197,14 @@ public class WatchedSecretsTest extends BaseOperatorTest {
|
|||
private void testDeploymentRestarted(Set<Keycloak> crsToBeRestarted, Set<Keycloak> crsNotToBeRestarted, Runnable action) {
|
||||
boolean restartExpected = !crsToBeRestarted.isEmpty();
|
||||
|
||||
List<String> podsToBeRestarted = getPodNamesForCrs(crsToBeRestarted);
|
||||
List<String> podsNotToBeRestarted = getPodNamesForCrs(crsNotToBeRestarted);
|
||||
var toBeRestarted = crsToBeRestarted.stream().collect(Collectors.toMap(Function.identity(), k -> getStatefulSet(k).getStatus().getUpdateRevision()));
|
||||
var notToBeRestarted = crsNotToBeRestarted.stream().collect(Collectors.toMap(Function.identity(), k -> getStatefulSet(k).getStatus().getUpdateRevision()));
|
||||
|
||||
action.run();
|
||||
|
||||
if (restartExpected) {
|
||||
// this depends on the restart taking long enough to detect after the action is run
|
||||
// we may want to switch to using an informer that runs before the action
|
||||
assertRollingUpdate(crsToBeRestarted, true);
|
||||
}
|
||||
|
||||
|
@ -220,45 +215,33 @@ public class WatchedSecretsTest extends BaseOperatorTest {
|
|||
if (restartExpected) {
|
||||
Awaitility.await()
|
||||
.untilAsserted(() -> {
|
||||
List<String> newPods = getPodNamesForCrs(allCrs);
|
||||
Log.infof("Pods to be restarted: %s\nPods NOT to be restarted: %s\nCurrent Pods: %s",
|
||||
podsToBeRestarted, podsNotToBeRestarted, newPods);
|
||||
assertThat(newPods).noneMatch(podsToBeRestarted::contains);
|
||||
assertThat(newPods).containsAll(podsNotToBeRestarted);
|
||||
toBeRestarted.forEach((k, version) -> {
|
||||
// make sure a new version was fully rolled in
|
||||
var status = getStatefulSet(k).getStatus();
|
||||
assertThat(status.getUpdateRevision()).isEqualTo(status.getCurrentRevision());
|
||||
assertThat(status.getUpdateRevision()).isNotEqualTo(version);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (!notToBeRestarted.isEmpty()) {
|
||||
Awaitility.await()
|
||||
.during(10, TimeUnit.SECONDS) // to ensure no pods were created
|
||||
.untilAsserted(() -> {
|
||||
List<String> newPods = getPodNamesForCrs(allCrs);
|
||||
Log.infof("Pods NOT to be restarted: %s, expected pods: %s\nAsserting current pods are unchanged: %s",
|
||||
podsNotToBeRestarted, newPods);
|
||||
assertThat(newPods).isEqualTo(podsNotToBeRestarted);
|
||||
notToBeRestarted.forEach((k, version) -> {
|
||||
// make sure the version has stayed the same
|
||||
var status = getStatefulSet(k).getStatus();
|
||||
assertThat(status.getUpdateRevision()).isEqualTo(status.getCurrentRevision());
|
||||
assertThat(status.getUpdateRevision()).isEqualTo(version);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getPodNamesForCrs(Set<Keycloak> crs) {
|
||||
return k8sclient
|
||||
.pods()
|
||||
.inNamespace(namespace)
|
||||
.list()
|
||||
.getItems()
|
||||
.stream()
|
||||
.map(pod -> pod.getMetadata().getName() + pod.getMetadata().getCreationTimestamp())
|
||||
.filter(pod -> crs.stream().map(c -> c.getMetadata().getName()).anyMatch(pod::startsWith))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void assertRollingUpdate(Set<Keycloak> crs, boolean expectedStatus) {
|
||||
Awaitility.await()
|
||||
.untilAsserted(() -> {
|
||||
for (var cr : crs) {
|
||||
Keycloak kc = k8sclient.resources(Keycloak.class)
|
||||
.inNamespace(namespace)
|
||||
.withName(cr.getMetadata().getName())
|
||||
.get();
|
||||
Keycloak kc = k8sclient.resource(cr).get();
|
||||
assertKeycloakStatusCondition(kc, KeycloakStatusCondition.ROLLING_UPDATE, expectedStatus);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpecBuilder;
|
|||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.UnsupportedSpec;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -93,7 +94,7 @@ public class PodTemplateTest {
|
|||
|
||||
var deployment = new KeycloakDeployment(null, config, kc, existingDeployment, "dummy-admin");
|
||||
|
||||
return (StatefulSet) deployment.getReconciledResource().get();
|
||||
return deployment.getReconciledResource().get();
|
||||
}
|
||||
|
||||
private StatefulSet getDeployment(PodTemplateSpec podTemplate, StatefulSet existingDeployment) {
|
||||
|
@ -368,4 +369,16 @@ public class PodTemplateTest {
|
|||
assertEquals("/some/health/ready", fourth.getReadinessProbe().getHttpGet().getPath());
|
||||
assertEquals("/some/health/live", fourth.getLivenessProbe().getHttpGet().getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultArgs() {
|
||||
// Arrange
|
||||
PodTemplateSpec additionalPodTemplate = null;
|
||||
|
||||
// Act
|
||||
var podTemplate = getDeployment(additionalPodTemplate).getSpec().getTemplate();
|
||||
|
||||
// Assert
|
||||
assertThat(podTemplate.getSpec().getContainers().get(0).getArgs()).doesNotContain("--optimized");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,25 +19,29 @@ package org.keycloak.operator.testsuite.utils;
|
|||
|
||||
import io.fabric8.kubernetes.api.model.HasMetadata;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.api.model.PodBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.KubernetesClientException;
|
||||
import io.fabric8.kubernetes.client.dsl.ExecWatch;
|
||||
import io.fabric8.kubernetes.client.dsl.Resource;
|
||||
import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil;
|
||||
import io.fabric8.kubernetes.client.utils.Serialization;
|
||||
import io.quarkus.logging.Log;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakSpecBuilder;
|
||||
import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakStatusCondition;
|
||||
import org.keycloak.operator.testsuite.integration.BaseOperatorTest;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
|
@ -48,16 +52,13 @@ public final class K8sUtils {
|
|||
}
|
||||
|
||||
public static Keycloak getDefaultKeycloakDeployment() {
|
||||
Keycloak kc = getResourceFromFile("example-keycloak.yaml", Keycloak.class);
|
||||
kc.getMetadata().setNamespace(BaseOperatorTest.getCurrentNamespace());
|
||||
return kc;
|
||||
return getResourceFromFile("example-keycloak.yaml", Keycloak.class);
|
||||
}
|
||||
|
||||
public static Secret getDefaultTlsSecret() {
|
||||
return getResourceFromFile("example-tls-secret.yaml", Secret.class);
|
||||
}
|
||||
|
||||
|
||||
public static void deployKeycloak(KubernetesClient client, Keycloak kc, boolean waitUntilReady) {
|
||||
deployKeycloak(client, kc, waitUntilReady, true);
|
||||
}
|
||||
|
@ -83,6 +84,10 @@ public final class K8sUtils {
|
|||
set(client, getDefaultTlsSecret());
|
||||
}
|
||||
|
||||
// speed the cleanup of pods
|
||||
kc.setSpec(new KeycloakSpecBuilder(kc.getSpec()).editOrNewUnsupported().editOrNewPodTemplate().editOrNewSpec()
|
||||
.withTerminationGracePeriodSeconds(0L).endSpec().endPodTemplate().endUnsupported().build());
|
||||
|
||||
set(client, kc);
|
||||
|
||||
if (waitUntilReady) {
|
||||
|
@ -90,10 +95,6 @@ public final class K8sUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void deployDefaultKeycloak(KubernetesClient client) {
|
||||
deployKeycloak(client, getDefaultKeycloakDeployment(), true);
|
||||
}
|
||||
|
||||
public static void waitForKeycloakToBeReady(KubernetesClient client, Keycloak kc) {
|
||||
Log.infof("Waiting for Keycloak \"%s\"", kc.getMetadata().getName());
|
||||
Awaitility.await()
|
||||
|
@ -113,37 +114,37 @@ public final class K8sUtils {
|
|||
}
|
||||
|
||||
public static String inClusterCurl(KubernetesClient k8sclient, String namespace, String... args) {
|
||||
var podName = KubernetesResourceUtil.sanitizeName("curl-" + UUID.randomUUID());
|
||||
var podName = "curl-pod";
|
||||
try {
|
||||
Pod curlPod = k8sclient.run().inNamespace(namespace)
|
||||
.withNewRunConfig()
|
||||
.withArgs(args)
|
||||
.withName(podName)
|
||||
.withImage("curlimages/curl:7.78.0")
|
||||
.withRestartPolicy("Never")
|
||||
.done();
|
||||
Log.info("Waiting for curl Pod to finish running");
|
||||
Awaitility.await().atMost(3, TimeUnit.MINUTES)
|
||||
.until(() -> {
|
||||
String phase =
|
||||
k8sclient.pods().inNamespace(namespace).withName(podName).get()
|
||||
.getStatus().getPhase();
|
||||
return phase.equals("Succeeded") || phase.equals("Failed");
|
||||
});
|
||||
Pod curlPod = new PodBuilder().withNewMetadata().withName(podName).endMetadata().withNewSpec()
|
||||
.addNewContainer()
|
||||
.withImage("curlimages/curl:8.1.2")
|
||||
.withCommand("sh")
|
||||
.withName("curl")
|
||||
.withStdin()
|
||||
.endContainer()
|
||||
.endSpec()
|
||||
.build();
|
||||
|
||||
String curlOutput =
|
||||
k8sclient.pods().inNamespace(namespace)
|
||||
.withName(curlPod.getMetadata().getName()).getLog();
|
||||
try {
|
||||
k8sclient.resource(curlPod).create();
|
||||
} catch (KubernetesClientException e) {
|
||||
if (e.getCode() != HttpURLConnection.HTTP_CONFLICT) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return curlOutput;
|
||||
} catch (KubernetesClientException ex) {
|
||||
throw new AssertionError(ex);
|
||||
} finally {
|
||||
Log.info("Deleting curl Pod");
|
||||
k8sclient.pods().inNamespace(namespace).withName(podName).delete();
|
||||
Awaitility.await().atMost(2, TimeUnit.MINUTES)
|
||||
.until(() -> k8sclient.pods().inNamespace(namespace).withName(podName)
|
||||
.get() == null);
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
try (ExecWatch watch = k8sclient.pods().resource(curlPod).withReadyWaitTimeout(60000)
|
||||
.writingOutput(output)
|
||||
.exec(Stream.concat(Stream.of("curl"), Stream.of(args)).toArray(String[]::new))) {
|
||||
watch.exitCode().get(15, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
return output.toString(StandardCharsets.UTF_8);
|
||||
} catch (Exception ex) {
|
||||
throw KubernetesClientException.launderThrowable(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue