From 1e36823d816b916033954237a4fbd0bee8329284 Mon Sep 17 00:00:00 2001 From: Ivan Zlenko <241953+ivanzlenko@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:02:06 +0400 Subject: [PATCH 1/3] IGNITE-28037 Fix deleted key prefix for distributed config --- .../configuration/ConfigurationRegistry.java | 26 +++++ .../ItDeletedPrefixConfigurationTest.java | 99 +++++++++++++++++++ ...butedDeletedPrefixConfigurationModule.java | 40 ++++++++ ...LocalDeletedPrefixConfigurationModule.java | 40 ++++++++ ...e.ignite.configuration.ConfigurationModule | 2 + .../ignite/internal/app/IgniteImpl.java | 17 ++-- 6 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java create mode 100644 modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java create mode 100644 modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java create mode 100644 modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationRegistry.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationRegistry.java index c5a17433a52c..4da72657fdb1 100644 --- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationRegistry.java +++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationRegistry.java @@ -29,6 +29,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +import org.apache.ignite.configuration.ConfigurationModule; import org.apache.ignite.configuration.ConfigurationTree; import org.apache.ignite.configuration.KeyIgnorer; import org.apache.ignite.configuration.RootKey; @@ -264,4 +265,29 @@ public KeyIgnorer keyIgnorer() { public long notificationCount() { return changer.notificationCount(); } + + /** + * Creates an instance of {@code ConfigurationRegistry}. + * + * @param configurationModule the module containing configuration root keys, migration logic, and deleted prefixes. + * @param storage the storage system to persist configuration data. + * @param generator the generator responsible for creating the configuration tree structure. + * @param configurationValidator the validator ensuring the correctness of configuration updates. + * @return a new {@code ConfigurationRegistry} instance initialized with the specified parameters. + */ + public static ConfigurationRegistry create( + ConfigurationModule configurationModule, + ConfigurationStorage storage, + ConfigurationTreeGenerator generator, + ConfigurationValidator configurationValidator + ) { + return new ConfigurationRegistry( + configurationModule.rootKeys(), + storage, + generator, + configurationValidator, + configurationModule::migrateDeprecatedConfigurations, + KeyIgnorer.fromDeletedPrefixes(configurationModule.deletedPrefixes()) + ); + } } diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java new file mode 100644 index 000000000000..a86fa098591b --- /dev/null +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.ignite.internal.configuration; + +import static org.apache.ignite.internal.ConfigTemplates.NODE_BOOTSTRAP_CFG_TEMPLATE; +import static org.apache.ignite.internal.configuration.TestDistributedDeletedPrefixConfigurationModule.DELETED_DISTRIBUTED_PREFIX; +import static org.apache.ignite.internal.configuration.TestLocalDeletedPrefixConfigurationModule.DELETED_LOCAL_PREFIX; +import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.ignite.configuration.ConfigurationModule; +import org.apache.ignite.configuration.KeyIgnorer; +import org.apache.ignite.internal.ClusterPerClassIntegrationTest; +import org.apache.ignite.internal.app.IgniteImpl; +import org.apache.ignite.internal.configuration.presentation.HoconPresentation; +import org.junit.jupiter.api.Test; + +/** + * Integration tests verifying that {@link IgniteImpl} correctly wires deleted prefixes from each {@link ConfigurationModule} + * into the corresponding {@link ConfigurationRegistry} via {@link ConfigurationRegistry#create}. + */ +public class ItDeletedPrefixConfigurationTest extends ClusterPerClassIntegrationTest { + @Override + protected int initialNodes() { + return 1; + } + + @Override + protected String getNodeBootstrapConfigTemplate() { + return NODE_BOOTSTRAP_CFG_TEMPLATE.substring(0, NODE_BOOTSTRAP_CFG_TEMPLATE.lastIndexOf('}')) + + " testDeletedLocalProp = \"old_value\"\n}"; + } + + /** + * Verifies that the local configuration registry's {@link KeyIgnorer} recognizes the local deleted prefix + * but not the distributed deleted prefix. + */ + @Test + void testLocalRegistryKeyIgnorerRecognizesLocalDeletedPrefix() { + ConfigurationRegistry nodeConfig = igniteImpl(0).nodeConfiguration(); + + assertTrue(nodeConfig.keyIgnorer().shouldIgnore(DELETED_LOCAL_PREFIX), + "Local registry must ignore local deleted prefix"); + assertFalse(nodeConfig.keyIgnorer().shouldIgnore(DELETED_DISTRIBUTED_PREFIX), + "Local registry must NOT ignore distributed deleted prefix"); + } + + /** + * Verifies that the distributed configuration registry's {@link KeyIgnorer} recognizes the distributed deleted prefix + * but not the local deleted prefix. + */ + @Test + void testDistributedRegistryKeyIgnorerRecognizesDistributedDeletedPrefix() { + ConfigurationRegistry clusterConfig = igniteImpl(0).clusterConfiguration(); + + assertTrue(clusterConfig.keyIgnorer().shouldIgnore(DELETED_DISTRIBUTED_PREFIX), + "Distributed registry must ignore distributed deleted prefix"); + assertFalse(clusterConfig.keyIgnorer().shouldIgnore(DELETED_LOCAL_PREFIX), + "Distributed registry must NOT ignore local deleted prefix"); + } + + /** + * Verifies that the node starts and the cluster initializes with deleted properties in both local and distributed configs. + */ + @Test + void testNodeStartsAndInitializesWithDeletedProperties() { + // Verify the deleted local property was dropped and is absent from local config. + String localConfigHocon = new HoconPresentation(igniteImpl(0).nodeConfiguration()).represent(); + assertFalse(localConfigHocon.contains("testDeletedLocalProp"), + "Deleted local property must not be present in local config after startup"); + + // Verify that applying the deleted distributed property via HoconPresentation succeeds. + HoconPresentation clusterPresentation = new HoconPresentation(igniteImpl(0).clusterConfiguration()); + assertThat(clusterPresentation.update("ignite.testDeletedDistribProp = \"old_value\""), + willCompleteSuccessfully()); + + // Verify the deleted distributed property was dropped and is absent from distributed config. + String clusterConfigHocon = clusterPresentation.represent(); + assertFalse(clusterConfigHocon.contains("testDeletedDistribProp"), + "Deleted distributed property must not be present in distributed config after update"); + } +} diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java new file mode 100644 index 000000000000..0221d7fcaba9 --- /dev/null +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.ignite.internal.configuration; + +import java.util.Collection; +import java.util.Set; +import org.apache.ignite.configuration.ConfigurationModule; +import org.apache.ignite.configuration.annotation.ConfigurationType; + +/** + * Test {@link ConfigurationModule} with a DISTRIBUTED deleted prefix. + */ +public class TestDistributedDeletedPrefixConfigurationModule implements ConfigurationModule { + static final String DELETED_DISTRIBUTED_PREFIX = "ignite.testDeletedDistribProp"; + + @Override + public ConfigurationType type() { + return ConfigurationType.DISTRIBUTED; + } + + @Override + public Collection deletedPrefixes() { + return Set.of(DELETED_DISTRIBUTED_PREFIX); + } +} diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java new file mode 100644 index 000000000000..12f3df032da3 --- /dev/null +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.ignite.internal.configuration; + +import java.util.Collection; +import java.util.Set; +import org.apache.ignite.configuration.ConfigurationModule; +import org.apache.ignite.configuration.annotation.ConfigurationType; + +/** + * Test {@link ConfigurationModule} with a LOCAL deleted prefix. + */ +public class TestLocalDeletedPrefixConfigurationModule implements ConfigurationModule { + static final String DELETED_LOCAL_PREFIX = "ignite.testDeletedLocalProp"; + + @Override + public ConfigurationType type() { + return ConfigurationType.LOCAL; + } + + @Override + public Collection deletedPrefixes() { + return Set.of(DELETED_LOCAL_PREFIX); + } +} diff --git a/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule b/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule new file mode 100644 index 000000000000..58aec5ea75e9 --- /dev/null +++ b/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule @@ -0,0 +1,2 @@ +org.apache.ignite.internal.configuration.TestLocalDeletedPrefixConfigurationModule +org.apache.ignite.internal.configuration.TestDistributedDeletedPrefixConfigurationModule \ No newline at end of file diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java index ce7c2cfda0d7..39de9eee97b1 100644 --- a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java +++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java @@ -65,7 +65,6 @@ import org.apache.ignite.client.handler.configuration.ClientConnectorExtensionConfiguration; import org.apache.ignite.compute.IgniteCompute; import org.apache.ignite.configuration.ConfigurationDynamicDefaultsPatcher; -import org.apache.ignite.configuration.KeyIgnorer; import org.apache.ignite.internal.catalog.CatalogManager; import org.apache.ignite.internal.catalog.CatalogManagerImpl; import org.apache.ignite.internal.catalog.DataNodesAwarePartitionCountCalculator; @@ -585,13 +584,11 @@ public class IgniteImpl implements Ignite { ConfigurationValidator localConfigurationValidator = ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators()); - nodeConfigRegistry = new ConfigurationRegistry( - modules.local().rootKeys(), + nodeConfigRegistry = ConfigurationRegistry.create( + modules.local(), localFileConfigurationStorage, localConfigurationGenerator, - localConfigurationValidator, - modules.local()::migrateDeprecatedConfigurations, - KeyIgnorer.fromDeletedPrefixes(modules.local().deletedPrefixes()) + localConfigurationValidator ); // Start local configuration to be able to read all local properties. @@ -810,13 +807,11 @@ public class IgniteImpl implements Ignite { cfgStorage = new DistributedConfigurationStorage(name, metaStorageMgr); - clusterConfigRegistry = new ConfigurationRegistry( - modules.distributed().rootKeys(), + clusterConfigRegistry = ConfigurationRegistry.create( + modules.distributed(), cfgStorage, distributedConfigurationGenerator, - distributedCfgValidator, - modules.distributed()::migrateDeprecatedConfigurations, - KeyIgnorer.fromDeletedPrefixes(modules.local().deletedPrefixes()) + distributedCfgValidator ); metricManager.configure(clusterConfigRegistry.getConfiguration(MetricExtensionConfiguration.KEY).metrics()); From d16bc51f1ff719a97e70e2aa0e885e431c98407e Mon Sep 17 00:00:00 2001 From: Ivan Zlenko <241953+ivanzlenko@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:16:00 +0400 Subject: [PATCH 2/3] IGNITE-28037 Fix review comments --- modules/runner/build.gradle | 2 ++ .../configuration/ItDeletedPrefixConfigurationTest.java | 7 +++++-- .../TestDistributedDeletedPrefixConfigurationModule.java | 2 ++ .../TestLocalDeletedPrefixConfigurationModule.java | 2 ++ .../org.apache.ignite.configuration.ConfigurationModule | 2 -- 5 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule diff --git a/modules/runner/build.gradle b/modules/runner/build.gradle index 5c7a7d3825c7..fb38f6c2eace 100644 --- a/modules/runner/build.gradle +++ b/modules/runner/build.gradle @@ -131,6 +131,7 @@ dependencies { testImplementation libs.awaitility integrationTestAnnotationProcessor project(':ignite-configuration-annotation-processor') + integrationTestAnnotationProcessor libs.auto.service integrationTestAnnotationProcessor libs.jmh.annotation.processor integrationTestImplementation project(':ignite-partition-distribution') integrationTestImplementation project(':ignite-jdbc') @@ -198,6 +199,7 @@ dependencies { integrationTestImplementation testFixtures(project(':ignite-raft')) integrationTestImplementation testFixtures(project(':ignite-replicator')) integrationTestImplementation testFixtures(project(':ignite-catalog')) + integrationTestImplementation libs.auto.service.annotations integrationTestImplementation libs.awaitility integrationTestImplementation libs.rocksdb.jni integrationTestImplementation libs.disruptor diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java index a86fa098591b..dd7162754301 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java @@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.typesafe.config.parser.ConfigDocument; +import com.typesafe.config.parser.ConfigDocumentFactory; import org.apache.ignite.configuration.ConfigurationModule; import org.apache.ignite.configuration.KeyIgnorer; import org.apache.ignite.internal.ClusterPerClassIntegrationTest; @@ -44,8 +46,9 @@ protected int initialNodes() { @Override protected String getNodeBootstrapConfigTemplate() { - return NODE_BOOTSTRAP_CFG_TEMPLATE.substring(0, NODE_BOOTSTRAP_CFG_TEMPLATE.lastIndexOf('}')) - + " testDeletedLocalProp = \"old_value\"\n}"; + ConfigDocument document = ConfigDocumentFactory.parseString(super.getNodeBootstrapConfigTemplate()) + .withValueText("ignite.testDeletedLocalProp", "old_value"); + return document.render(); } /** diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java index 0221d7fcaba9..0887f8520a4b 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestDistributedDeletedPrefixConfigurationModule.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.configuration; +import com.google.auto.service.AutoService; import java.util.Collection; import java.util.Set; import org.apache.ignite.configuration.ConfigurationModule; @@ -25,6 +26,7 @@ /** * Test {@link ConfigurationModule} with a DISTRIBUTED deleted prefix. */ +@AutoService(ConfigurationModule.class) public class TestDistributedDeletedPrefixConfigurationModule implements ConfigurationModule { static final String DELETED_DISTRIBUTED_PREFIX = "ignite.testDeletedDistribProp"; diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java index 12f3df032da3..8248ef20e710 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/TestLocalDeletedPrefixConfigurationModule.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.configuration; +import com.google.auto.service.AutoService; import java.util.Collection; import java.util.Set; import org.apache.ignite.configuration.ConfigurationModule; @@ -25,6 +26,7 @@ /** * Test {@link ConfigurationModule} with a LOCAL deleted prefix. */ +@AutoService(ConfigurationModule.class) public class TestLocalDeletedPrefixConfigurationModule implements ConfigurationModule { static final String DELETED_LOCAL_PREFIX = "ignite.testDeletedLocalProp"; diff --git a/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule b/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule deleted file mode 100644 index 58aec5ea75e9..000000000000 --- a/modules/runner/src/integrationTest/resources/META-INF/services/org.apache.ignite.configuration.ConfigurationModule +++ /dev/null @@ -1,2 +0,0 @@ -org.apache.ignite.internal.configuration.TestLocalDeletedPrefixConfigurationModule -org.apache.ignite.internal.configuration.TestDistributedDeletedPrefixConfigurationModule \ No newline at end of file From fed210476572d690e4e970dc75d0285a757417ee Mon Sep 17 00:00:00 2001 From: Ivan Zlenko <241953+ivanzlenko@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:10:35 +0400 Subject: [PATCH 3/3] IGNITE-28037 Fix checkstyle --- .../internal/configuration/ItDeletedPrefixConfigurationTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java index dd7162754301..f3ea751b560e 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDeletedPrefixConfigurationTest.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.configuration; -import static org.apache.ignite.internal.ConfigTemplates.NODE_BOOTSTRAP_CFG_TEMPLATE; import static org.apache.ignite.internal.configuration.TestDistributedDeletedPrefixConfigurationModule.DELETED_DISTRIBUTED_PREFIX; import static org.apache.ignite.internal.configuration.TestLocalDeletedPrefixConfigurationModule.DELETED_LOCAL_PREFIX; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;