You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ib...@apache.org on 2025/04/30 05:39:37 UTC
(ignite-3) branch main updated: IGNITE-25048 Support configuration deprecation (#5714)
This is an automated email from the ASF dual-hosted git repository.
ibessonov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new bc6fa5451d3 IGNITE-25048 Support configuration deprecation (#5714)
bc6fa5451d3 is described below
commit bc6fa5451d3163f53dad8d6c6c5904f81fca7a57
Author: Ivan Bessonov <be...@gmail.com>
AuthorDate: Wed Apr 30 08:39:32 2025 +0300
IGNITE-25048 Support configuration deprecation (#5714)
---
.../java/org/apache/ignite/client/TestServer.java | 3 +-
.../processor/ConfigurationProcessor.java | 24 +-
.../ignite/configuration/ConfigurationModule.java | 19 +
.../presentation/HoconPresentationTest.java | 3 +-
.../configuration/ConfigurationChanger.java | 63 ++-
.../configuration/ConfigurationManager.java | 6 +-
.../configuration/ConfigurationMigrator.java | 33 ++
.../configuration/ConfigurationRegistry.java | 12 +-
.../configuration/util/ConfigurationFlattener.java | 65 ++-
.../configuration/util/ConfigurationUtil.java | 28 +-
.../configuration/ConfigurationChangerTest.java | 6 +-
.../configuration/ConfigurationRegistryTest.java | 27 +-
.../InjectedValueConfigurationTest.java | 3 +-
.../asm/ConfigurationTreeGeneratorTest.java | 3 +-
.../deprecation/DeprecatedConfigurationTest.java | 459 +++++++++++++++++++++
.../configuration/direct/DirectPropertiesTest.java | 3 +-
.../configuration/hocon/HoconConverterTest.java | 3 +-
.../ConfigurationAnyListenerTest.java | 3 +-
.../notifications/ConfigurationListenerTest.java | 3 +-
.../internal/configuration/sample/UsageTest.java | 6 +-
.../configuration/tree/InternalIdTest.java | 3 +-
.../configuration/tree/NamedListNodeTest.java | 3 +-
.../configuration/util/ConfigurationUtilTest.java | 6 +-
.../configuration/TestConfigurationChanger.java | 10 +-
...niteDistributionZoneManagerNodeRestartTest.java | 6 +-
.../rebalance/ItRebalanceDistributedTest.java | 6 +-
.../metastorage/server/WatchProcessor.java | 2 +-
.../network/utils/ClusterServiceTestUtils.java | 3 +-
.../partition/replicator/fixtures/Node.java | 6 +-
.../ignite/internal/rest/RestComponentTest.java | 3 +-
.../internal/rest/configuration/TestFactory.java | 3 +-
.../configuration/generator/DefaultsGenerator.java | 2 +-
.../ItDistributedConfigurationPropertiesTest.java | 3 +-
.../runner/app/ItIgniteNodeRestartTest.java | 6 +-
.../org/apache/ignite/internal/app/IgniteImpl.java | 6 +-
.../internal/configuration/CompoundModule.java | 5 +
.../storage/LocalFileConfigurationStorageTest.java | 3 +-
37 files changed, 728 insertions(+), 120 deletions(-)
diff --git a/modules/client/src/test/java/org/apache/ignite/client/TestServer.java b/modules/client/src/test/java/org/apache/ignite/client/TestServer.java
index 34194725490..b7fb490f655 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/TestServer.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/TestServer.java
@@ -183,7 +183,8 @@ public class TestServer implements AutoCloseable {
List.of(NodeConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
ComponentContext componentContext = new ComponentContext();
diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java
index 9139376e79e..477640b3369 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java
+++ b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java
@@ -292,11 +292,16 @@ public class ConfigurationProcessor extends AbstractProcessor {
// Get configuration types (VIEW, CHANGE and so on)
TypeName interfaceGetMethodType = getInterfaceGetMethodType(field);
- MethodSpec interfaceGetMethod = MethodSpec.methodBuilder(fieldName)
+ MethodSpec.Builder builder = MethodSpec.methodBuilder(fieldName)
.addModifiers(PUBLIC, ABSTRACT)
.returns(interfaceGetMethodType)
- .addJavadoc("@see $T#" + field, field.getEnclosingElement())
- .build();
+ .addJavadoc("@see $T#" + field, field.getEnclosingElement());
+
+ if (field.getAnnotation(Deprecated.class) != null) {
+ builder.addAnnotation(Deprecated.class);
+ }
+
+ MethodSpec interfaceGetMethod = builder.build();
configurationInterfaceBuilder.addMethod(interfaceGetMethod);
}
@@ -474,6 +479,11 @@ public class ConfigurationProcessor extends AbstractProcessor {
.addJavadoc("@see $T#" + field, field.getEnclosingElement())
.returns(viewFieldType);
+ boolean isDeprecated = field.getAnnotation(Deprecated.class) != null;
+ if (isDeprecated) {
+ getMtdBuilder.addAnnotation(Deprecated.class);
+ }
+
viewClsBuilder.addMethod(getMtdBuilder.build());
// Read only.
@@ -488,6 +498,10 @@ public class ConfigurationProcessor extends AbstractProcessor {
.addJavadoc("@see $T#" + field, field.getEnclosingElement())
.returns(changeClsName);
+ if (isDeprecated) {
+ changeMtdBuilder.addAnnotation(Deprecated.class);
+ }
+
if (containsAnyAnnotation(field, Value.class, InjectedValue.class)) {
if (schemaFieldType.getKind() == TypeKind.ARRAY) {
changeMtdBuilder.varargs(true);
@@ -503,6 +517,10 @@ public class ConfigurationProcessor extends AbstractProcessor {
.addJavadoc("@see $T#" + field, field.getEnclosingElement())
.returns(changeFieldType);
+ if (isDeprecated) {
+ shortChangeMtdBuilder.addAnnotation(Deprecated.class);
+ }
+
changeClsBuilder.addMethod(shortChangeMtdBuilder.build());
}
diff --git a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
index e94a7993f88..f3e928d1eac 100644
--- a/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
+++ b/modules/configuration-api/src/main/java/org/apache/ignite/configuration/ConfigurationModule.java
@@ -117,4 +117,23 @@ public interface ConfigurationModule {
default void patchConfigurationWithDynamicDefaults(SuperRootChange rootChange) {
// No-op.
}
+
+ /**
+ * Logic to perform configuration migration when Ignite version is upgraded. Main task - replace deprecated configuration values with
+ * their non-deprecated cousins.
+ *
+ * <p>Typical implementation should look something like this:
+ * <pre><code>
+ * var barValue = superRoot.viewRoot(KEY).foo().oldConfiguration().bar()
+ *
+ * if (barValue != BAR_DEFAULT) { // Usually implies explicitly set value.
+ * superRoot.changeRoot(KEY).changeNewFoo().changeBar(barValue)
+ * }
+ * </code></pre>
+ *
+ * @param superRootChange Super root change instance.
+ */
+ default void migrateDeprecatedConfigurations(SuperRootChange superRootChange) {
+ // No-op.
+ }
}
diff --git a/modules/configuration-presentation/src/test/java/org/apache/ignite/internal/configuration/presentation/HoconPresentationTest.java b/modules/configuration-presentation/src/test/java/org/apache/ignite/internal/configuration/presentation/HoconPresentationTest.java
index d72a9c6696e..c8e2dfc4d3a 100644
--- a/modules/configuration-presentation/src/test/java/org/apache/ignite/internal/configuration/presentation/HoconPresentationTest.java
+++ b/modules/configuration-presentation/src/test/java/org/apache/ignite/internal/configuration/presentation/HoconPresentationTest.java
@@ -88,7 +88,8 @@ public class HoconPresentationTest {
List.of(TestRootConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
generator,
- ConfigurationValidatorImpl.withDefaultValidators(generator, Set.of(validator))
+ ConfigurationValidatorImpl.withDefaultValidators(generator, Set.of(validator)),
+ changer -> {}
);
assertThat(cfgRegistry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java
index 009a47da218..5e4df905c86 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationChanger.java
@@ -94,6 +94,9 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
/** Configuration validator. */
private final ConfigurationValidator configurationValidator;
+ /** Configuration migrator. */
+ private final ConfigurationMigrator migrator;
+
/** Storage trees. */
private volatile StorageRoots storageRoots;
@@ -144,8 +147,8 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
/** Immutable forest, so to say. */
private final SuperRoot roots;
- /** Version associated with the currently known storage state. */
- private final long version;
+ /** Full storage data. */
+ private final Data data;
/** Future that signifies update of current configuration. */
private final CompletableFuture<Void> changeFuture = new CompletableFuture<>();
@@ -155,12 +158,12 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
*
* @param rootsWithoutDefaults Forest without the defaults
* @param roots Forest with the defaults filled in
- * @param version Version associated with the currently known storage state.
+ * @param data Configuration storage state.
*/
- private StorageRoots(SuperRoot rootsWithoutDefaults, SuperRoot roots, long version) {
+ private StorageRoots(SuperRoot rootsWithoutDefaults, SuperRoot roots, Data data) {
this.rootsWithoutDefaults = rootsWithoutDefaults;
this.roots = roots;
- this.version = version;
+ this.data = data;
makeImmutable(roots);
makeImmutable(rootsWithoutDefaults);
@@ -203,19 +206,23 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
* @param rootKeys Configuration root keys.
* @param storage Configuration storage.
* @param configurationValidator Configuration validator.
+ * @param migrator Configuration migrator.
* @throws IllegalArgumentException If the configuration type of the root keys is not equal to the storage type.
*/
public ConfigurationChanger(
ConfigurationUpdateListener configurationUpdateListener,
Collection<RootKey<?, ?>> rootKeys,
ConfigurationStorage storage,
- ConfigurationValidator configurationValidator) {
+ ConfigurationValidator configurationValidator,
+ ConfigurationMigrator migrator
+ ) {
checkConfigurationType(rootKeys, storage);
this.configurationUpdateListener = configurationUpdateListener;
this.storage = storage;
this.configurationValidator = configurationValidator;
this.rootKeys = rootKeys.stream().collect(toMap(RootKey::key, identity()));
+ this.migrator = migrator;
}
/**
@@ -292,7 +299,7 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
// The root WITHOUT the defaults is used to calculate which properties to write to the underlying storage,
// in other words it allows us to persist the defaults from the code.
// After the storage listener fires for the first time both roots are supposed to become equal.
- storageRoots = new StorageRoots(superRootNoDefaults, superRoot, data.changeId());
+ storageRoots = new StorageRoots(superRootNoDefaults, superRoot, data);
storage.registerConfigurationListener(configurationStorageListener());
@@ -310,7 +317,7 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
private void persistDefaults() {
// If the storage version is 0, it indicates that the storage is empty.
// In this case, write the defaults along with the initial configuration.
- ConfigurationSource cfgSrc = storageRoots.version == 0 ? initialConfiguration : ConfigurationUtil.EMPTY_CFG_SRC;
+ ConfigurationSource cfgSrc = storageRoots.data.changeId() == 0 ? initialConfiguration : ConfigurationUtil.EMPTY_CFG_SRC;
changeInternally(cfgSrc, true)
.whenComplete((v, e) -> {
@@ -596,7 +603,7 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
// This read and the following comparison MUST be performed while holding read lock.
StorageRoots localRoots = storageRoots;
- if (localRoots.version < storageRevision) {
+ if (localRoots.data.changeId() < storageRevision) {
// Need to wait for the configuration updates from the storage, then try to update again (loop).
return localRoots.changeFuture.thenCompose(v -> changeInternally(src, onStartup));
}
@@ -611,7 +618,11 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
addDefaults(changes);
+ migrator.migrate(new SuperRootChangeImpl(changes));
+
Map<String, Serializable> allChanges = createFlattenedUpdatesMap(localRoots.rootsWithoutDefaults, changes);
+ dropUnnecessarilyDeletedKeys(allChanges, localRoots);
+
if (allChanges.isEmpty() && onStartup) {
// We don't want an empty storage update if this is the initialization changer.
return nullCompletedFuture();
@@ -625,7 +636,7 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
// still try to write the empty update, because local configuration can be obsolete. If this is the case, then the CAS will
// fail and the update will be recalculated and there is a chance that the new local configuration will produce a non-empty
// update.
- return storage.write(allChanges, localRoots.version)
+ return storage.write(allChanges, localRoots.data.changeId())
.thenCompose(casWroteSuccessfully -> {
if (casWroteSuccessfully) {
return localRoots.changeFuture;
@@ -675,7 +686,7 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
long newChangeId = changedEntries.changeId();
- var newStorageRoots = new StorageRoots(newSuperNoDefaults, newSuperRoot, newChangeId);
+ var newStorageRoots = new StorageRoots(newSuperNoDefaults, newSuperRoot, mergeData(oldStorageRoots.data, changedEntries));
rwLock.writeLock().lock();
@@ -700,6 +711,29 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
};
}
+ private static Data mergeData(Data currentData, Data delta) {
+ assert delta.changeId() > currentData.changeId() : currentData.changeId() + " " + delta.changeId();
+
+ Map<String, Serializable> newState = new HashMap<>(currentData.values());
+
+ for (Entry<String, ? extends Serializable> entry : delta.values().entrySet()) {
+ if (entry.getValue() == null) {
+ newState.remove(entry.getKey());
+ } else {
+ newState.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ return new Data(newState, delta.changeId());
+ }
+
+ /**
+ * Remove keys from {@code allChanges}, that are associated with nulls in this map, and already absent in {@link StorageRoots#data}.
+ */
+ private static void dropUnnecessarilyDeletedKeys(Map<String, Serializable> allChanges, StorageRoots localRoots) {
+ allChanges.entrySet().removeIf(entry -> entry.getValue() == null && !localRoots.data.values().containsKey(entry.getKey()));
+ }
+
/**
* Notifies all listeners of the current configuration.
*
@@ -710,7 +744,12 @@ public abstract class ConfigurationChanger implements DynamicConfigurationChange
long notificationCount = notificationListenerCnt.incrementAndGet();
- return configurationUpdateListener.onConfigurationUpdated(null, storageRoots.roots, storageRoots.version, notificationCount);
+ return configurationUpdateListener.onConfigurationUpdated(
+ null,
+ storageRoots.roots,
+ storageRoots.data.changeId(),
+ notificationCount
+ );
}
/** {@inheritDoc} */
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationManager.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationManager.java
index 23c7f81a96a..a99f9947e93 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationManager.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationManager.java
@@ -45,13 +45,15 @@ public class ConfigurationManager implements IgniteComponent {
Collection<RootKey<?, ?>> rootKeys,
ConfigurationStorage storage,
ConfigurationTreeGenerator generator,
- ConfigurationValidator configurationValidator
+ ConfigurationValidator configurationValidator,
+ ConfigurationMigrator migrator
) {
registry = new ConfigurationRegistry(
rootKeys,
storage,
generator,
- configurationValidator
+ configurationValidator,
+ migrator
);
}
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationMigrator.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationMigrator.java
new file mode 100644
index 00000000000..33cb87681d3
--- /dev/null
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/ConfigurationMigrator.java
@@ -0,0 +1,33 @@
+/*
+ * 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 org.apache.ignite.configuration.ConfigurationModule;
+import org.apache.ignite.configuration.SuperRootChange;
+
+/**
+ * Class that is used to perform configuration migration when Ignite version is upgraded. Main task - replace deprecated configuration
+ * values with their non-deprecated cousins. In production code expected to be based on
+ * {@link ConfigurationModule#migrateDeprecatedConfigurations(SuperRootChange)}. Could be anything in tests.
+ *
+ * @see ConfigurationModule#migrateDeprecatedConfigurations(SuperRootChange)
+ */
+@FunctionalInterface
+public interface ConfigurationMigrator {
+ void migrate(SuperRootChange superRoot);
+}
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 ac074ba17b0..e242077e179 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
@@ -63,23 +63,17 @@ public class ConfigurationRegistry implements IgniteComponent {
/**
* Constructor.
- *
- * @param rootKeys Configuration root keys.
- * @param storage Configuration storage.
- * @param generator Configuration tree generator.
- * @param configurationValidator Configuration validator.
- * @throws IllegalArgumentException If the configuration type of the root keys is not equal to the storage type, or if the schema or its
- * extensions are not valid.
*/
public ConfigurationRegistry(
Collection<RootKey<?, ?>> rootKeys,
ConfigurationStorage storage,
ConfigurationTreeGenerator generator,
- ConfigurationValidator configurationValidator
+ ConfigurationValidator configurationValidator,
+ ConfigurationMigrator migrator
) {
checkConfigurationType(rootKeys, storage);
- changer = new ConfigurationChanger(notificationUpdateListener(), rootKeys, storage, configurationValidator) {
+ changer = new ConfigurationChanger(notificationUpdateListener(), rootKeys, storage, configurationValidator, migrator) {
@Override
public InnerNode createRootNode(RootKey<?, ?> rootKey) {
return generator.instantiateNode(rootKey.schemaClass());
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationFlattener.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationFlattener.java
index 282a06cfb5e..f7e8f54af7b 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationFlattener.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationFlattener.java
@@ -114,11 +114,15 @@ public class ConfigurationFlattener {
/** {@inheritDoc} */
@Override
public Void doVisitLeafNode(Field field, String key, Serializable newVal) {
+ boolean isDeprecated = field.isAnnotationPresent(Deprecated.class);
+
// Read same value from old tree.
Serializable oldVal = oldInnerNodesStack.element().traverseChild(key, ConfigurationUtil.leafNodeVisitor(), true);
// Do not put duplicates into the resulting map.
- if (singleTreeTraversal || !Objects.deepEquals(oldVal, newVal)) {
+ if (isDeprecated || singleTreeTraversal || !Objects.deepEquals(oldVal, newVal)) {
+ boolean deletion = this.deletion || isDeprecated;
+
resMap.put(currentKey(), deletion ? null : newVal);
}
@@ -128,14 +132,11 @@ public class ConfigurationFlattener {
/** {@inheritDoc} */
@Override
public Void doVisitInnerNode(Field field, String key, InnerNode newNode) {
+ boolean isDeprecated = field != null && field.isAnnotationPresent(Deprecated.class);
+
// Read same node from old tree.
InnerNode oldNode = oldInnerNodesStack.element().traverseChild(key, ConfigurationUtil.innerNodeVisitor(), true);
- // Skip subtree that has not changed.
- if (oldNode == newNode && !singleTreeTraversal) {
- return null;
- }
-
// In case inner node is null in both trees,
// see LocalFileConfigurationStorageTest#innerNodeWithPartialContent – the node is someConfigurationValue.
if (oldNode == null && newNode == null) {
@@ -143,14 +144,16 @@ public class ConfigurationFlattener {
}
if (oldNode == null) {
- visitAsymmetricInnerNode(newNode, false);
+ visitAsymmetricInnerNode(newNode, isDeprecated);
} else if (oldNode.schemaType() != newNode.schemaType()) {
// At the moment, we do not separate the general fields from the fields of
// specific instances of the polymorphic configuration, so we will assume
// that all the fields have changed, perhaps we will fix this later.
visitAsymmetricInnerNode(oldNode, true);
- visitAsymmetricInnerNode(newNode, false);
+ visitAsymmetricInnerNode(newNode, isDeprecated);
+ } else if (isDeprecated) {
+ visitAsymmetricInnerNode(newNode, true);
} else {
oldInnerNodesStack.push(oldNode);
@@ -165,18 +168,14 @@ public class ConfigurationFlattener {
/** {@inheritDoc} */
@Override
public Void doVisitNamedListNode(Field field, String key, NamedListNode<?> newNode) {
+ boolean isDeprecated = field.isAnnotationPresent(Deprecated.class);
+
// Read same named list node from old tree.
NamedListNode<?> oldNode =
oldInnerNodesStack.element().traverseChild(key, ConfigurationUtil.namedListNodeVisitor(), true);
- // Skip subtree that has not changed.
- if (oldNode == newNode && !singleTreeTraversal) {
- return null;
- }
-
// Old keys ordering can be ignored if we either create or delete everything.
- Map<String, Integer> oldKeysToOrderIdxMap = singleTreeTraversal ? null
- : keysToOrderIdx(oldNode);
+ Map<String, Integer> oldKeysToOrderIdxMap = singleTreeTraversal ? null : keysToOrderIdx(oldNode);
// New keys ordering can be ignored if we delete everything.
Map<String, Integer> newKeysToOrderIdxMap = deletion ? null : keysToOrderIdx(newNode);
@@ -187,7 +186,7 @@ public class ConfigurationFlattener {
String namedListFullKey = currentKey();
withTracking(newNodeInternalId.toString(), false, false, () -> {
- InnerNode newNamedElement = newNode.getInnerNode(newNodeKey);
+ InnerNode newNamedElement = isDeprecated ? null : newNode.getInnerNode(newNodeKey);
String oldNodeKey = oldNode.keyByInternalId(newNodeInternalId);
InnerNode oldNamedElement = oldNode.getInnerNode(oldNodeKey);
@@ -197,27 +196,23 @@ public class ConfigurationFlattener {
return null;
}
- // Skip element that has not changed.
- // Its index can be different though, so we don't "continue" straight away.
- if (singleTreeTraversal || oldNamedElement != newNamedElement) {
- if (newNamedElement == null) {
- visitAsymmetricInnerNode(oldNamedElement, true);
- } else if (oldNamedElement == null) {
- visitAsymmetricInnerNode(newNamedElement, false);
- } else if (newNamedElement.schemaType() != oldNamedElement.schemaType()) {
- // At the moment, we do not separate the general fields from the fields of
- // specific instances of the polymorphic configuration, so we will assume
- // that all the fields have changed, perhaps we will fix this later.
- visitAsymmetricInnerNode(oldNamedElement, true);
-
- visitAsymmetricInnerNode(newNamedElement, false);
- } else {
- oldInnerNodesStack.push(oldNamedElement);
+ if (newNamedElement == null) {
+ visitAsymmetricInnerNode(oldNamedElement, true);
+ } else if (oldNamedElement == null) {
+ visitAsymmetricInnerNode(newNamedElement, isDeprecated);
+ } else if (newNamedElement.schemaType() != oldNamedElement.schemaType()) {
+ // At the moment, we do not separate the general fields from the fields of
+ // specific instances of the polymorphic configuration, so we will assume
+ // that all the fields have changed, perhaps we will fix this later.
+ visitAsymmetricInnerNode(oldNamedElement, true);
+
+ visitAsymmetricInnerNode(newNamedElement, isDeprecated);
+ } else {
+ oldInnerNodesStack.push(oldNamedElement);
- newNamedElement.traverseChildren(this, true);
+ newNamedElement.traverseChildren(this, true);
- oldInnerNodesStack.pop();
- }
+ oldInnerNodesStack.pop();
}
Integer newIdx = newKeysToOrderIdxMap == null ? null : newKeysToOrderIdxMap.get(newNodeKey);
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java
index a0e1a28b967..f2890cc5734 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/util/ConfigurationUtil.java
@@ -38,6 +38,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.RandomAccess;
@@ -223,7 +224,7 @@ public class ConfigurationUtil {
public static Map<String, ?> toPrefixMap(Map<String, ? extends Serializable> rawConfig) {
Map<String, Object> res = new HashMap<>();
- for (Map.Entry<String, ? extends Serializable> entry : rawConfig.entrySet()) {
+ for (Entry<String, ? extends Serializable> entry : rawConfig.entrySet()) {
List<String> keys = split(entry.getKey());
assert keys instanceof RandomAccess : keys.getClass();
@@ -755,9 +756,7 @@ public class ConfigurationUtil {
* @param prefixMap Prefix map, constructed from the storage notification data or its subtree.
*/
public static void compressDeletedEntries(Map<String, ?> prefixMap) {
- for (Iterator<? extends Map.Entry<String, ?>> it = prefixMap.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry<String, ?> entry = it.next();
-
+ for (Entry<String, ?> entry : prefixMap.entrySet()) {
Object value = entry.getValue();
if (value instanceof Map) {
@@ -768,10 +767,6 @@ public class ConfigurationUtil {
if (map.containsKey(NamedListNode.NAME) && map.get(NamedListNode.NAME) == null) {
entry.setValue(null);
}
- } else if (value == null) {
- // If there was a change in the type of polymorphic configuration,
- // then the fields of the old configuration will be {@code null}, so we can get rid of them.
- it.remove();
}
}
@@ -998,7 +993,9 @@ public class ConfigurationUtil {
return;
}
- for (Map.Entry<String, ?> entry : map.entrySet()) {
+ assert node instanceof InnerNode : node;
+
+ for (Entry<String, ?> entry : map.entrySet()) {
String key = entry.getKey();
Object val = entry.getValue();
@@ -1010,7 +1007,16 @@ public class ConfigurationUtil {
}
if (val == null) {
- node.construct(key, null, true);
+ try {
+ // If we received a null value, there are two options:
+ // - we changed a type of the polymorphic configuration, and some values must disappear. We'll get an exception.
+ // - we deleted deprecated configuration value from configuration storage. The value in tree must be replaced with
+ // default in such a case.
+ ((InnerNode) node).constructDefault(key);
+ } catch (NoSuchElementException ignore) {
+ assert ((InnerNode) node).isPolymorphic()
+ : "Constructing property " + key + " failed in " + node + " and it is not polymorphic.";
+ }
} else if (val instanceof Map) {
node.construct(key, new InnerConfigurationSource((Map<String, ?>) val), true);
} else {
@@ -1034,7 +1040,7 @@ public class ConfigurationUtil {
// This list must be mutable and RandomAccess.
var orderedKeys = new ArrayList<>(((NamedListView<?>) node).namedListKeys());
- for (Map.Entry<String, ?> entry : map.entrySet()) {
+ for (Entry<String, ?> entry : map.entrySet()) {
String internalIdStr = entry.getKey();
// This is the mapping of internal ids to names. Skip it.
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationChangerTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationChangerTest.java
index f868c6f04aa..fae6f64ce63 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationChangerTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationChangerTest.java
@@ -226,7 +226,8 @@ public class ConfigurationChangerTest {
List.of(KEY),
storage,
generator,
- ConfigurationValidatorImpl.withDefaultValidators(generator, Set.of(validator))
+ ConfigurationValidatorImpl.withDefaultValidators(generator, Set.of(validator)),
+ change -> {}
);
changer2.start();
@@ -606,7 +607,8 @@ public class ConfigurationChangerTest {
List.of(rootKey),
storage,
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ change -> {}
);
}
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationRegistryTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationRegistryTest.java
index 785946b9def..8e50996e211 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationRegistryTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/ConfigurationRegistryTest.java
@@ -65,7 +65,8 @@ public class ConfigurationRegistryTest {
List.of(ExtendedFirstRootConfigurationSchema.class),
List.of()
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
)
);
@@ -78,7 +79,8 @@ public class ConfigurationRegistryTest {
List.of(ExtendedFirstRootConfigurationSchema.class),
List.of()
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(configRegistry.stopAsync(new ComponentContext()), willCompleteSuccessfully());
@@ -97,7 +99,8 @@ public class ConfigurationRegistryTest {
List.of(),
List.of(Second0PolymorphicConfigurationSchema.class)
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
)
);
@@ -112,7 +115,8 @@ public class ConfigurationRegistryTest {
List.of(),
List.of(First0PolymorphicConfigurationSchema.class, ErrorFirst0PolymorphicConfigurationSchema.class)
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
)
);
@@ -131,7 +135,8 @@ public class ConfigurationRegistryTest {
Third1PolymorphicConfigurationSchema.class
)
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(configRegistry.stopAsync(new ComponentContext()), willCompleteSuccessfully());
@@ -145,7 +150,8 @@ public class ConfigurationRegistryTest {
List.of(ThirdRootConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
new ConfigurationTreeGenerator(ThirdRootConfiguration.KEY),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
)
);
@@ -172,7 +178,8 @@ public class ConfigurationRegistryTest {
List.of(),
List.of(Fourth0PolymorphicConfigurationSchema.class)
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
@@ -204,7 +211,8 @@ public class ConfigurationRegistryTest {
Fourth0PolymorphicConfigurationSchema.class
)
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
@@ -232,7 +240,8 @@ public class ConfigurationRegistryTest {
List.of(FirstRootConfiguration.KEY, SecondRootConfiguration.KEY),
storage,
new ConfigurationTreeGenerator(FirstRootConfiguration.KEY, SecondRootConfiguration.KEY),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/InjectedValueConfigurationTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/InjectedValueConfigurationTest.java
index 5748ec4fa83..5a3535adb58 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/InjectedValueConfigurationTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/InjectedValueConfigurationTest.java
@@ -80,7 +80,8 @@ public class InjectedValueConfigurationTest {
roots,
new TestConfigurationStorage(LOCAL),
new ConfigurationTreeGenerator(roots, List.of(), List.of()),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationTreeGeneratorTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationTreeGeneratorTest.java
index ace55ac0129..1b988968dc7 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationTreeGeneratorTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/asm/ConfigurationTreeGeneratorTest.java
@@ -119,7 +119,8 @@ public class ConfigurationTreeGeneratorTest {
rootKeys,
new TestConfigurationStorage(LOCAL),
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ change -> {}
);
changer.start();
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/deprecation/DeprecatedConfigurationTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/deprecation/DeprecatedConfigurationTest.java
new file mode 100644
index 00000000000..ebfe0851fce
--- /dev/null
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/deprecation/DeprecatedConfigurationTest.java
@@ -0,0 +1,459 @@
+/*
+ * 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.deprecation;
+
+import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import org.apache.ignite.configuration.RootKey;
+import org.apache.ignite.configuration.SuperRootChange;
+import org.apache.ignite.configuration.annotation.ConfigValue;
+import org.apache.ignite.configuration.annotation.ConfigurationRoot;
+import org.apache.ignite.configuration.annotation.ConfigurationType;
+import org.apache.ignite.configuration.annotation.NamedConfigValue;
+import org.apache.ignite.configuration.annotation.Value;
+import org.apache.ignite.internal.configuration.ConfigurationChanger;
+import org.apache.ignite.internal.configuration.ConfigurationMigrator;
+import org.apache.ignite.internal.configuration.ConfigurationTreeGenerator;
+import org.apache.ignite.internal.configuration.SuperRoot;
+import org.apache.ignite.internal.configuration.SuperRootChangeImpl;
+import org.apache.ignite.internal.configuration.TestConfigurationChanger;
+import org.apache.ignite.internal.configuration.storage.ConfigurationStorage;
+import org.apache.ignite.internal.configuration.storage.Data;
+import org.apache.ignite.internal.configuration.storage.TestConfigurationStorage;
+import org.apache.ignite.internal.configuration.tree.ConfigurationSource;
+import org.apache.ignite.internal.configuration.tree.ConstructableTreeNode;
+import org.apache.ignite.internal.configuration.tree.InnerNode;
+import org.apache.ignite.internal.configuration.tree.TraversableTreeNodeTest.ChildConfigurationSchema;
+import org.apache.ignite.internal.configuration.tree.TraversableTreeNodeTest.NamedElementConfigurationSchema;
+import org.apache.ignite.internal.configuration.util.ConfigurationUtil;
+import org.apache.ignite.internal.configuration.validation.TestConfigurationValidator;
+import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+/**
+ * Tests for configuration schemas with {@link Deprecated} properties.
+ */
+@ExtendWith(MockitoExtension.class)
+public class DeprecatedConfigurationTest extends BaseIgniteAbstractTest {
+ private static final ConfigurationType TEST_CONFIGURATION_TYPE = ConfigurationType.LOCAL;
+
+ private ConfigurationStorage storage;
+
+ /**
+ * Argument captor for {@link ConfigurationStorage#write(Map, long)}.
+ */
+ @Captor
+ private ArgumentCaptor<Map<String, Serializable>> lastWriteCapture;
+
+ /**
+ * Configuration root schema without any deprecations.
+ */
+ @ConfigurationRoot(rootName = "root", type = ConfigurationType.LOCAL)
+ public static class BeforeDeprecationConfigurationSchema {
+ @Value(hasDefault = true)
+ public int intValue = 10;
+
+ @ConfigValue
+ public ChildConfigurationSchema child;
+
+ @NamedConfigValue
+ public NamedElementConfigurationSchema list;
+ }
+
+ /**
+ * Configuration root schema with deprecated primitive configuration field.
+ */
+ @ConfigurationRoot(rootName = "root", type = ConfigurationType.LOCAL)
+ public static class DeprecatedValueConfigurationSchema {
+ @Deprecated
+ @Value(hasDefault = true)
+ public int intValue = 10;
+
+ @ConfigValue
+ public ChildConfigurationSchema child;
+
+ @NamedConfigValue
+ public NamedElementConfigurationSchema list;
+ }
+
+ /**
+ * Configuration root schema with deprecated child configuration field.
+ */
+ @ConfigurationRoot(rootName = "root", type = ConfigurationType.LOCAL)
+ public static class DeprecatedChildConfigurationSchema {
+ @Value(hasDefault = true)
+ public int intValue = 10;
+
+ @Deprecated
+ @ConfigValue
+ public ChildConfigurationSchema child;
+
+ @NamedConfigValue
+ public NamedElementConfigurationSchema list;
+ }
+
+ /**
+ * Configuration root schema with deprecated named list configuration field.
+ */
+ @ConfigurationRoot(rootName = "root", type = ConfigurationType.LOCAL)
+ public static class DeprecatedNamedListConfigurationSchema {
+ @Value(hasDefault = true)
+ public int intValue = 10;
+
+ @ConfigValue
+ public ChildConfigurationSchema child;
+
+ @Deprecated
+ @NamedConfigValue
+ public NamedElementConfigurationSchema list;
+ }
+
+ @BeforeEach
+ void setUp() {
+ storage = spy(new TestConfigurationStorage(TEST_CONFIGURATION_TYPE));
+
+ when(storage.write(lastWriteCapture.capture(), anyLong())).thenAnswer(InvocationOnMock::callRealMethod);
+ }
+
+ @AfterEach
+ void tearDown() {
+ storage.close();
+ }
+
+ /**
+ * Common assertions for the initial state of the test. In all other tests we rely on invariants stated here.
+ */
+ @Test
+ void testInitialState() {
+ withConfigurationChanger(BeforeDeprecationConfiguration.KEY, true, change -> {}, changer -> {
+ assertEquals(
+ Map.of(
+ "root.intValue", 10,
+ "root.child.my-int-cfg", 99
+ ),
+ lastWriteCapture.getValue()
+ );
+
+ Data data = getData();
+
+ assertEquals(1, data.changeId());
+ assertEquals(
+ Map.of(
+ "root.intValue", 10,
+ "root.child.my-int-cfg", 99
+ ),
+ data.values()
+ );
+ });
+ }
+
+ @Test
+ void testDeprecatedPrimitiveConfiguration() {
+ withConfigurationChanger(BeforeDeprecationConfiguration.KEY, true, change -> {}, changer -> {});
+
+ withConfigurationChanger(DeprecatedValueConfiguration.KEY, false, change -> {}, changer -> {
+ //noinspection CastToIncompatibleInterface
+ var root = (DeprecatedValueView) changer.superRoot().getRoot(DeprecatedValueConfiguration.KEY);
+ // Deprecated value should still be read as a default.
+ assertEquals(10, root.intValue());
+
+ // Check that deprecated value has been deleted while starting the changer.
+ assertEquals(
+ mapWithNulls("root.intValue", null),
+ lastWriteCapture.getValue()
+ );
+
+ // Check that deprecated value is not present in the storage anymore.
+ Data data = getData();
+ assertEquals(2, data.changeId());
+ assertEquals(
+ Map.of("root.child.my-int-cfg", 99),
+ data.values()
+ );
+
+ // Deprecated values should NOT be re-written if they're already absent.
+ changeConfiguration(changer, superRoot ->
+ superRoot.changeRoot(DeprecatedValueConfiguration.KEY).changeChild().changeIntCfg(100)
+ );
+
+ assertEquals(
+ Map.of("root.child.my-int-cfg", 100),
+ lastWriteCapture.getValue()
+ );
+
+ data = getData();
+ assertEquals(3, data.changeId());
+ assertEquals(
+ Map.of("root.child.my-int-cfg", 100),
+ data.values()
+ );
+ });
+ }
+
+ @Test
+ void testConfigurationMigrator() {
+ withConfigurationChanger(BeforeDeprecationConfiguration.KEY, true, change -> {}, changer -> {});
+
+ ConfigurationMigrator migrator = superRootChange -> {
+ // Check one more time that an old value can be read, just to show that we can do that inside of migrator.
+ assertEquals(10, superRootChange.viewRoot(DeprecatedValueConfiguration.KEY).intValue());
+
+ superRootChange.changeRoot(DeprecatedValueConfiguration.KEY).changeChild().changeIntCfg(100);
+ };
+
+ withConfigurationChanger(DeprecatedValueConfiguration.KEY, false, migrator, changer -> {
+ //noinspection CastToIncompatibleInterface
+ var root = (DeprecatedValueView) changer.superRoot().getRoot(DeprecatedValueConfiguration.KEY);
+ // Migrator completed its task.
+ assertEquals(100, root.child().intCfg());
+
+ // Check that deprecated value has been deleted while starting the changer, and that migrator did its job at the same time.
+ assertEquals(
+ mapWithNulls(
+ "root.intValue", null,
+ "root.child.my-int-cfg", 100
+ ),
+ lastWriteCapture.getValue()
+ );
+ });
+ }
+
+ @Test
+ void testDeprecatedChildConfiguration() {
+ withConfigurationChanger(BeforeDeprecationConfiguration.KEY, true, change -> {}, changer -> {});
+
+ withConfigurationChanger(DeprecatedChildConfiguration.KEY, false, change -> {}, changer -> {
+ //noinspection CastToIncompatibleInterface
+ var root = (DeprecatedChildView) changer.superRoot().getRoot(DeprecatedChildConfiguration.KEY);
+ assertNotNull(root.child());
+ assertNull(root.child().strCfg()); // This test never really did anything to "strValue", that's why it's null.
+ assertEquals(99, root.child().intCfg());
+
+ // Check that deprecated value has been deleted while starting the changer.
+ assertEquals(
+ mapWithNulls(
+ "root.child.my-int-cfg", null
+ ),
+ lastWriteCapture.getValue()
+ );
+
+ // Check that deprecated value is not present in the storage anymore.
+ Data data = getData();
+
+ assertEquals(2, data.changeId());
+ assertEquals(
+ Map.of("root.intValue", 10),
+ data.values()
+ );
+
+ // Deprecated values should NOT be re-written if they're already absent.
+ changeConfiguration(changer, superRoot ->
+ superRoot.changeRoot(DeprecatedChildConfiguration.KEY).changeIntValue(20)
+ );
+
+ assertEquals(
+ Map.of("root.intValue", 20),
+ lastWriteCapture.getValue()
+ );
+
+ data = getData();
+ assertEquals(3, data.changeId());
+ assertEquals(
+ Map.of("root.intValue", 20),
+ data.values()
+ );
+ });
+ }
+
+ @Test
+ void testDeprecatedNamedListConfiguration() {
+ AtomicReference<UUID> internalIdReference = new AtomicReference<>();
+
+ withConfigurationChanger(BeforeDeprecationConfiguration.KEY, true, change -> {}, changer -> {
+ // Add named list element for the test.
+ changeConfiguration(changer, superRoot -> {
+ superRoot.changeRoot(BeforeDeprecationConfiguration.KEY)
+ .changeList()
+ .create("foo", namedElementChange ->
+ internalIdReference.set(((InnerNode) namedElementChange).internalId())
+ );
+ });
+
+ UUID internalId = internalIdReference.get();
+ assertNotNull(internalId);
+
+ // Check that all expected properties have been added.
+ assertEquals(
+ Map.of(
+ "root.list." + internalId + ".<order>", 0,
+ "root.list." + internalId + ".<name>", "foo",
+ "root.list.<ids>.foo", internalId
+ ),
+ lastWriteCapture.getValue()
+ );
+
+ // Check storage state.
+ Data data = getData();
+
+ assertEquals(2, data.changeId());
+ assertEquals(
+ Map.of(
+ "root.intValue", 10,
+ "root.child.my-int-cfg", 99,
+ "root.list.<ids>.foo", internalId,
+ "root.list." + internalId + ".<order>", 0,
+ "root.list." + internalId + ".<name>", "foo"
+ ),
+ data.values()
+ );
+ });
+
+ withConfigurationChanger(DeprecatedNamedListConfiguration.KEY, false, change -> {}, changer -> {
+ //noinspection CastToIncompatibleInterface
+ var root = (DeprecatedNamedListView) changer.superRoot().getRoot(DeprecatedNamedListConfiguration.KEY);
+ assertNotNull(root.list());
+
+ UUID internalId = internalIdReference.get();
+
+ // Check that deprecated value has been deleted while starting the changer.
+ assertEquals(
+ mapWithNulls(
+ "root.list." + internalId + ".<order>", null,
+ "root.list." + internalId + ".<name>", null,
+ "root.list.<ids>.foo", null
+ ),
+ lastWriteCapture.getValue()
+ );
+
+ // Check that deprecated value is not present in the storage anymore.
+ Data data = getData();
+
+ assertEquals(3, data.changeId());
+ assertEquals(
+ Map.of(
+ "root.intValue", 10,
+ "root.child.my-int-cfg", 99
+ ),
+ data.values()
+ );
+
+ // Deprecated values should NOT be re-written if they're already absent.
+ changeConfiguration(changer, superRoot ->
+ superRoot.changeRoot(DeprecatedNamedListConfiguration.KEY).changeIntValue(20)
+ );
+
+ assertEquals(
+ Map.of("root.intValue", 20),
+ lastWriteCapture.getValue()
+ );
+
+ data = getData();
+ assertEquals(4, data.changeId());
+ assertEquals(
+ Map.of(
+ "root.intValue", 20,
+ "root.child.my-int-cfg", 99
+ ),
+ data.values()
+ );
+ });
+ }
+
+ private void withConfigurationChanger(
+ RootKey<?, ?> rootKey,
+ boolean init,
+ ConfigurationMigrator migrator,
+ Consumer<ConfigurationChanger> action
+ ) {
+ ConfigurationChanger changer = new TestConfigurationChanger(
+ List.of(rootKey),
+ storage,
+ new ConfigurationTreeGenerator(rootKey),
+ new TestConfigurationValidator(),
+ migrator
+ );
+
+ if (init) {
+ changer.initializeConfigurationWith(ConfigurationUtil.EMPTY_CFG_SRC);
+ }
+
+ changer.start();
+
+ try {
+ action.accept(changer);
+ } finally {
+ changer.stop();
+ }
+ }
+
+ private static void changeConfiguration(ConfigurationChanger changer, Consumer<SuperRootChange> changeClosure) {
+ CompletableFuture<Void> changeFuture = changer.change(new ConfigurationSource() {
+ @Override
+ public void descend(ConstructableTreeNode node) {
+ changeClosure.accept(new SuperRootChangeImpl((SuperRoot) node));
+ }
+ });
+
+ assertThat(changeFuture, willCompleteSuccessfully());
+ }
+
+ private Data getData() {
+ CompletableFuture<Data> dataFuture = storage.readDataOnRecovery();
+
+ assertThat(dataFuture, willCompleteSuccessfully());
+
+ return dataFuture.join();
+ }
+
+ /**
+ * {@link Map#of} does not support null values.
+ */
+ private static <K, V> Map<K, V> mapWithNulls(Object... pairs) {
+ assertEquals(0, pairs.length % 2);
+
+ Map<K, V> map = new HashMap<>();
+
+ for (int i = 0; i < pairs.length / 2; i++) {
+ map.put((K) pairs[i * 2], (V) pairs[i * 2 + 1]);
+ }
+
+ return map;
+ }
+}
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/direct/DirectPropertiesTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/direct/DirectPropertiesTest.java
index c3f64e8e1e3..454af8834bd 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/direct/DirectPropertiesTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/direct/DirectPropertiesTest.java
@@ -110,7 +110,8 @@ public class DirectPropertiesTest {
List.of(DirectConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
new ConfigurationTreeGenerator(DirectConfiguration.KEY),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/hocon/HoconConverterTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/hocon/HoconConverterTest.java
index 13383c608cb..91b00bc285a 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/hocon/HoconConverterTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/hocon/HoconConverterTest.java
@@ -232,7 +232,8 @@ public class HoconConverterTest {
HoconSecondPolymorphicInstanceConfigurationSchema.class
)
),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationAnyListenerTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationAnyListenerTest.java
index ce4aaf811c5..54739efec60 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationAnyListenerTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationAnyListenerTest.java
@@ -168,7 +168,8 @@ public class ConfigurationAnyListenerTest {
List.of(RootConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationListenerTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationListenerTest.java
index 8d1b6d090bc..ec78048fa04 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationListenerTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/notifications/ConfigurationListenerTest.java
@@ -189,7 +189,8 @@ public class ConfigurationListenerTest {
List.of(ParentConfiguration.KEY),
storage,
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/sample/UsageTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/sample/UsageTest.java
index c38c0886086..1e29fb70dd4 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/sample/UsageTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/sample/UsageTest.java
@@ -55,7 +55,8 @@ public class UsageTest {
List.of(LocalConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
new ConfigurationTreeGenerator(LocalConfiguration.KEY),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
@@ -114,7 +115,8 @@ public class UsageTest {
List.of(NetworkConfiguration.KEY, LocalConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
new ConfigurationTreeGenerator(NetworkConfiguration.KEY, LocalConfiguration.KEY),
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/InternalIdTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/InternalIdTest.java
index 478ceb29b2f..169e03027e7 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/InternalIdTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/InternalIdTest.java
@@ -95,7 +95,8 @@ public class InternalIdTest {
List.of(InternalIdParentConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(registry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/NamedListNodeTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/NamedListNodeTest.java
index 7c334618a5f..98ac215513a 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/NamedListNodeTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/tree/NamedListNodeTest.java
@@ -110,7 +110,8 @@ public class NamedListNodeTest {
List.of(FirstConfiguration.KEY),
storage,
cgen,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ change -> {}
);
changer.start();
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java
index 486fd0a812e..0ec72f49b7d 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java
@@ -1020,7 +1020,11 @@ public class ConfigurationUtilTest {
Map<String, Object> exp = new HashMap<>();
- exp.put("0", Map.of("first", "1"));
+ Map<String, Object> expMapZero = new HashMap<>();
+ expMapZero.put("first", "1");
+ expMapZero.put("second", null);
+
+ exp.put("0", expMapZero);
exp.put("1", null);
exp.put("2", Map.of("strVal", "foo", "intVal", 10));
diff --git a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/TestConfigurationChanger.java b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/TestConfigurationChanger.java
index efd464fb657..c1a4498e9fd 100644
--- a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/TestConfigurationChanger.java
+++ b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/TestConfigurationChanger.java
@@ -36,19 +36,15 @@ public class TestConfigurationChanger extends ConfigurationChanger {
/**
* Constructor.
- *
- * @param rootKeys Configuration root keys.
- * @param storage Configuration storage.
- * @param generator Runtime implementations tree generator for node classes.
- * @throws IllegalArgumentException If the configuration type of the root keys is not equal to the storage type.
*/
public TestConfigurationChanger(
Collection<RootKey<?, ?>> rootKeys,
ConfigurationStorage storage,
ConfigurationTreeGenerator generator,
- ConfigurationValidator configurationValidator
+ ConfigurationValidator validator,
+ ConfigurationMigrator migrator
) {
- super(noOpListener(), rootKeys, storage, configurationValidator);
+ super(noOpListener(), rootKeys, storage, validator, migrator);
this.generator = generator;
}
diff --git a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java
index d0a86e349d4..1b69cc019c3 100644
--- a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java
+++ b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItIgniteDistributionZoneManagerNodeRestartTest.java
@@ -221,7 +221,8 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
modules.local().rootKeys(),
new LocalFileConfigurationStorage(configFile, localConfigurationGenerator, modules.local()),
localConfigurationGenerator,
- ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators())
+ ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators()),
+ changer -> {}
);
NetworkConfiguration networkConfiguration = nodeCfgMgr.configurationRegistry()
@@ -288,7 +289,8 @@ public class ItIgniteDistributionZoneManagerNodeRestartTest extends BaseIgniteRe
modules.distributed().rootKeys(),
cfgStorage,
distributedConfigurationGenerator,
- ConfigurationValidatorImpl.withDefaultValidators(distributedConfigurationGenerator, validators)
+ ConfigurationValidatorImpl.withDefaultValidators(distributedConfigurationGenerator, validators),
+ changer -> {}
);
ConfigurationRegistry clusterConfigRegistry = clusterCfgMgr.configurationRegistry();
diff --git a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
index 82f39c771da..2e146dbbcd1 100644
--- a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
+++ b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
@@ -1223,7 +1223,8 @@ public class ItRebalanceDistributedTest extends BaseIgniteAbstractTest {
List.of(NodeConfiguration.KEY),
new LocalFileConfigurationStorage(configPath, nodeCfgGenerator, null),
nodeCfgGenerator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
clusterService = ClusterServiceTestUtils.clusterService(
@@ -1376,7 +1377,8 @@ public class ItRebalanceDistributedTest extends BaseIgniteAbstractTest {
clusterCfgGenerator,
ConfigurationValidatorImpl.withDefaultValidators(
clusterCfgGenerator, Set.of(new NonNegativeIntegerNumberSystemPropertyValueValidator(REBALANCE_RETRY_DELAY_MS))
- )
+ ),
+ changer -> {}
);
ConfigurationRegistry clusterConfigRegistry = clusterCfgMgr.configurationRegistry();
diff --git a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/WatchProcessor.java b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/WatchProcessor.java
index d48ab17b474..34cf9713d0b 100644
--- a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/WatchProcessor.java
+++ b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/WatchProcessor.java
@@ -400,7 +400,7 @@ public class WatchProcessor implements ManuallyCloseable {
if (!nodeStopping) {
LOG.error("Notification chain encountered an error, so no notifications will be ever fired for subsequent revisions "
- + "until a restart. Notifying the FailureManager. Additional info: '{}'", additionalInfoSupplier.get(), e);
+ + "until a restart. Notifying the FailureManager. Additional info: '{}'", additionalInfoSupplier.get());
failureProcessor.process(new FailureContext(CRITICAL_ERROR, e));
} else {
diff --git a/modules/network/src/testFixtures/java/org/apache/ignite/internal/network/utils/ClusterServiceTestUtils.java b/modules/network/src/testFixtures/java/org/apache/ignite/internal/network/utils/ClusterServiceTestUtils.java
index 9d1dfc7434b..10eeb600447 100644
--- a/modules/network/src/testFixtures/java/org/apache/ignite/internal/network/utils/ClusterServiceTestUtils.java
+++ b/modules/network/src/testFixtures/java/org/apache/ignite/internal/network/utils/ClusterServiceTestUtils.java
@@ -221,7 +221,8 @@ public class ClusterServiceTestUtils {
Collections.singleton(NodeConfiguration.KEY),
new TestConfigurationStorage(ConfigurationType.LOCAL),
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
NetworkConfiguration networkConfiguration = nodeConfigurationMgr.configurationRegistry()
diff --git a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java
index bceb3b9e133..d0fb870f97b 100644
--- a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java
+++ b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java
@@ -360,7 +360,8 @@ public class Node {
List.of(NodeConfiguration.KEY),
new LocalFileConfigurationStorage(configPath, nodeCfgGenerator, null),
nodeCfgGenerator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
var clusterIdHolder = new ClusterIdHolder();
@@ -540,7 +541,8 @@ public class Node {
List.of(ClusterConfiguration.KEY),
cfgStorage,
clusterCfgGenerator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
ConfigurationRegistry clusterConfigRegistry = clusterCfgMgr.configurationRegistry();
diff --git a/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java b/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java
index 1070943fb5a..93e3368d087 100644
--- a/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java
+++ b/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java
@@ -91,7 +91,8 @@ public class RestComponentTest extends BaseIgniteAbstractTest {
List.of(NodeConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
assertThat(configurationManager.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/rest/src/test/java/org/apache/ignite/internal/rest/configuration/TestFactory.java b/modules/rest/src/test/java/org/apache/ignite/internal/rest/configuration/TestFactory.java
index 7073b05e4db..357d6bed353 100644
--- a/modules/rest/src/test/java/org/apache/ignite/internal/rest/configuration/TestFactory.java
+++ b/modules/rest/src/test/java/org/apache/ignite/internal/rest/configuration/TestFactory.java
@@ -64,7 +64,8 @@ public class TestFactory {
List.of(TestRootConfiguration.KEY),
new TestConfigurationStorage(LOCAL),
generator,
- ConfigurationValidatorImpl.withDefaultValidators(generator, Set.of(validator))
+ ConfigurationValidatorImpl.withDefaultValidators(generator, Set.of(validator)),
+ changer -> {}
);
assertThat(configurationRegistry.startAsync(new ComponentContext()), willCompleteSuccessfully());
diff --git a/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java b/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java
index 5dfd62dbd8d..f9af33af58a 100644
--- a/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java
+++ b/modules/runner/src/defaultsGenerator/java/org/apache/ignite/internal/configuration/generator/DefaultsGenerator.java
@@ -95,7 +95,7 @@ public class DefaultsGenerator {
ConfigurationUpdateListener empty = (oldRoot, newRoot, storageRevision, notificationNumber) -> nullCompletedFuture();
- return new ConfigurationChanger(empty, modules.local().rootKeys(), storage, configurationValidator) {
+ return new ConfigurationChanger(empty, modules.local().rootKeys(), storage, configurationValidator, c -> {}) {
@Override
public InnerNode createRootNode(RootKey<?, ?> rootKey) {
return localConfigurationGenerator.instantiateNode(rootKey.schemaClass());
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
index 0955e9c4122..679b93c204d 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
@@ -270,7 +270,8 @@ public class ItDistributedConfigurationPropertiesTest extends BaseIgniteAbstract
List.of(DistributedConfiguration.KEY),
distributedCfgStorage,
generator,
- new TestConfigurationValidator()
+ new TestConfigurationValidator(),
+ changer -> {}
);
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index 9cb13fe98d8..e1986bdc48c 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -373,7 +373,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
modules.local().rootKeys(),
new LocalFileConfigurationStorage(configFile, localConfigurationGenerator, modules.local()),
localConfigurationGenerator,
- ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators())
+ ConfigurationValidatorImpl.withDefaultValidators(localConfigurationGenerator, modules.local().validators()),
+ changer -> {}
);
NetworkConfiguration networkConfiguration = nodeCfgMgr.configurationRegistry()
@@ -550,7 +551,8 @@ public class ItIgniteNodeRestartTest extends BaseIgniteRestartTest {
modules.distributed().rootKeys(),
cfgStorage,
distributedConfigurationGenerator,
- ConfigurationValidatorImpl.withDefaultValidators(distributedConfigurationGenerator, modules.distributed().validators())
+ ConfigurationValidatorImpl.withDefaultValidators(distributedConfigurationGenerator, modules.distributed().validators()),
+ changer -> {}
);
ConfigurationRegistry clusterConfigRegistry = clusterCfgMgr.configurationRegistry();
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 c9f5fa7c869..863fc8b1c5f 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
@@ -547,7 +547,8 @@ public class IgniteImpl implements Ignite {
modules.local().rootKeys(),
localFileConfigurationStorage,
localConfigurationGenerator,
- localConfigurationValidator
+ localConfigurationValidator,
+ modules.local()::migrateDeprecatedConfigurations
);
// Start local configuration to be able to read all local properties.
@@ -763,7 +764,8 @@ public class IgniteImpl implements Ignite {
modules.distributed().rootKeys(),
cfgStorage,
distributedConfigurationGenerator,
- distributedCfgValidator
+ distributedCfgValidator,
+ modules.distributed()::migrateDeprecatedConfigurations
);
ConfigurationRegistry clusterConfigRegistry = clusterCfgMgr.configurationRegistry();
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java b/modules/runner/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java
index f64aac2d51c..fc19c9d9f24 100644
--- a/modules/runner/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java
@@ -84,4 +84,9 @@ public class CompoundModule implements ConfigurationModule {
public void patchConfigurationWithDynamicDefaults(SuperRootChange rootChange) {
modules.forEach(module -> module.patchConfigurationWithDynamicDefaults(rootChange));
}
+
+ @Override
+ public void migrateDeprecatedConfigurations(SuperRootChange superRootChange) {
+ modules.forEach(module -> module.migrateDeprecatedConfigurations(superRootChange));
+ }
}
diff --git a/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java b/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
index 0bd47c0078d..d412736b106 100644
--- a/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
+++ b/modules/runner/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
@@ -97,7 +97,8 @@ public class LocalFileConfigurationStorageTest {
List.of(TopConfiguration.KEY),
storage,
treeGenerator,
- new ConfigurationValidatorImpl(treeGenerator, Set.of())
+ new ConfigurationValidatorImpl(treeGenerator, Set.of()),
+ change -> {}
);
}