Repository: accumulo Updated Branches: refs/heads/master a05c96d81 -> 117d5c5c8
ACCUMULO-2841 Add Arbitrary Table Properties Signed-off-by: Christopher Tubbs <ctubb...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/6eedd1f8 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/6eedd1f8 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/6eedd1f8 Branch: refs/heads/master Commit: 6eedd1f880186e9d20e75fdfee1b17f32c45e59c Parents: a05c96d Author: Jenna Huston <jenna.husto...@gmail.com> Authored: Wed Sep 10 15:32:44 2014 -0400 Committer: Christopher Tubbs <ctubb...@apache.org> Committed: Fri Sep 12 13:31:27 2014 -0400 ---------------------------------------------------------------------- .../org/apache/accumulo/core/conf/Property.java | 4 +- .../test/ArbitraryTablePropertiesIT.java | 203 +++++++++++++++++++ 2 files changed, 206 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/6eedd1f8/core/src/main/java/org/apache/accumulo/core/conf/Property.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/conf/Property.java b/core/src/main/java/org/apache/accumulo/core/conf/Property.java index 35cd0a6..f6d6b50 100644 --- a/core/src/main/java/org/apache/accumulo/core/conf/Property.java +++ b/core/src/main/java/org/apache/accumulo/core/conf/Property.java @@ -345,6 +345,7 @@ public enum Property { + "in zookeeper. Restarting accumulo tablet servers after setting these properties in the site file " + "will cause the global setting to take effect. However, you must use the API or the shell to change " + "properties in zookeeper that are set on a table."), + TABLE_ARBITRARY_PROP_PREFIX("table.custom.", null, PropertyType.PREFIX, "Prefix to be used for user defined arbitrary properties."), TABLE_MAJC_RATIO("table.compaction.major.ratio", "3", PropertyType.FRACTION, "minimum ratio of total input size to maximum input file size for running a major compactionWhen adjusting this property you may want to also " + "adjust table.file.max. Want to avoid the situation where only merging minor compactions occur."), @@ -699,7 +700,8 @@ public enum Property { return validTableProperties.contains(key) || key.startsWith(Property.TABLE_CONSTRAINT_PREFIX.getKey()) || key.startsWith(Property.TABLE_ITERATOR_PREFIX.getKey()) || key.startsWith(Property.TABLE_LOCALITY_GROUP_PREFIX.getKey()) - || key.startsWith(Property.TABLE_COMPACTION_STRATEGY_PREFIX.getKey()) || key.startsWith(Property.TABLE_REPLICATION_TARGET.getKey()); + || key.startsWith(Property.TABLE_COMPACTION_STRATEGY_PREFIX.getKey()) || key.startsWith(Property.TABLE_REPLICATION_TARGET.getKey()) + || key.startsWith(Property.TABLE_ARBITRARY_PROP_PREFIX.getKey()); } private static final EnumSet<Property> fixedProperties = EnumSet.of(Property.TSERV_CLIENTPORT, Property.TSERV_NATIVEMAP_ENABLED, http://git-wip-us.apache.org/repos/asf/accumulo/blob/6eedd1f8/test/src/test/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java ---------------------------------------------------------------------- diff --git a/test/src/test/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java b/test/src/test/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java new file mode 100644 index 0000000..20bd0b4 --- /dev/null +++ b/test/src/test/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java @@ -0,0 +1,203 @@ +/* + * 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.accumulo.test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.Connector; +import org.apache.accumulo.core.client.security.tokens.PasswordToken; +import org.apache.accumulo.core.conf.Property; +import org.apache.accumulo.core.security.TablePermission; +import org.apache.accumulo.minicluster.impl.MiniAccumuloConfigImpl; +import org.apache.accumulo.test.functional.ConfigurableMacIT; +import org.apache.hadoop.conf.Configuration; +import org.junit.Assert; +import org.junit.Test; + +public class ArbitraryTablePropertiesIT extends ConfigurableMacIT { + + @Override + public void configure(MiniAccumuloConfigImpl cfg, Configuration hadoopCoreSite) { + cfg.setNumTservers(1); + + Map<String,String> siteConfig = new HashMap<String,String>(); + siteConfig.put(Property.TSERV_MAJC_DELAY.getKey(), "50ms"); + cfg.setSiteConfig(siteConfig); + } + + // Test set, get, and remove arbitrary table properties on the root account + @Test(timeout = 60 * 1000) + public void setGetRemoveTablePropertyRoot() throws Exception { + log.debug("Starting setGetRemoveTablePropertyRoot test ------------------------"); + + // make a table + final String tableName = getUniqueNames(1)[0]; + final Connector conn = getConnector(); + conn.tableOperations().create(tableName); + + // Set variables for the property name to use and the initial value + String propertyName = "table.custom.description"; + String description1 = "Description"; + + // Make sure the property name is valid + Assert.assertTrue(Property.isValidPropertyKey(propertyName)); + // Set the property to the desired value + conn.tableOperations().setProperty(tableName, propertyName, description1); + + // Loop through properties to make sure the new property is added to the list + int count = 0; + for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) { + if (property.getKey().equals(propertyName) && property.getValue().equals(description1)) + count++; + } + Assert.assertEquals(count, 1); + + // Set the property as something different + String description2 = "set second"; + conn.tableOperations().setProperty(tableName, propertyName, description2); + + // / Loop through properties to make sure the new property is added to the list + count = 0; + for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) { + if (property.getKey().equals(propertyName) && property.getValue().equals(description2)) + count++; + } + Assert.assertEquals(count, 1); + + // Remove the property and make sure there is no longer a value associated with it + conn.tableOperations().removeProperty(tableName, propertyName); + + // / Loop through properties to make sure the new property is added to the list + count = 0; + for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) { + if (property.getKey().equals(propertyName)) + count++; + } + Assert.assertEquals(count, 0); + } + + // Tests set, get, and remove of user added arbitrary properties using a non-root account with permissions to alter tables + @Test(timeout = 60 * 1000) + public void userSetGetRemoveTablePropertyWithPermission() throws Exception { + log.debug("Starting userSetGetRemoveTablePropertyWithPermission test ------------------------"); + + // Make a test username and password + String testUser = makeUserName(); + PasswordToken testPasswd = new PasswordToken("test_password"); + + // Create a root user and create the table + // Create a test user and grant that user permission to alter the table + final String tableName = getUniqueNames(1)[0]; + final Connector c = getConnector(); + c.securityOperations().createLocalUser(testUser, testPasswd); + Connector conn = c.getInstance().getConnector(testUser, testPasswd); + c.tableOperations().create(tableName); + c.securityOperations().grantTablePermission(testUser, tableName, TablePermission.ALTER_TABLE); + + // Set variables for the property name to use and the initial value + String propertyName = "table.custom.description"; + String description1 = "Description"; + + // Make sure the property name is valid + Assert.assertTrue(Property.isValidPropertyKey(propertyName)); + // Set the property to the desired value + conn.tableOperations().setProperty(tableName, propertyName, description1); + + // Loop through properties to make sure the new property is added to the list + int count = 0; + for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) { + if (property.getKey().equals(propertyName) && property.getValue().equals(description1)) + count++; + } + Assert.assertEquals(count, 1); + + // Set the property as something different + String description2 = "set second"; + conn.tableOperations().setProperty(tableName, propertyName, description2); + + // / Loop through properties to make sure the new property is added to the list + count = 0; + for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) { + if (property.getKey().equals(propertyName) && property.getValue().equals(description2)) + count++; + } + Assert.assertEquals(count, 1); + + // Remove the property and make sure there is no longer a value associated with it + conn.tableOperations().removeProperty(tableName, propertyName); + + // / Loop through properties to make sure the new property is added to the list + count = 0; + for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) { + if (property.getKey().equals(propertyName)) + count++; + } + Assert.assertEquals(count, 0); + + } + + // Tests set and get of user added arbitrary properties using a non-root account without permissions to alter tables + @Test(timeout = 60 * 1000) + public void userSetGetTablePropertyWithoutPermission() throws Exception { + log.debug("Starting userSetGetTablePropertyWithoutPermission test ------------------------"); + + // Make a test username and password + String testUser = makeUserName(); + PasswordToken testPasswd = new PasswordToken("test_password"); + + // Create a root user and create the table + // Create a test user and grant that user permission to alter the table + final String tableName = getUniqueNames(1)[0]; + final Connector c = getConnector(); + c.securityOperations().createLocalUser(testUser, testPasswd); + Connector conn = c.getInstance().getConnector(testUser, testPasswd); + c.tableOperations().create(tableName); + + // Set variables for the property name to use and the initial value + String propertyName = "table.custom.description"; + String description1 = "Description"; + + // Make sure the property name is valid + Assert.assertTrue(Property.isValidPropertyKey(propertyName)); + + // Try to set the property to the desired value. + // If able to set it, the test fails, since permission was never granted + try { + conn.tableOperations().setProperty(tableName, propertyName, description1); + Assert.fail("Was able to set property without permissions"); + } catch (AccumuloSecurityException e) {} + + // Loop through properties to make sure the new property is not added to the list + int count = 0; + for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) { + if (property.getKey().equals(propertyName)) + count++; + } + Assert.assertEquals(count, 0); + } + + static AtomicInteger userId = new AtomicInteger(0); + + static String makeUserName() { + return "user_" + userId.getAndIncrement(); + } + +}