diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBridgeCluster.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBridgeCluster.java index cce17c55e9..c2b77f2828 100644 --- a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBridgeCluster.java +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBridgeCluster.java @@ -87,7 +87,6 @@ public class KafkaBridgeCluster extends AbstractModel implements SupportsLogging // Kafka Bridge configuration keys (EnvVariables) protected static final String ENV_VAR_PREFIX = "KAFKA_BRIDGE_"; protected static final String ENV_VAR_KAFKA_BRIDGE_METRICS_ENABLED = "KAFKA_BRIDGE_METRICS_ENABLED"; - protected static final String ENV_VAR_KAFKA_BRIDGE_TLS = "KAFKA_BRIDGE_TLS"; protected static final String ENV_VAR_KAFKA_BRIDGE_TRUSTED_CERTS = "KAFKA_BRIDGE_TRUSTED_CERTS"; protected static final String OAUTH_TLS_CERTS_BASE_VOLUME_MOUNT = "/opt/strimzi/oauth-certs/"; diff --git a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBridgeClusterTest.java b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBridgeClusterTest.java index 873df9fc45..2b51e20a1a 100644 --- a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBridgeClusterTest.java +++ b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBridgeClusterTest.java @@ -241,7 +241,6 @@ public void testGenerateDeployment() { assertThat(dep.getSpec().getStrategy().getType(), is("RollingUpdate")); assertThat(dep.getSpec().getStrategy().getRollingUpdate().getMaxSurge().getIntVal(), is(1)); assertThat(dep.getSpec().getStrategy().getRollingUpdate().getMaxUnavailable().getIntVal(), is(0)); - assertThat(io.strimzi.operator.cluster.TestUtils.containerEnvVars(dep.getSpec().getTemplate().getSpec().getContainers().get(0)).get(KafkaBridgeCluster.ENV_VAR_KAFKA_BRIDGE_TLS), is(nullValue())); assertThat(dep.getSpec().getTemplate().getSpec().getVolumes().stream() .filter(volume -> volume.getName().equalsIgnoreCase("strimzi-tmp")) .findFirst().get().getEmptyDir().getSizeLimit(), is(new Quantity(VolumeUtils.STRIMZI_TMP_DIRECTORY_DEFAULT_SIZE))); @@ -968,6 +967,50 @@ public void testNullClusterRoleBinding() { assertThat(crb, is(nullValue())); } + @ParallelTest + public void testKafkaBridgeContainerEnvVarsConflict() { + ContainerEnvVar envVar1 = new ContainerEnvVar(); + String testEnvOneKey = KafkaBridgeCluster.ENV_VAR_KAFKA_BRIDGE_METRICS_ENABLED; + String testEnvOneValue = "false"; + envVar1.setName(testEnvOneKey); + envVar1.setValue(testEnvOneValue); + + ContainerEnvVar envVar2 = new ContainerEnvVar(); + String testEnvTwoKey = KafkaBridgeCluster.ENV_VAR_KAFKA_BRIDGE_TRUSTED_CERTS; + String testEnvTwoValue = "PEM certs"; + envVar2.setName(testEnvTwoKey); + envVar2.setValue(testEnvTwoValue); + + List testEnvs = new ArrayList<>(); + testEnvs.add(envVar1); + testEnvs.add(envVar2); + ContainerTemplate kafkaBridgeContainer = new ContainerTemplate(); + kafkaBridgeContainer.setEnv(testEnvs); + + KafkaBridge resource = new KafkaBridgeBuilder(this.resource) + .editSpec() + .withNewTls() + .addNewTrustedCertificate() + .withSecretName("tls-trusted-certificate") + .withCertificate("pem-content") + .endTrustedCertificate() + .endTls() + .withNewTemplate() + .withBridgeContainer(kafkaBridgeContainer) + .endTemplate() + .endSpec() + .build(); + + List kafkaEnvVars = KafkaBridgeCluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, resource, SHARED_ENV_PROVIDER).getEnvVars(); + + assertThat("Failed to prevent over writing existing container environment variable: " + testEnvOneKey, + kafkaEnvVars.stream().filter(env -> testEnvOneKey.equals(env.getName())) + .map(EnvVar::getValue).findFirst().orElse("").equals(testEnvOneValue), is(false)); + assertThat("Failed to prevent over writing existing container environment variable: " + testEnvTwoKey, + kafkaEnvVars.stream().filter(env -> testEnvTwoKey.equals(env.getName())) + .map(EnvVar::getValue).findFirst().orElse("").equals(testEnvTwoValue), is(false)); + } + @ParallelTest public void testGenerateDeploymentWithOAuthWithAccessToken() { KafkaBridge resource = new KafkaBridgeBuilder(this.resource) diff --git a/development-docs/systemtests/io.strimzi.systemtest.bridge.HttpBridgeST.md b/development-docs/systemtests/io.strimzi.systemtest.bridge.HttpBridgeST.md index 17c6c274ad..2faf9ea70d 100644 --- a/development-docs/systemtests/io.strimzi.systemtest.bridge.HttpBridgeST.md +++ b/development-docs/systemtests/io.strimzi.systemtest.bridge.HttpBridgeST.md @@ -34,6 +34,26 @@ * [bridge](labels/bridge.md) +## testCustomAndUpdatedValues + +**Description:** Test that validates the creation, update, and verification of a Kafka Bridge with specific initial and updated configurations. + +**Steps:** + +| Step | Action | Result | +| - | - | - | +| 1. | Create a Kafka Bridge resource with initial configuration. | Kafka Bridge is created and deployed with the specified initial configuration. | +| 2. | Remove an environment variable that is in use. | Environment variable TEST_ENV_1 is removed from the initial configuration. | +| 3. | Verify initial probe values and environment variables. | The probe values and environment variables match the initial configuration. | +| 4. | Update Kafka Bridge resource with new configuration. | Kafka Bridge is updated and redeployed with the new configuration. | +| 5. | Verify updated probe values and environment variables. | The probe values and environment variables match the updated configuration. | +| 6. | Verify Kafka Bridge configurations for producer and consumer. | Producer and consumer configurations match the updated settings. | + +**Labels:** + +* [bridge](labels/bridge.md) + + ## testCustomBridgeLabelsAreProperlySet **Description:** Test verifying if custom labels and annotations for Kafka Bridge services are properly set and validated. diff --git a/development-docs/systemtests/labels/bridge.md b/development-docs/systemtests/labels/bridge.md index de8617771a..9ec7defc1a 100644 --- a/development-docs/systemtests/labels/bridge.md +++ b/development-docs/systemtests/labels/bridge.md @@ -8,13 +8,14 @@ These tests ensure that the bridge behaves as expected under various configurati **Tests:** -- [testScaleBridgeSubresource](../io.strimzi.systemtest.bridge.HttpBridgeST.md) -- [testSendSimpleMessage](../io.strimzi.systemtest.bridge.HttpBridgeST.md) - [testReceiveSimpleMessageTlsScramSha](../io.strimzi.systemtest.bridge.HttpBridgeScramShaST.md) - [testBridgeLogSetting](../io.strimzi.systemtest.log.LogSettingST.md) +- [testSendSimpleMessageTls](../io.strimzi.systemtest.bridge.HttpBridgeTlsST.md) +- [testCustomAndUpdatedValues](../io.strimzi.systemtest.bridge.HttpBridgeST.md) +- [testScaleBridgeSubresource](../io.strimzi.systemtest.bridge.HttpBridgeST.md) +- [testSendSimpleMessage](../io.strimzi.systemtest.bridge.HttpBridgeST.md) - [testReceiveSimpleMessage](../io.strimzi.systemtest.bridge.HttpBridgeST.md) - [testCorsOriginAllowed](../io.strimzi.systemtest.bridge.HttpBridgeCorsST.md) -- [testSendSimpleMessageTls](../io.strimzi.systemtest.bridge.HttpBridgeTlsST.md) - [testCorsForbidden](../io.strimzi.systemtest.bridge.HttpBridgeCorsST.md) - [testReceiveSimpleMessageTls](../io.strimzi.systemtest.bridge.HttpBridgeTlsST.md) - [testConfigureDeploymentStrategy](../io.strimzi.systemtest.bridge.HttpBridgeST.md) diff --git a/systemtest/src/test/java/io/strimzi/systemtest/bridge/HttpBridgeST.java b/systemtest/src/test/java/io/strimzi/systemtest/bridge/HttpBridgeST.java index 0f3ceb2132..0066568393 100644 --- a/systemtest/src/test/java/io/strimzi/systemtest/bridge/HttpBridgeST.java +++ b/systemtest/src/test/java/io/strimzi/systemtest/bridge/HttpBridgeST.java @@ -48,6 +48,8 @@ import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -59,6 +61,7 @@ import static io.strimzi.test.k8s.KubeClusterResource.cmdKubeClient; import static io.strimzi.test.k8s.KubeClusterResource.kubeClient; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -167,6 +170,118 @@ void testReceiveSimpleMessage() { ClientUtils.waitForClientsSuccess(testStorage.getNamespaceName(), testStorage.getConsumerName(), testStorage.getProducerName(), testStorage.getMessageCount()); } + @ParallelTest + @TestDoc( + description = @Desc("Test that validates the creation, update, and verification of a Kafka Bridge with specific initial and updated configurations."), + steps = { + @Step(value = "Create a Kafka Bridge resource with initial configuration.", expected = "Kafka Bridge is created and deployed with the specified initial configuration."), + @Step(value = "Remove an environment variable that is in use.", expected = "Environment variable TEST_ENV_1 is removed from the initial configuration."), + @Step(value = "Verify initial probe values and environment variables.", expected = "The probe values and environment variables match the initial configuration."), + @Step(value = "Update Kafka Bridge resource with new configuration.", expected = "Kafka Bridge is updated and redeployed with the new configuration."), + @Step(value = "Verify updated probe values and environment variables.", expected = "The probe values and environment variables match the updated configuration."), + @Step(value = "Verify Kafka Bridge configurations for producer and consumer.", expected = "Producer and consumer configurations match the updated settings.") + }, + labels = { + @Label(TestDocsLabels.BRIDGE) + } + ) + void testCustomAndUpdatedValues() { + + String bridgeName = "custom-bridge"; + String usedVariable = "KAFKA_BRIDGE_PRODUCER_CONFIG"; + LinkedHashMap envVarGeneral = new LinkedHashMap<>(); + envVarGeneral.put("TEST_ENV_1", "test.env.one"); + envVarGeneral.put("TEST_ENV_2", "test.env.two"); + envVarGeneral.put(usedVariable, "test.value"); + + LinkedHashMap envVarUpdated = new LinkedHashMap<>(); + envVarUpdated.put("TEST_ENV_2", "updated.test.env.two"); + envVarUpdated.put("TEST_ENV_3", "test.env.three"); + + Map producerConfig = new HashMap<>(); + producerConfig.put("acks", "1"); + + Map consumerConfig = new HashMap<>(); + consumerConfig.put("auto.offset.reset", "earliest"); + + int initialDelaySeconds = 30; + int timeoutSeconds = 10; + int updatedInitialDelaySeconds = 31; + int updatedTimeoutSeconds = 11; + int periodSeconds = 10; + int successThreshold = 1; + int failureThreshold = 3; + int updatedPeriodSeconds = 5; + int updatedFailureThreshold = 1; + + resourceManager.createResourceWithWait(KafkaBridgeTemplates.kafkaBridge(Environment.TEST_SUITE_NAMESPACE, bridgeName, KafkaResources.plainBootstrapAddress(suiteTestStorage.getClusterName()), 1) + .editSpec() + .withNewTemplate() + .withNewBridgeContainer() + .withEnv(StUtils.createContainerEnvVarsFromMap(envVarGeneral)) + .endBridgeContainer() + .endTemplate() + .withNewProducer() + .endProducer() + .withNewConsumer() + .endConsumer() + .withNewReadinessProbe() + .withInitialDelaySeconds(initialDelaySeconds) + .withTimeoutSeconds(timeoutSeconds) + .withPeriodSeconds(periodSeconds) + .withSuccessThreshold(successThreshold) + .withFailureThreshold(failureThreshold) + .endReadinessProbe() + .withNewLivenessProbe() + .withInitialDelaySeconds(initialDelaySeconds) + .withTimeoutSeconds(timeoutSeconds) + .withPeriodSeconds(periodSeconds) + .withSuccessThreshold(successThreshold) + .withFailureThreshold(failureThreshold) + .endLivenessProbe() + .endSpec() + .build()); + + Map bridgeSnapshot = DeploymentUtils.depSnapshot(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName)); + + // Remove variable which is already in use + envVarGeneral.remove(usedVariable); + LOGGER.info("Verifying values before update"); + VerificationUtils.verifyReadinessAndLivenessProbes(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName), KafkaBridgeResources.componentName(bridgeName), initialDelaySeconds, timeoutSeconds, + periodSeconds, successThreshold, failureThreshold); + VerificationUtils.verifyContainerEnvVariables(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName), KafkaBridgeResources.componentName(bridgeName), envVarGeneral); + + LOGGER.info("Check if actual env variable {} has different value than {}", usedVariable, "test.value"); + assertThat( + StUtils.checkEnvVarInPod(Environment.TEST_SUITE_NAMESPACE, kubeClient().listPods(Environment.TEST_SUITE_NAMESPACE, suiteTestStorage.getClusterName(), Labels.STRIMZI_KIND_LABEL, KafkaBridge.RESOURCE_KIND).get(0).getMetadata().getName(), usedVariable), + is(not("test.value")) + ); + + LOGGER.info("Updating values in Bridge container"); + KafkaBridgeResource.replaceBridgeResourceInSpecificNamespace(Environment.TEST_SUITE_NAMESPACE, bridgeName, kb -> { + kb.getSpec().getTemplate().getBridgeContainer().setEnv(StUtils.createContainerEnvVarsFromMap(envVarUpdated)); + kb.getSpec().getProducer().setConfig(producerConfig); + kb.getSpec().getConsumer().setConfig(consumerConfig); + kb.getSpec().getLivenessProbe().setInitialDelaySeconds(updatedInitialDelaySeconds); + kb.getSpec().getReadinessProbe().setInitialDelaySeconds(updatedInitialDelaySeconds); + kb.getSpec().getLivenessProbe().setTimeoutSeconds(updatedTimeoutSeconds); + kb.getSpec().getReadinessProbe().setTimeoutSeconds(updatedTimeoutSeconds); + kb.getSpec().getLivenessProbe().setPeriodSeconds(updatedPeriodSeconds); + kb.getSpec().getReadinessProbe().setPeriodSeconds(updatedPeriodSeconds); + kb.getSpec().getLivenessProbe().setFailureThreshold(updatedFailureThreshold); + kb.getSpec().getReadinessProbe().setFailureThreshold(updatedFailureThreshold); + }); + + DeploymentUtils.waitTillDepHasRolled(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName), 1, bridgeSnapshot); + + LOGGER.info("Verifying values after update"); + VerificationUtils.verifyReadinessAndLivenessProbes(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName), KafkaBridgeResources.componentName(bridgeName), updatedInitialDelaySeconds, updatedTimeoutSeconds, + updatedPeriodSeconds, successThreshold, updatedFailureThreshold); + VerificationUtils.verifyContainerEnvVariables(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName), KafkaBridgeResources.componentName(bridgeName), envVarUpdated); + VerificationUtils.verifyComponentConfiguration(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName), KafkaBridgeResources.componentName(bridgeName), "KAFKA_BRIDGE_PRODUCER_CONFIG", producerConfig); + VerificationUtils.verifyComponentConfiguration(Environment.TEST_SUITE_NAMESPACE, KafkaBridgeResources.componentName(bridgeName), KafkaBridgeResources.componentName(bridgeName), "KAFKA_BRIDGE_CONSUMER_CONFIG", consumerConfig); + } + @ParallelTest @TestDoc( description = @Desc("Test verifying the presence and correctness of the discovery annotation in the Kafka Bridge service."),