You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jm...@apache.org on 2022/04/07 19:53:51 UTC
[cassandra] branch trunk updated: Add guardrail to disallow creation of secondary indexes
This is an automated email from the ASF dual-hosted git repository.
jmckenzie pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new 910bbb9b5f Add guardrail to disallow creation of secondary indexes
910bbb9b5f is described below
commit 910bbb9b5fced249696930c2e38240a9b0f51bb5
Author: Josh McKenzie <jm...@apache.org>
AuthorDate: Tue Mar 29 14:18:10 2022 -0400
Add guardrail to disallow creation of secondary indexes
Patch by Josh McKenzie; reviewed by Chris Lohfink for CASSANDRA-17498
---
CHANGES.txt | 1 +
conf/cassandra.yaml | 2 +
src/java/org/apache/cassandra/config/Config.java | 1 +
.../apache/cassandra/config/GuardrailsOptions.java | 14 ++++
.../statements/schema/CreateIndexStatement.java | 2 +
.../apache/cassandra/db/guardrails/Guardrails.java | 20 ++++++
.../cassandra/db/guardrails/GuardrailsConfig.java | 5 ++
.../cassandra/db/guardrails/GuardrailsMBean.java | 11 +++
.../guardrails/GuardrailSecondaryIndexTester.java | 84 ++++++++++++++++++++++
9 files changed, 140 insertions(+)
diff --git a/CHANGES.txt b/CHANGES.txt
index 9ded13f525..54fa1e8ec6 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.1
+ * Add guardrail for creation of secondary indexes (CASSANDRA-17498)
* Add guardrail to disallow creation of uncompressed tables (CASSANDRA-17504)
* Add guardrail to disallow creation of new COMPACT STORAGE tables (CASSANDRA-17522)
* repair vtables should expose a completed field due to lack of filtering options in CQL (CASSANDRA-17520)
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index df1eeb259b..1a876ca934 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -1619,6 +1619,8 @@ drop_compact_storage_enabled: false
# The two thresholds default to -1 to disable.
# secondary_indexes_per_table_warn_threshold: -1
# secondary_indexes_per_table_fail_threshold: -1
+# Guardrail to enable or disable the creation of secondary indexes
+# secondary_indexes_enabled: true
# Guardrail to warn or fail when creating more materialized views per table than threshold.
# The two thresholds default to -1 to disable.
# materialized_views_per_table_warn_threshold: -1
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index 00db7ea859..e0dc5767c6 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -800,6 +800,7 @@ public class Config
public volatile Set<ConsistencyLevel> write_consistency_levels_warned = Collections.emptySet();
public volatile Set<ConsistencyLevel> write_consistency_levels_disallowed = Collections.emptySet();
public volatile boolean user_timestamps_enabled = true;
+ public volatile boolean secondary_indexes_enabled = true;
public volatile boolean uncompressed_tables_enabled = true;
public volatile boolean compact_tables_enabled = true;
public volatile boolean read_before_write_list_operations_enabled = true;
diff --git a/src/java/org/apache/cassandra/config/GuardrailsOptions.java b/src/java/org/apache/cassandra/config/GuardrailsOptions.java
index 405cca7ee3..d08f8c555a 100644
--- a/src/java/org/apache/cassandra/config/GuardrailsOptions.java
+++ b/src/java/org/apache/cassandra/config/GuardrailsOptions.java
@@ -332,6 +332,20 @@ public class GuardrailsOptions implements GuardrailsConfig
x -> config.user_timestamps_enabled = x);
}
+ @Override
+ public boolean getSecondaryIndexesEnabled()
+ {
+ return config.secondary_indexes_enabled;
+ }
+
+ public void setSecondaryIndexesEnabled(boolean enabled)
+ {
+ updatePropertyWithLogging("secondary_indexes_enabled",
+ enabled,
+ () -> config.secondary_indexes_enabled,
+ x -> config.secondary_indexes_enabled = x);
+ }
+
@Override
public boolean getUncompressedTablesEnabled()
{
diff --git a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
index 686a9cd5d1..7a3a41e618 100644
--- a/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java
@@ -84,6 +84,8 @@ public final class CreateIndexStatement extends AlterSchemaStatement
{
attrs.validate();
+ Guardrails.createSecondaryIndexesEnabled.ensureEnabled("Creating secondary indexes", state);
+
if (attrs.isCustom && attrs.customClass.equals(SASIIndex.class.getName()) && !DatabaseDescriptor.getSASIIndexesEnabled())
throw new InvalidRequestException("SASI indexes are disabled. Enable in cassandra.yaml to use.");
diff --git a/src/java/org/apache/cassandra/db/guardrails/Guardrails.java b/src/java/org/apache/cassandra/db/guardrails/Guardrails.java
index 6e08660b2a..824160491f 100644
--- a/src/java/org/apache/cassandra/db/guardrails/Guardrails.java
+++ b/src/java/org/apache/cassandra/db/guardrails/Guardrails.java
@@ -98,6 +98,14 @@ public final class Guardrails implements GuardrailsMBean
: format("Tables cannot have more than %s secondary indexes, aborting the creation of secondary index %s",
threshold, what));
+ /**
+ * Guardrail disabling user's ability to create secondary indexes
+ */
+ public static final DisableFlag createSecondaryIndexesEnabled =
+ new DisableFlag("secondary_indexes",
+ state -> !CONFIG_PROVIDER.getOrCreate(state).getSecondaryIndexesEnabled(),
+ "User creation of secondary indexes");
+
/**
* Guardrail on the number of materialized views per table.
*/
@@ -355,6 +363,18 @@ public final class Guardrails implements GuardrailsMBean
DEFAULT_CONFIG.setSecondaryIndexesPerTableThreshold(warn, fail);
}
+ @Override
+ public boolean getSecondaryIndexesEnabled()
+ {
+ return DEFAULT_CONFIG.getSecondaryIndexesEnabled();
+ }
+
+ @Override
+ public void setSecondaryIndexesEnabled(boolean enabled)
+ {
+ DEFAULT_CONFIG.setSecondaryIndexesEnabled(enabled);
+ }
+
@Override
public int getMaterializedViewsPerTableWarnThreshold()
{
diff --git a/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java b/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java
index 3b3473a288..f95989fcf7 100644
--- a/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java
+++ b/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java
@@ -93,6 +93,11 @@ public interface GuardrailsConfig
*/
int getSecondaryIndexesPerTableFailThreshold();
+ /**
+ * @return Whether creation of secondary indexes is allowed.
+ */
+ boolean getSecondaryIndexesEnabled();
+
/**
* @return The threshold to warn when creating more materialized views per table than threshold.
*/
diff --git a/src/java/org/apache/cassandra/db/guardrails/GuardrailsMBean.java b/src/java/org/apache/cassandra/db/guardrails/GuardrailsMBean.java
index 77f0d2dfc4..8d151a1032 100644
--- a/src/java/org/apache/cassandra/db/guardrails/GuardrailsMBean.java
+++ b/src/java/org/apache/cassandra/db/guardrails/GuardrailsMBean.java
@@ -119,6 +119,17 @@ public interface GuardrailsMBean
*/
void setSecondaryIndexesPerTableThreshold(int warn, int fail);
+ /**
+ * @return Whether secondary index creation is active or not on the node
+ */
+ boolean getSecondaryIndexesEnabled();
+
+ /**
+ * Enables or disables the ability to create secondary indexes
+ * @param enabled
+ */
+ void setSecondaryIndexesEnabled(boolean enabled);
+
/**
* @return The threshold to warn when creating more materialized views per table than threshold.
* -1 means disabled.
diff --git a/test/unit/org/apache/cassandra/db/guardrails/GuardrailSecondaryIndexTester.java b/test/unit/org/apache/cassandra/db/guardrails/GuardrailSecondaryIndexTester.java
new file mode 100644
index 0000000000..53ba1b5eb6
--- /dev/null
+++ b/test/unit/org/apache/cassandra/db/guardrails/GuardrailSecondaryIndexTester.java
@@ -0,0 +1,84 @@
+/*
+ * 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.cassandra.db.guardrails;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.lang.String.format;
+
+/**
+ * Tests the guardrail for disabling user creation of secondary indexes, {@link Guardrails#setSecondaryIndexesEnabled(boolean)}.
+ */
+public class GuardrailSecondaryIndexTester extends GuardrailTester
+{
+ public GuardrailSecondaryIndexTester()
+ {
+ super(Guardrails.createSecondaryIndexesEnabled);
+ }
+
+ @Before
+ public void setupTest()
+ {
+ createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int, v3 int, v4 int)");
+ }
+
+ private void setGuardrail(boolean enabled)
+ {
+ guardrails().setSecondaryIndexesEnabled(enabled);
+ }
+
+ @Test
+ public void testCreateIndex() throws Throwable
+ {
+ setGuardrail(true);
+ assertValid(String.format("CREATE INDEX %s ON %s.%s(%s)", "v1_idx", keyspace(), currentTable(), "v1"));
+ assertValid(String.format("CREATE INDEX %s ON %s.%s(%s)", "v2_idx", keyspace(), currentTable(), "v2"));
+
+ setGuardrail(false);
+ assertFails(String.format("CREATE INDEX %s ON %s.%s(%s)", "v3_idx", keyspace(), currentTable(), "v3"), "Creating secondary indexes");
+ assertFails(String.format("CREATE INDEX %s ON %s.%s(%s)", "v4_idx", keyspace(), currentTable(), "v4"), "Creating secondary indexes");
+ assertFails(String.format("CREATE INDEX %s ON %s.%s(%s)", "v2_idx", keyspace(), currentTable(), "v2"), "Creating secondary indexes");
+
+ setGuardrail(true);
+ assertValid(String.format("CREATE INDEX %s ON %s.%s(%s)", "v3_idx", keyspace(), currentTable(), "v3"));
+ assertValid(String.format("CREATE INDEX %s ON %s.%s(%s)", "v4_idx", keyspace(), currentTable(), "v4"));
+
+ // Confirm can drop in either state
+ setGuardrail(false);
+ dropIndex(format("DROP INDEX %s.%s", keyspace(), "v1_idx"));
+
+ setGuardrail(true);
+ dropIndex(format("DROP INDEX %s.%s", keyspace(), "v2_idx"));
+ }
+
+ @Test
+ public void testCustomIndex() throws Throwable
+ {
+ // 2i guardrail will also affect custom indexes
+ setGuardrail(false);
+ assertFails(format("CREATE CUSTOM INDEX ON %%s (%s) USING 'org.apache.cassandra.index.sasi.SASIIndex'", "v4"),
+ format("Creating secondary indexes", currentTable())
+ );
+
+ // Confirm custom creation will work on flip
+ setGuardrail(true);
+ assertValid(format("CREATE CUSTOM INDEX ON %%s (%s) USING 'org.apache.cassandra.index.sasi.SASIIndex'", "v4"));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org