This is an automated email from the ASF dual-hosted git repository. dlmarion pushed a commit to branch 2.1 in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/2.1 by this push: new af50af77ce Added validation of configuration during upgrade (#4289) af50af77ce is described below commit af50af77cea24a8c4c8cfe62c09b4238577e1034 Author: Dave Marion <dlmar...@apache.org> AuthorDate: Thu Feb 22 12:19:36 2024 -0500 Added validation of configuration during upgrade (#4289) Backported second parameter to CheckConfigUtil.validate and updated all call locations to supply the second parameter. Added method to UpgradeCoordinator to call CheckConfigUtil.validate after the upgradeMetadata method is called on all Upgraders Fixes #3972 --- core/pom.xml | 4 +++ .../apache/accumulo/core/conf/ConfigCheckUtil.java | 11 ++++--- .../accumulo/core/conf/SiteConfiguration.java | 2 +- .../accumulo/core/conf/ConfigCheckUtilTest.java | 16 +++++----- .../core/conf/DefaultConfigurationTest.java | 2 +- .../server/conf/ServerConfigurationFactory.java | 4 +-- .../manager/upgrade/UpgradeCoordinator.java | 37 +++++++++++++++++++++- 7 files changed, 58 insertions(+), 18 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 43dcd6de30..d8cc050b33 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -135,6 +135,10 @@ <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper-jute</artifactId> </dependency> + <dependency> + <groupId>org.checkerframework</groupId> + <artifactId>checker-qual</artifactId> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ConfigCheckUtil.java b/core/src/main/java/org/apache/accumulo/core/conf/ConfigCheckUtil.java index b9e7ecfff3..ba3e7e543f 100644 --- a/core/src/main/java/org/apache/accumulo/core/conf/ConfigCheckUtil.java +++ b/core/src/main/java/org/apache/accumulo/core/conf/ConfigCheckUtil.java @@ -23,6 +23,7 @@ import java.util.Map.Entry; import java.util.Objects; import org.apache.accumulo.core.spi.crypto.CryptoServiceFactory; +import org.checkerframework.checker.nullness.qual.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +46,7 @@ public class ConfigCheckUtil { * @param entries iterable through configuration keys and values * @throws ConfigCheckException if a fatal configuration error is found */ - public static void validate(Iterable<Entry<String,String>> entries) { + public static void validate(Iterable<Entry<String,String>> entries, @NonNull String source) { String instanceZkTimeoutValue = null; for (Entry<String,String> entry : entries) { String key = entry.getKey(); @@ -54,12 +55,12 @@ public class ConfigCheckUtil { if (prop == null && Property.isValidPropertyKey(key)) { continue; // unknown valid property (i.e. has proper prefix) } else if (prop == null) { - log.warn(PREFIX + "unrecognized property key (" + key + ")"); + log.warn(PREFIX + "unrecognized property key ({}) for {}", key, source); } else if (prop.getType() == PropertyType.PREFIX) { - fatal(PREFIX + "incomplete property key (" + key + ")"); + fatal(PREFIX + "incomplete property key (" + key + ") for {}" + source); } else if (!prop.getType().isValidFormat(value)) { fatal(PREFIX + "improperly formatted value for key (" + key + ", type=" + prop.getType() - + ") : " + value); + + ") : " + value + " for " + source); } if (key.equals(Property.INSTANCE_ZK_TIMEOUT.getKey())) { @@ -128,7 +129,7 @@ public class ConfigCheckUtil { } /** - * The exception thrown when {@link ConfigCheckUtil#validate(Iterable)} fails. + * The exception thrown when {@link ConfigCheckUtil#validate(Iterable, String)} fails. */ public static class ConfigCheckException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/core/src/main/java/org/apache/accumulo/core/conf/SiteConfiguration.java b/core/src/main/java/org/apache/accumulo/core/conf/SiteConfiguration.java index c20aab006b..196486f205 100644 --- a/core/src/main/java/org/apache/accumulo/core/conf/SiteConfiguration.java +++ b/core/src/main/java/org/apache/accumulo/core/conf/SiteConfiguration.java @@ -212,7 +212,7 @@ public class SiteConfiguration extends AccumuloConfiguration { private final Map<String,String> config; private SiteConfiguration(Map<String,String> config) { - ConfigCheckUtil.validate(config.entrySet()); + ConfigCheckUtil.validate(config.entrySet(), "site config"); this.config = config; } diff --git a/core/src/test/java/org/apache/accumulo/core/conf/ConfigCheckUtilTest.java b/core/src/test/java/org/apache/accumulo/core/conf/ConfigCheckUtilTest.java index 258e38075f..e204316c50 100644 --- a/core/src/test/java/org/apache/accumulo/core/conf/ConfigCheckUtilTest.java +++ b/core/src/test/java/org/apache/accumulo/core/conf/ConfigCheckUtilTest.java @@ -40,51 +40,51 @@ public class ConfigCheckUtilTest { m.put(Property.MANAGER_TABLET_BALANCER.getKey(), "org.apache.accumulo.server.manager.balancer.TableLoadBalancer"); m.put(Property.MANAGER_BULK_RETRIES.getKey(), "3"); - ConfigCheckUtil.validate(m.entrySet()); + ConfigCheckUtil.validate(m.entrySet(), "test"); } @Test public void testPass_Empty() { - ConfigCheckUtil.validate(m.entrySet()); + ConfigCheckUtil.validate(m.entrySet(), "test"); } @Test public void testPass_UnrecognizedValidProperty() { m.put(Property.MANAGER_CLIENTPORT.getKey(), "9999"); m.put(Property.MANAGER_PREFIX.getKey() + "something", "abcdefg"); - ConfigCheckUtil.validate(m.entrySet()); + ConfigCheckUtil.validate(m.entrySet(), "test"); } @Test public void testPass_UnrecognizedProperty() { m.put(Property.MANAGER_CLIENTPORT.getKey(), "9999"); m.put("invalid.prefix.value", "abcdefg"); - ConfigCheckUtil.validate(m.entrySet()); + ConfigCheckUtil.validate(m.entrySet(), "test"); } @Test public void testFail_Prefix() { m.put(Property.MANAGER_CLIENTPORT.getKey(), "9999"); m.put(Property.MANAGER_PREFIX.getKey(), "oops"); - assertThrows(ConfigCheckException.class, () -> ConfigCheckUtil.validate(m.entrySet())); + assertThrows(ConfigCheckException.class, () -> ConfigCheckUtil.validate(m.entrySet(), "test")); } @Test public void testFail_InstanceZkTimeoutOutOfRange() { m.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "10ms"); - assertThrows(ConfigCheckException.class, () -> ConfigCheckUtil.validate(m.entrySet())); + assertThrows(ConfigCheckException.class, () -> ConfigCheckUtil.validate(m.entrySet(), "test")); } @Test public void testFail_badCryptoFactory() { m.put(Property.INSTANCE_CRYPTO_FACTORY.getKey(), "DoesNotExistCryptoFactory"); - assertThrows(ConfigCheckException.class, () -> ConfigCheckUtil.validate(m.entrySet())); + assertThrows(ConfigCheckException.class, () -> ConfigCheckUtil.validate(m.entrySet(), "test")); } @Test public void testPass_defaultCryptoFactory() { m.put(Property.INSTANCE_CRYPTO_FACTORY.getKey(), Property.INSTANCE_CRYPTO_FACTORY.getDefaultValue()); - ConfigCheckUtil.validate(m.entrySet()); + ConfigCheckUtil.validate(m.entrySet(), "test"); } } diff --git a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java index 123b5bc326..8ddecfbdf3 100644 --- a/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java +++ b/core/src/test/java/org/apache/accumulo/core/conf/DefaultConfigurationTest.java @@ -52,6 +52,6 @@ public class DefaultConfigurationTest { @Test public void testSanityCheck() { - ConfigCheckUtil.validate(c); + ConfigCheckUtil.validate(c, "test"); } } diff --git a/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java b/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java index 21f7822461..e5ac4945a3 100644 --- a/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java +++ b/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java @@ -115,7 +115,7 @@ public class ServerConfigurationFactory extends ServerConfiguration { context.getPropStore().registerAsListener(TablePropKey.of(context, tableId), changeWatcher); var conf = new TableConfiguration(context, tableId, getNamespaceConfigurationForTable(tableId)); - ConfigCheckUtil.validate(conf); + ConfigCheckUtil.validate(conf, "table id: " + tableId.toString()); return conf; } return null; @@ -138,7 +138,7 @@ public class ServerConfigurationFactory extends ServerConfiguration { context.getPropStore().registerAsListener(NamespacePropKey.of(context, namespaceId), changeWatcher); var conf = new NamespaceConfiguration(context, namespaceId, getSystemConfiguration()); - ConfigCheckUtil.validate(conf); + ConfigCheckUtil.validate(conf, "namespace id: " + namespaceId.toString()); return conf; }); } diff --git a/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeCoordinator.java b/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeCoordinator.java index d6494356ec..d62e824e05 100644 --- a/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeCoordinator.java +++ b/server/manager/src/main/java/org/apache/accumulo/manager/upgrade/UpgradeCoordinator.java @@ -29,6 +29,10 @@ import java.util.concurrent.TimeUnit; import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.NamespaceNotFoundException; +import org.apache.accumulo.core.client.TableNotFoundException; +import org.apache.accumulo.core.conf.ConfigCheckUtil; import org.apache.accumulo.core.dataImpl.KeyExtent; import org.apache.accumulo.core.fate.ReadOnlyTStore; import org.apache.accumulo.core.fate.ZooStore; @@ -78,6 +82,15 @@ public class UpgradeCoordinator { return extent.isMeta(); } }, + /** + * This signifies that zookeeper and the root and metadata tables have been upgraded so far. + */ + UPGRADED_METADATA { + @Override + public boolean isParentLevelUpgraded(KeyExtent extent) { + return extent.isMeta(); + } + }, /** * This signifies that everything (zookeeper, root table, metadata table) is upgraded. */ @@ -188,13 +201,16 @@ public class UpgradeCoordinator { log.info("Upgrading Root from data version {}", v); upgraders.get(v).upgradeRoot(context); } - setStatus(UpgradeStatus.UPGRADED_ROOT, eventCoordinator); for (int v = currentVersion; v < AccumuloDataVersion.get(); v++) { log.info("Upgrading Metadata from data version {}", v); upgraders.get(v).upgradeMetadata(context); } + setStatus(UpgradeStatus.UPGRADED_METADATA, eventCoordinator); + + log.info("Validating configuration properties."); + validateProperties(context); log.info("Updating persistent data version."); updateAccumuloVersion(context.getServerDirs(), context.getVolumeManager(), @@ -211,6 +227,25 @@ public class UpgradeCoordinator { } } + private void validateProperties(ServerContext context) { + ConfigCheckUtil.validate(context.getSiteConfiguration(), "site configuration"); + ConfigCheckUtil.validate(context.getConfiguration(), "system configuration"); + try { + for (String ns : context.namespaceOperations().list()) { + ConfigCheckUtil.validate( + context.namespaceOperations().getNamespaceProperties(ns).entrySet(), + ns + " namespace configuration"); + } + for (String table : context.tableOperations().list()) { + ConfigCheckUtil.validate(context.tableOperations().getTableProperties(table).entrySet(), + table + " table configuration"); + } + } catch (AccumuloException | AccumuloSecurityException | NamespaceNotFoundException + | TableNotFoundException e) { + throw new IllegalStateException("Error checking properties", e); + } + } + // visible for testing synchronized void updateAccumuloVersion(ServerDirs serverDirs, VolumeManager fs, int oldVersion) { for (Volume volume : fs.getVolumes()) {