Flatten guardrails config

patch by Andrés de la Peña; reviewed by David Capwell for CASSANDRA-17353
This commit is contained in:
Andrés de la Peña 2022-02-09 18:31:37 +00:00
parent 543608ba39
commit 8e1c8f9863
25 changed files with 613 additions and 583 deletions

View File

@ -1,4 +1,5 @@
4.1
* Flatten guardrails config (CASSANDRA-17353)
* Instance failed to start up due to NPE in StartupClusterConnectivityChecker (CASSANDRA-17347)
* add the shorter version of version flag (-v) in cqlsh (CASSANDRA-17236)
* Make vtables accessible via internode messaging (CASSANDRA-17295)

View File

@ -1510,7 +1510,7 @@ report_unconfirmed_repaired_data_mismatches: false
# Having many tables and/or keyspaces negatively affects performance of many operations in the
# cluster. When the number of tables/keyspaces in the cluster exceeds the following thresholds
# a client warning will be sent back to the user when creating a table or keyspace.
# As of cassandra 4.1, these properties are deprecated in favor of guardrails.keyspaces and guardrails.tables
# As of cassandra 4.1, these properties are deprecated in favor of keyspaces_warn_threshold and tables_warn_threshold
# table_count_warn_threshold: 150
# keyspace_count_warn_threshold: 40
@ -1577,46 +1577,37 @@ drop_compact_storage_enabled: false
# warn_threshold_kb: 0
# abort_threshold_kb: 0
# Guardrails settings.
# guardrails:
# Whether guardrails are enabled or not. Guardrails are disabled by default.
# enabled: false
# Guardrail to warn or abort when creating more user keyspaces than threshold.
# guardrails_enabled: true
# Guardrail to warn or fail when creating more user keyspaces than threshold.
# The two thresholds default to -1 to disable.
# keyspaces:
# warn_threshold: -1
# abort_threshold: -1
# Guardrail to warn or abort when creating more user tables than threshold.
# keyspaces_warn_threshold: -1
# keyspaces_fail_threshold: -1
# Guardrail to warn or fail when creating more user tables than threshold.
# The two thresholds default to -1 to disable.
# tables:
# warn_threshold: -1
# abort_threshold: -1
# Guardrail to warn or abort when creating/altering a table with more columns per table than threshold.
# tables_warn_threshold: -1
# tables_fail_threshold: -1
# Guardrail to warn or fail when creating/altering a table with more columns per table than threshold.
# The two thresholds default to -1 to disable.
# columns_per_table:
# warn_threshold: -1
# abort_threshold: -1
# Guardrail to warn or abort when creating more secondary indexes per table than threshold.
# columns_per_table_warn_threshold: -1
# columns_per_table_fail_threshold: -1
# Guardrail to warn or fail when creating more secondary indexes per table than threshold.
# The two thresholds default to -1 to disable.
# secondary_indexes_per_table:
# warn_threshold: -1
# abort_threshold: -1
# Guardrail to warn or abort when creating more materialized views per table than threshold.
# secondary_indexes_per_table_warn_threshold: -1
# secondary_indexes_per_table_fail_threshold: -1
# 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
# abort_threshold: -1
# materialized_views_per_table_warn_threshold: -1
# materialized_views_per_table_fail_threshold: -1
# Guardrail to ignore or reject properties when creating tables. By default all properties are allowed.
# table_properties:
# ignored: []
# disallowed: []
# table_properties_ignored: []
# table_properties_disallowed: []
# Guardrail to allow/disallow user-provided timestamps. Defaults to true.
# user_timestamps_enabled: true
# Guardrail to warn or abort when using a page size greater than threshold.
# user_timestamps_enabled: true
# Guardrail to warn or fail when using a page size greater than threshold.
# The two thresholds default to -1 to disable.
# page_size:
# warn_threshold: -1
# abort_threshold: -1
# page_size_warn_threshold: -1
# page_size_fail_threshold: -1
# Guardrail to allow/disallow list operations that require read before write, i.e. setting list element by index and
# removing list elements by either index or value. Defaults to true.
# read_before_write_list_operations_enabled: true
# read_before_write_list_operations_enabled: true

View File

@ -20,6 +20,7 @@ package org.apache.cassandra.config;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -666,9 +667,6 @@ public class Config
*/
public volatile double range_tombstone_list_growth_factor = 1.5;
/** The configuration for guardrails. */
public final GuardrailsOptions guardrails = new GuardrailsOptions();
/**
* @deprecated migrate to {@link DatabaseDescriptor#isClientInitialized()}
*/
@ -725,6 +723,25 @@ public class Config
public volatile SubnetGroups client_error_reporting_exclusions = new SubnetGroups();
public volatile SubnetGroups internode_error_reporting_exclusions = new SubnetGroups();
public static final int DISABLED_GUARDRAIL = -1;
public volatile boolean guardrails_enabled = false;
public volatile int keyspaces_warn_threshold = DISABLED_GUARDRAIL;
public volatile int keyspaces_fail_threshold = DISABLED_GUARDRAIL;
public volatile int tables_warn_threshold = DISABLED_GUARDRAIL;
public volatile int tables_fail_threshold = DISABLED_GUARDRAIL;
public volatile int columns_per_table_warn_threshold = DISABLED_GUARDRAIL;
public volatile int columns_per_table_fail_threshold = DISABLED_GUARDRAIL;
public volatile int secondary_indexes_per_table_warn_threshold = DISABLED_GUARDRAIL;
public volatile int secondary_indexes_per_table_fail_threshold = DISABLED_GUARDRAIL;
public volatile int materialized_views_per_table_warn_threshold = DISABLED_GUARDRAIL;
public volatile int materialized_views_per_table_fail_threshold = DISABLED_GUARDRAIL;
public volatile int page_size_warn_threshold = DISABLED_GUARDRAIL;
public volatile int page_size_fail_threshold = DISABLED_GUARDRAIL;
public volatile Set<String> table_properties_ignored = Collections.emptySet();
public volatile Set<String> table_properties_disallowed = Collections.emptySet();
public volatile boolean user_timestamps_enabled = true;
public volatile boolean read_before_write_list_operations_enabled = true;
public enum PaxosVariant
{
v1_without_linearizable_reads, // with legacy semantics for read/read linearizability (i.e. not guaranteed)

View File

@ -155,6 +155,9 @@ public class DatabaseDescriptor
public static volatile boolean allowUnlimitedConcurrentValidations = Boolean.getBoolean("cassandra.allow_unlimited_concurrent_validations");
/** The configuration for guardrails. */
private static GuardrailsOptions guardrails;
private static Function<CommitLog, AbstractCommitLogSegmentManager> commitLogSegmentMgrProvider = c -> DatabaseDescriptor.isCDCEnabled()
? new CommitLogSegmentManagerCDC(c, DatabaseDescriptor.getCommitLogLocation())
: new CommitLogSegmentManagerStandard(c, DatabaseDescriptor.getCommitLogLocation());
@ -879,14 +882,14 @@ public class DatabaseDescriptor
public static GuardrailsOptions getGuardrailsConfig()
{
return conf.guardrails;
return guardrails;
}
private static void applyGuardrails()
{
try
{
conf.guardrails.validate();
guardrails = new GuardrailsOptions(conf);
}
catch (IllegalArgumentException e)
{

View File

@ -18,7 +18,6 @@
package org.apache.cassandra.config;
import java.util.Collections;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
@ -44,7 +43,7 @@ import static java.util.stream.Collectors.toSet;
* <p>This contains a main setting, {@code enabled}, controlling if guardrails are globally active or not, and
* individual settings to control each guardrail.
*
* <p>We have 2 variants of guardrails, soft (warn) and hard (abort) limits, each guardrail having either one of the
* <p>We have 2 variants of guardrails, soft (warn) and hard (fail) limits, each guardrail having either one of the
* variants or both. Note in particular that hard limits only make sense for guardrails triggering during query
* execution. For other guardrails, say one triggering during compaction, aborting that compaction does not make sense.
*
@ -53,36 +52,27 @@ import static java.util.stream.Collectors.toSet;
*/
public class GuardrailsOptions implements GuardrailsConfig
{
private static final String NAME_PREFIX = "guardrails.";
private static final Logger logger = LoggerFactory.getLogger(GuardrailsOptions.class);
private final Config config;
public volatile boolean enabled = false;
public final IntThreshold keyspaces = new IntThreshold();
public final IntThreshold tables = new IntThreshold();
public final IntThreshold columns_per_table = new IntThreshold();
public final IntThreshold secondary_indexes_per_table = new IntThreshold();
public final IntThreshold materialized_views_per_table = new IntThreshold();
public final TableProperties table_properties = new TableProperties();
public final IntThreshold page_size = new IntThreshold();
public volatile boolean user_timestamps_enabled = true;
public volatile boolean read_before_write_list_operations_enabled = true;
public void validate()
public GuardrailsOptions(Config config)
{
keyspaces.init("keyspaces");
tables.init("tables");
columns_per_table.init("columns_per_table");
secondary_indexes_per_table.init("secondary_indexes_per_table");
materialized_views_per_table.init("materialized_views_per_table");
table_properties.init("table_properties");
page_size.init("guardrails.page_size");
this.config = config;
validateIntThreshold(config.keyspaces_warn_threshold, config.keyspaces_fail_threshold, "keyspaces");
validateIntThreshold(config.tables_warn_threshold, config.tables_fail_threshold, "tables");
validateIntThreshold(config.columns_per_table_warn_threshold, config.columns_per_table_fail_threshold, "columns_per_table");
validateIntThreshold(config.secondary_indexes_per_table_warn_threshold, config.secondary_indexes_per_table_fail_threshold, "secondary_indexes_per_table");
validateIntThreshold(config.materialized_views_per_table_warn_threshold, config.materialized_views_per_table_fail_threshold, "materialized_views_per_table");
config.table_properties_ignored = validateTableProperties(config.table_properties_ignored, "table_properties_ignored");
config.table_properties_disallowed = validateTableProperties(config.table_properties_disallowed, "table_properties_disallowed");
validateIntThreshold(config.page_size_warn_threshold, config.page_size_fail_threshold, "page_size");
}
@Override
public boolean getEnabled()
{
return enabled;
return config.guardrails_enabled;
}
/**
@ -92,77 +82,216 @@ public class GuardrailsOptions implements GuardrailsConfig
*/
public void setEnabled(boolean enabled)
{
updatePropertyWithLogging(NAME_PREFIX + "enabled", enabled, () -> this.enabled, x -> this.enabled = x);
updatePropertyWithLogging("guardrails_enabled",
enabled,
() -> config.guardrails_enabled,
x -> config.guardrails_enabled = x);
}
@Override
public IntThreshold getKeyspaces()
public int getKeyspacesWarnThreshold()
{
return keyspaces;
return config.keyspaces_warn_threshold;
}
@Override
public IntThreshold getTables()
public int getKeyspacesFailThreshold()
{
return tables;
return config.keyspaces_fail_threshold;
}
public void setKeyspacesThreshold(int warn, int fail)
{
validateIntThreshold(warn, fail, "keyspaces");
updatePropertyWithLogging("keyspaces_warn_threshold",
warn,
() -> config.keyspaces_warn_threshold,
x -> config.keyspaces_warn_threshold = x);
updatePropertyWithLogging("keyspaces_fail_threshold",
fail,
() -> config.keyspaces_fail_threshold,
x -> config.keyspaces_fail_threshold = x);
}
@Override
public IntThreshold getColumnsPerTable()
public int getTablesWarnThreshold()
{
return columns_per_table;
return config.tables_warn_threshold;
}
@Override
public IntThreshold getSecondaryIndexesPerTable()
public int getTablesFailThreshold()
{
return secondary_indexes_per_table;
return config.tables_fail_threshold;
}
public void setTablesThreshold(int warn, int fail)
{
validateIntThreshold(warn, fail, "tables");
updatePropertyWithLogging("tables_warn_threshold",
warn,
() -> config.tables_warn_threshold,
x -> config.tables_warn_threshold = x);
updatePropertyWithLogging("tables_fail_threshold",
fail,
() -> config.tables_fail_threshold,
x -> config.tables_fail_threshold = x);
}
@Override
public IntThreshold getMaterializedViewsPerTable()
public int getColumnsPerTableWarnThreshold()
{
return materialized_views_per_table;
return config.columns_per_table_warn_threshold;
}
@Override
public TableProperties getTableProperties()
public int getColumnsPerTableFailThreshold()
{
return table_properties;
return config.columns_per_table_fail_threshold;
}
public void setColumnsPerTableThreshold(int warn, int fail)
{
validateIntThreshold(warn, fail, "columns_per_table");
updatePropertyWithLogging("columns_per_table_warn_threshold",
warn,
() -> config.columns_per_table_warn_threshold,
x -> config.columns_per_table_warn_threshold = x);
updatePropertyWithLogging("columns_per_table_fail_threshold",
fail,
() -> config.columns_per_table_fail_threshold,
x -> config.columns_per_table_fail_threshold = x);
}
@Override
public int getSecondaryIndexesPerTableWarnThreshold()
{
return config.secondary_indexes_per_table_warn_threshold;
}
@Override
public int getSecondaryIndexesPerTableFailThreshold()
{
return config.secondary_indexes_per_table_fail_threshold;
}
public void setSecondaryIndexesPerTableThreshold(int warn, int fail)
{
validateIntThreshold(warn, fail, "secondary_indexes_per_table");
updatePropertyWithLogging("secondary_indexes_per_table_warn_threshold",
warn,
() -> config.secondary_indexes_per_table_warn_threshold,
x -> config.secondary_indexes_per_table_warn_threshold = x);
updatePropertyWithLogging("secondary_indexes_per_table_fail_threshold",
fail,
() -> config.secondary_indexes_per_table_fail_threshold,
x -> config.secondary_indexes_per_table_fail_threshold = x);
}
@Override
public int getMaterializedViewsPerTableWarnThreshold()
{
return config.materialized_views_per_table_warn_threshold;
}
@Override
public int getMaterializedViewsPerTableFailThreshold()
{
return config.materialized_views_per_table_fail_threshold;
}
public void setMaterializedViewsPerTableThreshold(int warn, int fail)
{
validateIntThreshold(warn, fail, "materialized_views_per_table");
updatePropertyWithLogging("materialized_views_per_table_warn_threshold",
warn,
() -> config.materialized_views_per_table_warn_threshold,
x -> config.materialized_views_per_table_warn_threshold = x);
updatePropertyWithLogging("materialized_views_per_table_fail_threshold",
fail,
() -> config.materialized_views_per_table_fail_threshold,
x -> config.materialized_views_per_table_fail_threshold = x);
}
@Override
public int getPageSizeWarnThreshold()
{
return config.page_size_warn_threshold;
}
@Override
public int getPageSizeFailThreshold()
{
return config.page_size_fail_threshold;
}
public void setPageSizeThreshold(int warn, int fail)
{
validateIntThreshold(warn, fail, "page_size");
updatePropertyWithLogging("page_size_warn_threshold",
warn,
() -> config.page_size_warn_threshold,
x -> config.page_size_warn_threshold = x);
updatePropertyWithLogging("page_size_fail_threshold",
fail,
() -> config.page_size_fail_threshold,
x -> config.page_size_fail_threshold = x);
}
@Override
public Set<String> getTablePropertiesIgnored()
{
return config.table_properties_ignored;
}
public void setTablePropertiesIgnored(Set<String> properties)
{
updatePropertyWithLogging("table_properties_ignored",
validateTableProperties(properties, "table_properties_ignored"),
() -> config.table_properties_ignored,
x -> config.table_properties_ignored = x);
}
@Override
public Set<String> getTablePropertiesDisallowed()
{
return config.table_properties_disallowed;
}
public void setTablePropertiesDisallowed(Set<String> properties)
{
updatePropertyWithLogging("table_properties_disallowed",
validateTableProperties(properties, "table_properties_disallowed"),
() -> config.table_properties_disallowed,
x -> config.table_properties_disallowed = x);
}
@Override
public boolean getUserTimestampsEnabled()
{
return user_timestamps_enabled;
}
@Override
public IntThreshold getPageSize()
{
return page_size;
return config.user_timestamps_enabled;
}
public void setUserTimestampsEnabled(boolean enabled)
{
updatePropertyWithLogging(NAME_PREFIX + "user_timestamps_enabled",
updatePropertyWithLogging("user_timestamps_enabled",
enabled,
() -> user_timestamps_enabled,
x -> user_timestamps_enabled = x);
() -> config.user_timestamps_enabled,
x -> config.user_timestamps_enabled = x);
}
@Override
public boolean getReadBeforeWriteListOperationsEnabled()
{
return read_before_write_list_operations_enabled;
return config.read_before_write_list_operations_enabled;
}
public void setReadBeforeWriteListOperationsEnabled(boolean enabled)
{
updatePropertyWithLogging(NAME_PREFIX + "read_before_write_list_operations_enabled",
updatePropertyWithLogging("read_before_write_list_operations_enabled",
enabled,
() -> read_before_write_list_operations_enabled,
x -> read_before_write_list_operations_enabled = x);
() -> config.read_before_write_list_operations_enabled,
x -> config.read_before_write_list_operations_enabled = x);
}
private static <T> void updatePropertyWithLogging(String propertyName, T newValue, Supplier<T> getter, Consumer<T> setter)
@ -175,169 +304,62 @@ public class GuardrailsOptions implements GuardrailsConfig
}
}
protected static abstract class Config
private static void validatePositiveNumeric(long value, long maxValue, boolean allowZero, String name)
{
protected String name;
if (value > maxValue)
throw new IllegalArgumentException(format("Invalid value %d for %s: maximum allowed value is %d",
value, name, maxValue));
public String getName()
{
return name;
}
if (value == 0 && !allowZero)
throw new IllegalArgumentException(format("Invalid value for %s: 0 is not allowed; " +
"if attempting to disable use %d",
name, Config.DISABLED_GUARDRAIL));
protected void init(String name)
{
this.name = NAME_PREFIX + name;
validate();
}
protected abstract void validate();
// We allow -1 as a general "disabling" flag. But reject anything lower to avoid mistakes.
if (value < Config.DISABLED_GUARDRAIL)
throw new IllegalArgumentException(format("Invalid value %d for %s: negative values are not allowed, " +
"outside of %d which disables the guardrail",
value, name, Config.DISABLED_GUARDRAIL));
}
public static abstract class Threshold extends Config
private static void validateStrictlyPositiveInteger(long value, String name)
{
public static final long DISABLED = -1;
public abstract long maxValue();
public abstract boolean allowZero();
protected void validate(long warn, long abort)
{
validateLimits(warn, name + ".warn_threshold");
validateLimits(abort, name + ".abort_threshold");
validateWarnLowerThanAbort(warn, abort);
}
protected void validateLimits(long value, String name)
{
if (value > maxValue())
throw new IllegalArgumentException(format("Invalid value %d for %s: maximum allowed value is %d",
value, name, maxValue()));
if (value == 0 && !allowZero())
throw new IllegalArgumentException(format("Invalid value for %s: 0 is not allowed; " +
"if attempting to disable use %d",
name, DISABLED));
// We allow -1 as a general "disabling" flag. But reject anything lower to avoid mistakes.
if (value < DISABLED)
throw new IllegalArgumentException(format("Invalid value %d for %s: negative values are not allowed, " +
"outside of %d which disables the guardrail",
value, name, DISABLED));
}
private void validateWarnLowerThanAbort(long warn, long abort)
{
if (warn == DISABLED || abort == DISABLED)
return;
if (abort < warn)
throw new IllegalArgumentException(format("The warn threshold %d for %s should be lower than the " +
"abort threshold %d", warn, name, abort));
}
// We use 'long' for generality, but most numeric guardrail cannot effectively be more than a 'int' for various
// internal reasons. Not that any should ever come close in practice ...
// Also, in most cases, zero does not make sense (allowing 0 tables or columns is not exactly useful).
validatePositiveNumeric(value, Integer.MAX_VALUE, false, name);
}
public static class IntThreshold extends Threshold implements GuardrailsConfig.IntThreshold
private static void validateIntThreshold(int warn, int fail, String name)
{
public volatile int warn_threshold = (int) DISABLED;
public volatile int abort_threshold = (int) DISABLED;
@Override
public int getWarnThreshold()
{
return warn_threshold;
}
@Override
public int getAbortThreshold()
{
return abort_threshold;
}
public void setThresholds(int warn, int abort)
{
validate(warn, abort);
updatePropertyWithLogging(name + ".warn_threshold", warn, () -> warn_threshold, x -> warn_threshold = x);
updatePropertyWithLogging(name + ".abort_threshold", abort, () -> abort_threshold, x -> abort_threshold = x);
}
@Override
protected void validate()
{
validate(warn_threshold, abort_threshold);
}
@Override
public long maxValue()
{
return Integer.MAX_VALUE;
}
@Override
public boolean allowZero()
{
return false;
}
validateStrictlyPositiveInteger(warn, name + "_warn_threshold");
validateStrictlyPositiveInteger(fail, name + "_fail_threshold");
validateWarnLowerThanFail(warn, fail, name);
}
public static class TableProperties extends Config implements GuardrailsConfig.TableProperties
private static void validateWarnLowerThanFail(long warn, long fail, String name)
{
public volatile Set<String> ignored = Collections.emptySet();
public volatile Set<String> disallowed = Collections.emptySet();
if (warn == Config.DISABLED_GUARDRAIL || fail == Config.DISABLED_GUARDRAIL)
return;
@Override
public Set<String> getIgnored()
{
return ignored;
}
if (fail < warn)
throw new IllegalArgumentException(format("The warn threshold %d for %s_warn_threshold should be lower " +
"than the fail threshold %d", warn, name, fail));
}
@Override
public Set<String> getDisallowed()
{
return disallowed;
}
private static Set<String> validateTableProperties(Set<String> properties, String name)
{
if (properties == null)
throw new IllegalArgumentException(format("Invalid value for %s: null is not allowed", name));
public void setIgnored(Set<String> properties)
{
updatePropertyWithLogging(name + ".ignored", validateIgnored(properties), () -> ignored, x -> ignored = x);
}
Set<String> lowerCaseProperties = properties.stream().map(String::toLowerCase).collect(toSet());
public void setDisallowed(Set<String> properties)
{
updatePropertyWithLogging(name + ".disallowed", validateDisallowed(properties), () -> disallowed, x -> disallowed = x);
}
Set<String> diff = Sets.difference(lowerCaseProperties, TableAttributes.allKeywords());
@Override
protected void validate()
{
validateIgnored(ignored);
validateDisallowed(disallowed);
}
if (!diff.isEmpty())
throw new IllegalArgumentException(format("Invalid value for %s: '%s' do not parse as valid table properties",
name, diff));
private Set<String> validateIgnored(Set<String> properties)
{
return validateTableProperties(properties, name + ".ignored");
}
private Set<String> validateDisallowed(Set<String> properties)
{
return validateTableProperties(properties, name + ".disallowed");
}
private Set<String> validateTableProperties(Set<String> properties, String name)
{
if (properties == null)
throw new IllegalArgumentException(format("Invalid value for %s: null is not allowed", name));
Set<String> lowerCaseProperties = properties.stream().map(String::toLowerCase).collect(toSet());
Set<String> diff = Sets.difference(lowerCaseProperties, TableAttributes.allKeywords());
if (!diff.isEmpty())
throw new IllegalArgumentException(format("Invalid value for %s: '%s' do not parse as valid table properties",
name, diff));
return lowerCaseProperties;
}
return lowerCaseProperties;
}
}

View File

@ -76,6 +76,6 @@ public class DisableFlag extends Guardrail
public void ensureEnabled(String what, @Nullable ClientState state)
{
if (enabled(state) && disabled.test(state))
abort(what + " is not allowed");
fail(what + " is not allowed");
}
}

View File

@ -68,7 +68,7 @@ public abstract class Guardrail
Tracing.trace(message);
}
protected void abort(String message)
protected void fail(String message)
{
logger.error(message);
// Note that ClientWarn will simply ignore the message if we're not running this as part of a user query

View File

@ -47,8 +47,8 @@ public final class Guardrails implements GuardrailsMBean
* Guardrail on the total number of user keyspaces.
*/
public static final Threshold keyspaces =
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getKeyspaces().getWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getKeyspaces().getAbortThreshold(),
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getKeyspacesWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getKeyspacesFailThreshold(),
(isWarning, what, value, threshold) ->
isWarning ? format("Creating keyspace %s, current number of keyspaces %s exceeds warning threshold of %s.",
what, value, threshold)
@ -59,8 +59,8 @@ public final class Guardrails implements GuardrailsMBean
* Guardrail on the total number of tables on user keyspaces.
*/
public static final Threshold tables =
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getTables().getWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getTables().getAbortThreshold(),
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getTablesWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getTablesFailThreshold(),
(isWarning, what, value, threshold) ->
isWarning ? format("Creating table %s, current number of tables %s exceeds warning threshold of %s.",
what, value, threshold)
@ -71,8 +71,8 @@ public final class Guardrails implements GuardrailsMBean
* Guardrail on the number of columns per table.
*/
public static final Threshold columnsPerTable =
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getColumnsPerTable().getWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getColumnsPerTable().getAbortThreshold(),
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getColumnsPerTableWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getColumnsPerTableFailThreshold(),
(isWarning, what, value, threshold) ->
isWarning ? format("The table %s has %s columns, this exceeds the warning threshold of %s.",
what, value, threshold)
@ -80,8 +80,8 @@ public final class Guardrails implements GuardrailsMBean
threshold, value, what));
public static final Threshold secondaryIndexesPerTable =
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getSecondaryIndexesPerTable().getWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getSecondaryIndexesPerTable().getAbortThreshold(),
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getSecondaryIndexesPerTableWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getSecondaryIndexesPerTableFailThreshold(),
(isWarning, what, value, threshold) ->
isWarning ? format("Creating secondary index %s, current number of indexes %s exceeds warning threshold of %s.",
what, value, threshold)
@ -92,8 +92,8 @@ public final class Guardrails implements GuardrailsMBean
* Guardrail on the number of materialized views per table.
*/
public static final Threshold materializedViewsPerTable =
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getMaterializedViewsPerTable().getWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getMaterializedViewsPerTable().getAbortThreshold(),
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getMaterializedViewsPerTableWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getMaterializedViewsPerTableFailThreshold(),
(isWarning, what, value, threshold) ->
isWarning ? format("Creating materialized view %s, current number of views %s exceeds warning threshold of %s.",
what, value, threshold)
@ -104,8 +104,8 @@ public final class Guardrails implements GuardrailsMBean
* Guardrail ignoring/disallowing the usage of certain table properties.
*/
public static final Values<String> tableProperties =
new Values<>(state -> CONFIG_PROVIDER.getOrCreate(state).getTableProperties().getIgnored(),
state -> CONFIG_PROVIDER.getOrCreate(state).getTableProperties().getDisallowed(),
new Values<>(state -> CONFIG_PROVIDER.getOrCreate(state).getTablePropertiesIgnored(),
state -> CONFIG_PROVIDER.getOrCreate(state).getTablePropertiesDisallowed(),
"Table Properties");
/**
@ -119,12 +119,12 @@ public final class Guardrails implements GuardrailsMBean
* Guardrail on the number of elements returned within page.
*/
public static final Threshold pageSize =
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getPageSize().getWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getPageSize().getAbortThreshold(),
new Threshold(state -> CONFIG_PROVIDER.getOrCreate(state).getPageSizeWarnThreshold(),
state -> CONFIG_PROVIDER.getOrCreate(state).getPageSizeFailThreshold(),
(isWarning, what, value, threshold) ->
isWarning ? format("Query for table %s with page size %s exceeds warning threshold of %s.",
what, value, threshold)
: format("Aborting query for table %s, page size %s exceeds abort threshold of %s.",
: format("Aborting query for table %s, page size %s exceeds fail threshold of %s.",
what, value, threshold));
/**
@ -165,103 +165,103 @@ public final class Guardrails implements GuardrailsMBean
@Override
public int getKeyspacesWarnThreshold()
{
return DEFAULT_CONFIG.getKeyspaces().getWarnThreshold();
return DEFAULT_CONFIG.getKeyspacesWarnThreshold();
}
@Override
public int getKeyspacesAbortThreshold()
public int getKeyspacesFailThreshold()
{
return DEFAULT_CONFIG.getKeyspaces().getAbortThreshold();
return DEFAULT_CONFIG.getKeyspacesFailThreshold();
}
@Override
public void setKeyspacesThreshold(int warn, int abort)
public void setKeyspacesThreshold(int warn, int fail)
{
DEFAULT_CONFIG.getKeyspaces().setThresholds(warn, abort);
DEFAULT_CONFIG.setKeyspacesThreshold(warn, fail);
}
@Override
public int getTablesWarnThreshold()
{
return DEFAULT_CONFIG.getTables().getWarnThreshold();
return DEFAULT_CONFIG.getTablesWarnThreshold();
}
@Override
public int getTablesAbortThreshold()
public int getTablesFailThreshold()
{
return DEFAULT_CONFIG.getTables().getAbortThreshold();
return DEFAULT_CONFIG.getTablesFailThreshold();
}
@Override
public void setTablesThreshold(int warn, int abort)
public void setTablesThreshold(int warn, int fail)
{
DEFAULT_CONFIG.getTables().setThresholds(warn, abort);
DEFAULT_CONFIG.setTablesThreshold(warn, fail);
}
@Override
public int getColumnsPerTableWarnThreshold()
{
return DEFAULT_CONFIG.getColumnsPerTable().getWarnThreshold();
return DEFAULT_CONFIG.getColumnsPerTableWarnThreshold();
}
@Override
public int getColumnsPerTableAbortThreshold()
public int getColumnsPerTableFailThreshold()
{
return DEFAULT_CONFIG.getColumnsPerTable().getAbortThreshold();
return DEFAULT_CONFIG.getColumnsPerTableFailThreshold();
}
@Override
public void setColumnsPerTableThreshold(int warn, int abort)
public void setColumnsPerTableThreshold(int warn, int fail)
{
DEFAULT_CONFIG.getColumnsPerTable().setThresholds(warn, abort);
DEFAULT_CONFIG.setColumnsPerTableThreshold(warn, fail);
}
@Override
public int getSecondaryIndexesPerTableWarnThreshold()
{
return DEFAULT_CONFIG.getSecondaryIndexesPerTable().getWarnThreshold();
return DEFAULT_CONFIG.getSecondaryIndexesPerTableWarnThreshold();
}
@Override
public int getSecondaryIndexesPerTableAbortThreshold()
public int getSecondaryIndexesPerTableFailThreshold()
{
return DEFAULT_CONFIG.getSecondaryIndexesPerTable().getAbortThreshold();
return DEFAULT_CONFIG.getSecondaryIndexesPerTableFailThreshold();
}
@Override
public void setSecondaryIndexesPerTableThreshold(int warn, int abort)
public void setSecondaryIndexesPerTableThreshold(int warn, int fail)
{
DEFAULT_CONFIG.getSecondaryIndexesPerTable().setThresholds(warn, abort);
DEFAULT_CONFIG.setSecondaryIndexesPerTableThreshold(warn, fail);
}
@Override
public int getMaterializedViewsPerTableWarnThreshold()
{
return DEFAULT_CONFIG.getMaterializedViewsPerTable().getWarnThreshold();
return DEFAULT_CONFIG.getMaterializedViewsPerTableWarnThreshold();
}
@Override
public int getMaterializedViewsPerTableAbortThreshold()
public int getMaterializedViewsPerTableFailThreshold()
{
return DEFAULT_CONFIG.getMaterializedViewsPerTable().getAbortThreshold();
return DEFAULT_CONFIG.getMaterializedViewsPerTableFailThreshold();
}
@Override
public void setMaterializedViewsPerTableThreshold(int warn, int abort)
public void setMaterializedViewsPerTableThreshold(int warn, int fail)
{
DEFAULT_CONFIG.getMaterializedViewsPerTable().setThresholds(warn, abort);
DEFAULT_CONFIG.setMaterializedViewsPerTableThreshold(warn, fail);
}
@Override
public Set<String> getTablePropertiesDisallowed()
{
return DEFAULT_CONFIG.getTableProperties().getDisallowed();
return DEFAULT_CONFIG.getTablePropertiesDisallowed();
}
@Override
public String getTablePropertiesDisallowedCSV()
{
return toCSV(DEFAULT_CONFIG.getTableProperties().getDisallowed());
return toCSV(DEFAULT_CONFIG.getTablePropertiesDisallowed());
}
public void setTablePropertiesDisallowed(String... properties)
@ -272,7 +272,7 @@ public final class Guardrails implements GuardrailsMBean
@Override
public void setTablePropertiesDisallowed(Set<String> properties)
{
DEFAULT_CONFIG.getTableProperties().setDisallowed(properties);
DEFAULT_CONFIG.setTablePropertiesDisallowed(properties);
}
@Override
@ -284,13 +284,13 @@ public final class Guardrails implements GuardrailsMBean
@Override
public Set<String> getTablePropertiesIgnored()
{
return DEFAULT_CONFIG.getTableProperties().getIgnored();
return DEFAULT_CONFIG.getTablePropertiesIgnored();
}
@Override
public String getTablePropertiesIgnoredCSV()
{
return toCSV(DEFAULT_CONFIG.getTableProperties().getIgnored());
return toCSV(DEFAULT_CONFIG.getTablePropertiesIgnored());
}
public void setTablePropertiesIgnored(String... properties)
@ -301,7 +301,7 @@ public final class Guardrails implements GuardrailsMBean
@Override
public void setTablePropertiesIgnored(Set<String> properties)
{
DEFAULT_CONFIG.getTableProperties().setIgnored(properties);
DEFAULT_CONFIG.setTablePropertiesIgnored(properties);
}
@Override
@ -325,19 +325,19 @@ public final class Guardrails implements GuardrailsMBean
@Override
public int getPageSizeWarnThreshold()
{
return DEFAULT_CONFIG.getPageSize().getWarnThreshold();
return DEFAULT_CONFIG.getPageSizeWarnThreshold();
}
@Override
public int getPageSizeAbortThreshold()
public int getPageSizeFailThreshold()
{
return DEFAULT_CONFIG.getPageSize().getAbortThreshold();
return DEFAULT_CONFIG.getPageSizeFailThreshold();
}
@Override
public void setPageSizeThreshold(int warn, int abort)
public void setPageSizeThreshold(int warn, int fail)
{
DEFAULT_CONFIG.getPageSize().setThresholds(warn, abort);
DEFAULT_CONFIG.setPageSizeThreshold(warn, fail);
}
public boolean getReadBeforeWriteListOperationsEnabled()

View File

@ -30,7 +30,7 @@ import java.util.Set;
* <p>This contains a main setting, {@code enabled}, controlling if guardrails are globally active or not, and
* individual settings to control each guardrail.
*
* <p>We have 2 variants of guardrails, soft (warn) and hard (abort) limits, each guardrail having either one of the
* <p>We have 2 variants of guardrails, soft (warn) and hard (fail) limits, each guardrail having either one of the
* variants or both. Note in particular that hard limits only make sense for guardrails triggering during query
* execution. For other guardrails, say one triggering during compaction, aborting that compaction does not make sense.
*
@ -51,34 +51,64 @@ public interface GuardrailsConfig
boolean getEnabled();
/**
* @return The threshold to warn or abort when creating more user keyspaces than threshold.
* @return The threshold to warn when creating more user keyspaces than threshold.
*/
IntThreshold getKeyspaces();
int getKeyspacesWarnThreshold();
/**
* @return The threshold to warn or abort when creating more user tables than threshold.
* @return The threshold to fail when creating more user keyspaces than threshold.
*/
IntThreshold getTables();
int getKeyspacesFailThreshold();
/**
* @return The threshold to warn or abort when creating more columns per table than threshold.
* @return The threshold to warn when creating more user tables than threshold.
*/
IntThreshold getColumnsPerTable();
int getTablesWarnThreshold();
/**
* @return The threshold to warn or abort when creating more secondary indexes per table than threshold.
* @return The threshold to fail when creating more user tables than threshold.
*/
IntThreshold getSecondaryIndexesPerTable();
int getTablesFailThreshold();
/**
* @return The threshold to warn or abort when creating more materialized views per table than threshold.
* @return The threshold to warn when creating more columns per table than threshold.
*/
IntThreshold getMaterializedViewsPerTable();
int getColumnsPerTableWarnThreshold();
/**
* @return The table properties that are ignored/disallowed when creating or altering a table.
* @return The threshold to fail when creating more columns per table than threshold.
*/
TableProperties getTableProperties();
int getColumnsPerTableFailThreshold();
/**
* @return The threshold to warn when creating more secondary indexes per table than threshold.
*/
int getSecondaryIndexesPerTableWarnThreshold();
/**
* @return The threshold to fail when creating more secondary indexes per table than threshold.
*/
int getSecondaryIndexesPerTableFailThreshold();
/**
* @return The threshold to warn when creating more materialized views per table than threshold.
*/
int getMaterializedViewsPerTableWarnThreshold();
/**
* @return The threshold to fail when creating more materialized views per table than threshold.
*/
int getMaterializedViewsPerTableFailThreshold();
/**
* @return The table properties that are ignored when creating or altering a table.
*/
Set<String> getTablePropertiesIgnored();
/**
* @return The table properties that are disallowed when creating or altering a table.
*/
Set<String> getTablePropertiesDisallowed();
/**
* Returns whether user-provided timestamps are allowed.
@ -88,9 +118,14 @@ public interface GuardrailsConfig
boolean getUserTimestampsEnabled();
/**
* @return The threshold to warn or abort when page size exceeds given size.
* @return The threshold to warn when page size exceeds given size.
*/
IntThreshold getPageSize();
int getPageSizeWarnThreshold();
/**
* @return The threshold to fail when page size exceeds given size.
*/
int getPageSizeFailThreshold();
/**
* Returns whether list operations that require read before write are allowed.
@ -98,37 +133,4 @@ public interface GuardrailsConfig
* @return {@code true} if list operations that require read before write are allowed, {@code false} otherwise.
*/
boolean getReadBeforeWriteListOperationsEnabled();
/**
* Configuration of {@code int}-based thresholds to check if the guarded value should trigger a warning or abort the
* operation.
*/
public interface IntThreshold
{
/**
* @return The threshold to warn when the guarded value exceeds it. A negative value means disabled.
*/
public int getWarnThreshold();
/**
* @return The threshold to abort the operation when the guarded value exceeds it. A negative value means disabled.
*/
public int getAbortThreshold();
}
/**
* Configuration class containing the sets of table properties to ignore and/or reject.
*/
public interface TableProperties
{
/**
* @return The values to be ignored.
*/
Set<String> getIgnored();
/**
* @return The values to be rejected.
*/
Set<String> getDisallowed();
}
}

View File

@ -26,9 +26,9 @@ import java.util.Set;
* This is different to just exposing {@link GuardrailsConfig} in that the methods here should be JMX-friendly.
*
* <p>For consistency, guardrails based on a simple numeric threshold should use the naming scheme
* {@code <whatIsGuarded>WarnThreshold} for soft limits and {@code <whatIsGuarded>AbortThreshold} for hard
* {@code <whatIsGuarded>WarnThreshold} for soft limits and {@code <whatIsGuarded>FailThreshold} for hard
* ones, and if the value has a unit, that unit should be added at the end (for instance,
* {@code <whatIsGuarded>AbortThresholdInKb}). For "boolean" guardrails that disable a feature, use
* {@code <whatIsGuarded>FailThresholdInKb}). For "boolean" guardrails that disable a feature, use
* {@code <whatIsGuardedEnabled}. Other type of guardrails can use appropriate suffixes but should start with
* {@code <whatIsGuarded>}.
*/
@ -58,13 +58,13 @@ public interface GuardrailsMBean
* @return The threshold to prevent creating more user keyspaces than threshold.
* -1 means disabled.
*/
int getKeyspacesAbortThreshold();
int getKeyspacesFailThreshold();
/**
* @param warn The threshold to warn when creating more user keyspaces than threshold. -1 means disabled.
* @param abort The threshold to prevent creating more user keyspaces than threshold. -1 means disabled.
* @param fail The threshold to prevent creating more user keyspaces than threshold. -1 means disabled.
*/
void setKeyspacesThreshold(int warn, int abort);
void setKeyspacesThreshold(int warn, int fail);
/**
* @return The threshold to warn when creating more tables than threshold.
@ -76,13 +76,13 @@ public interface GuardrailsMBean
* @return The threshold to prevent creating more tables than threshold.
* -1 means disabled.
*/
int getTablesAbortThreshold();
int getTablesFailThreshold();
/**
* @param warn The threshold to warn when creating more tables than threshold. -1 means disabled.
* @param abort The threshold to prevent creating more tables than threshold. -1 means disabled.
* @param fail The threshold to prevent creating more tables than threshold. -1 means disabled.
*/
void setTablesThreshold(int warn, int abort);
void setTablesThreshold(int warn, int fail);
/**
* @return The threshold to warn when having more columns per table than threshold.
@ -93,13 +93,13 @@ public interface GuardrailsMBean
/**
* @return The threshold to prevent having more columns per table than threshold. -1 means disabled.
*/
int getColumnsPerTableAbortThreshold();
int getColumnsPerTableFailThreshold();
/**
* @param warn The threshold to warn when having more columns per table than threshold. -1 means disabled.
* @param abort The threshold to prevent having more columns per table than threshold. -1 means disabled.
* @param fail The threshold to prevent having more columns per table than threshold. -1 means disabled.
*/
void setColumnsPerTableThreshold(int warn, int abort);
void setColumnsPerTableThreshold(int warn, int fail);
/**
* @return The threshold to warn when creating more secondary indexes per table than threshold. -1 means disabled.
@ -109,13 +109,13 @@ public interface GuardrailsMBean
/**
* @return The threshold to prevent creating more secondary indexes per table than threshold. -1 means disabled.
*/
int getSecondaryIndexesPerTableAbortThreshold();
int getSecondaryIndexesPerTableFailThreshold();
/**
* @param warn The threshold to warn when creating more secondary indexes per table than threshold. -1 means disabled.
* @param abort The threshold to prevent creating more secondary indexes per table than threshold. -1 means disabled.
* @param fail The threshold to prevent creating more secondary indexes per table than threshold. -1 means disabled.
*/
void setSecondaryIndexesPerTableThreshold(int warn, int abort);
void setSecondaryIndexesPerTableThreshold(int warn, int fail);
/**
* @return The threshold to warn when creating more materialized views per table than threshold.
@ -127,13 +127,13 @@ public interface GuardrailsMBean
* @return The threshold to prevent creating more materialized views per table than threshold.
* -1 means disabled.
*/
int getMaterializedViewsPerTableAbortThreshold();
int getMaterializedViewsPerTableFailThreshold();
/**
* @param warn The threshold to warn when creating more materialized views per table than threshold. -1 means disabled.
* @param abort The threshold to prevent creating more materialized views per table than threshold. -1 means disabled.
* @param fail The threshold to prevent creating more materialized views per table than threshold. -1 means disabled.
*/
void setMaterializedViewsPerTableThreshold(int warn, int abort);
void setMaterializedViewsPerTableThreshold(int warn, int fail);
/**
* @return properties that are not allowed when creating or altering a table.
@ -199,13 +199,13 @@ public interface GuardrailsMBean
* @return The threshold to prevent requesting page with more elements than threshold.
* -1 means disabled.
*/
int getPageSizeAbortThreshold();
int getPageSizeFailThreshold();
/**
* @param warn The threshold to warn when the requested page size is greater than threshold. -1 means disabled.
* @param abort The threshold to prevent requesting pages with more elements than threshold. -1 means disabled.
* @param fail The threshold to prevent requesting pages with more elements than threshold. -1 means disabled.
*/
void setPageSizeThreshold(int warn, int abort);
void setPageSizeThreshold(int warn, int fail);
/**
* Returns whether list operations that require read before write are allowed.

View File

@ -34,22 +34,22 @@ import org.apache.cassandra.service.ClientState;
public class Threshold extends Guardrail
{
private final ToLongFunction<ClientState> warnThreshold;
private final ToLongFunction<ClientState> abortThreshold;
private final ToLongFunction<ClientState> failThreshold;
private final ErrorMessageProvider messageProvider;
/**
* Creates a new threshold guardrail.
*
* @param warnThreshold a {@link ClientState}-based provider of the value above which a warning should be triggered.
* @param abortThreshold a {@link ClientState}-based provider of the value above which the operation should be aborted.
* @param failThreshold a {@link ClientState}-based provider of the value above which the operation should be aborted.
* @param messageProvider a function to generate the warning or error message if the guardrail is triggered
*/
public Threshold(ToLongFunction<ClientState> warnThreshold,
ToLongFunction<ClientState> abortThreshold,
ToLongFunction<ClientState> failThreshold,
ErrorMessageProvider messageProvider)
{
this.warnThreshold = warnThreshold;
this.abortThreshold = abortThreshold;
this.failThreshold = failThreshold;
this.messageProvider = messageProvider;
}
@ -61,10 +61,10 @@ public class Threshold extends Guardrail
thresholdValue);
}
private long abortValue(ClientState state)
private long failValue(ClientState state)
{
long abortValue = abortThreshold.applyAsLong(state);
return abortValue < 0 ? Long.MAX_VALUE : abortValue;
long failValue = failThreshold.applyAsLong(state);
return failValue < 0 ? Long.MAX_VALUE : failValue;
}
private long warnValue(ClientState state)
@ -79,11 +79,11 @@ public class Threshold extends Guardrail
if (!super.enabled(state))
return false;
return abortThreshold.applyAsLong(state) >= 0 || warnThreshold.applyAsLong(state) >= 0;
return failThreshold.applyAsLong(state) >= 0 || warnThreshold.applyAsLong(state) >= 0;
}
/**
* Apply the guardrail to the provided value, warning or aborting if appropriate.
* Apply the guardrail to the provided value, warning or failing if appropriate.
*
* @param value The value to check.
* @param what A string describing what {@code value} is a value of. This is used in the error message if the
@ -97,10 +97,10 @@ public class Threshold extends Guardrail
if (!enabled(state))
return;
long abortValue = abortValue(state);
if (value > abortValue)
long failValue = failValue(state);
if (value > failValue)
{
triggerAbort(value, abortValue, what);
triggerFail(value, failValue, what);
return;
}
@ -109,9 +109,9 @@ public class Threshold extends Guardrail
triggerWarn(value, warnValue, what);
}
private void triggerAbort(long value, long abortValue, String what)
private void triggerFail(long value, long failValue, String what)
{
abort(errMsg(false, what, value, abortValue));
fail(errMsg(false, what, value, failValue));
}
private void triggerWarn(long value, long warnValue, String what)
@ -127,7 +127,7 @@ public class Threshold extends Guardrail
/**
* Called when the guardrail is triggered to build the corresponding error message.
*
* @param isWarning Whether the trigger is a warning one; otherwise it is an abort one.
* @param isWarning Whether the trigger is a warning one; otherwise it is a failure one.
* @param what A string, provided by the call to the {@link #guard} method, describing what the guardrail
* has been applied to (and that has triggered it).
* @param value The value that triggered the guardrail (as a string).

View File

@ -75,8 +75,8 @@ public class Values<T> extends Guardrail
Set<T> disallowed = disallowedValues.apply(state);
Set<T> toDisallow = Sets.intersection(values, disallowed);
if (!toDisallow.isEmpty())
abort(format("Provided values %s are not allowed for %s (disallowed values are: %s)",
toDisallow.stream().sorted().collect(Collectors.toList()), what, disallowed));
fail(format("Provided values %s are not allowed for %s (disallowed values are: %s)",
toDisallow.stream().sorted().collect(Collectors.toList()), what, disallowed));
Set<T> ignored = ignoredValues.apply(state);
Set<T> toIgnore = Sets.intersection(values, ignored);

View File

@ -20,8 +20,6 @@ package org.apache.cassandra.db.guardrails;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import static java.lang.String.format;
/**
@ -30,16 +28,16 @@ import static java.lang.String.format;
public class GuardrailColumnsPerTableTest extends ThresholdTester
{
private static final int COLUMNS_PER_TABLE_WARN_THRESHOLD = 2;
private static final int COLUMNS_PER_TABLE_ABORT_THRESHOLD = 4;
private static final int COLUMNS_PER_TABLE_FAIL_THRESHOLD = 4;
public GuardrailColumnsPerTableTest()
{
super(COLUMNS_PER_TABLE_WARN_THRESHOLD,
COLUMNS_PER_TABLE_ABORT_THRESHOLD,
DatabaseDescriptor.getGuardrailsConfig().getColumnsPerTable(),
COLUMNS_PER_TABLE_FAIL_THRESHOLD,
"columns_per_table",
Guardrails::setColumnsPerTableThreshold,
Guardrails::getColumnsPerTableWarnThreshold,
Guardrails::getColumnsPerTableAbortThreshold);
Guardrails::getColumnsPerTableFailThreshold);
}
@Override
@ -55,39 +53,39 @@ public class GuardrailColumnsPerTableTest extends ThresholdTester
assertCreateTableValid("CREATE TABLE %s (k1 int, v int, PRIMARY KEY((k1)))");
assertCreateTableWarns(3, "CREATE TABLE %s (k1 int, k2 int, v int, PRIMARY KEY((k1, k2)))");
assertCreateTableWarns(4, "CREATE TABLE %s (k1 int, k2 int, k3 int, v int, PRIMARY KEY((k1, k2, k3)))");
assertCreateTableAborts(5, "CREATE TABLE %s (k1 int, k2 int, k3 int, k4 int, v int, PRIMARY KEY((k1, k2, k3, k4)))");
assertCreateTableAborts(6, "CREATE TABLE %s (k1 int, k2 int, k3 int, k4 int, k5 int, v int, PRIMARY KEY((k1, k2, k3, k4, k5)))");
assertCreateTableFails(5, "CREATE TABLE %s (k1 int, k2 int, k3 int, k4 int, v int, PRIMARY KEY((k1, k2, k3, k4)))");
assertCreateTableFails(6, "CREATE TABLE %s (k1 int, k2 int, k3 int, k4 int, k5 int, v int, PRIMARY KEY((k1, k2, k3, k4, k5)))");
// partition key on wide table
assertCreateTableWarns(3, "CREATE TABLE %s (k1 int, c int, v int, PRIMARY KEY(k1, c))");
assertCreateTableWarns(4, "CREATE TABLE %s (k1 int, k2 int, c int, v int, PRIMARY KEY((k1, k2), c))");
assertCreateTableAborts(5, "CREATE TABLE %s (k1 int, k2 int, k3 int, c int, v int, PRIMARY KEY((k1, k2, k3), c))");
assertCreateTableAborts(6, "CREATE TABLE %s (k1 int, k2 int, k3 int, k4 int, c int, v int, PRIMARY KEY((k1, k2, k3, k4), c))");
assertCreateTableFails(5, "CREATE TABLE %s (k1 int, k2 int, k3 int, c int, v int, PRIMARY KEY((k1, k2, k3), c))");
assertCreateTableFails(6, "CREATE TABLE %s (k1 int, k2 int, k3 int, k4 int, c int, v int, PRIMARY KEY((k1, k2, k3, k4), c))");
// clustering key
assertCreateTableWarns(3, "CREATE TABLE %s (k int, c1 int, v int, PRIMARY KEY(k, c1))");
assertCreateTableWarns(4, "CREATE TABLE %s (k int, c1 int, c2 int, v int, PRIMARY KEY(k, c1, c2))");
assertCreateTableAborts(5, "CREATE TABLE %s (k int, c1 int, c2 int, c3 int, v int, PRIMARY KEY(k, c1, c2, c3))");
assertCreateTableAborts(6, "CREATE TABLE %s (k int, c1 int, c2 int, c3 int, c4 int, v int, PRIMARY KEY(k, c1, c2, c3, c4))");
assertCreateTableFails(5, "CREATE TABLE %s (k int, c1 int, c2 int, c3 int, v int, PRIMARY KEY(k, c1, c2, c3))");
assertCreateTableFails(6, "CREATE TABLE %s (k int, c1 int, c2 int, c3 int, c4 int, v int, PRIMARY KEY(k, c1, c2, c3, c4))");
// static column
assertCreateTableWarns(3, "CREATE TABLE %s (k int, c int, s1 int STATIC, PRIMARY KEY(k, c))");
assertCreateTableWarns(4, "CREATE TABLE %s (k int, c int, s1 int STATIC, s2 int STATIC, PRIMARY KEY(k, c))");
assertCreateTableAborts(5, "CREATE TABLE %s (k int, c int, s1 int STATIC, s2 int STATIC, s3 int STATIC, PRIMARY KEY(k, c))");
assertCreateTableAborts(6, "CREATE TABLE %s (k int, c int, s1 int STATIC, s2 int STATIC, s3 int STATIC, s4 int STATIC, PRIMARY KEY(k, c))");
assertCreateTableFails(5, "CREATE TABLE %s (k int, c int, s1 int STATIC, s2 int STATIC, s3 int STATIC, PRIMARY KEY(k, c))");
assertCreateTableFails(6, "CREATE TABLE %s (k int, c int, s1 int STATIC, s2 int STATIC, s3 int STATIC, s4 int STATIC, PRIMARY KEY(k, c))");
// regular column on skinny table
assertCreateTableValid("CREATE TABLE %s (k int PRIMARY KEY, v1 int)");
assertCreateTableWarns(3, "CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int)");
assertCreateTableWarns(4, "CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int, v3 int)");
assertCreateTableAborts(5, "CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int, v3 int, v4 int)");
assertCreateTableAborts(6, "CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int, v3 int, v4 int, v5 int)");
assertCreateTableFails(5, "CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int, v3 int, v4 int)");
assertCreateTableFails(6, "CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int, v3 int, v4 int, v5 int)");
// regular column on wide table
assertCreateTableWarns(3, "CREATE TABLE %s (k int, c int, v1 int, PRIMARY KEY(k, c))");
assertCreateTableWarns(4, "CREATE TABLE %s (k int, c int, v1 int, v2 int, PRIMARY KEY(k, c))");
assertCreateTableAborts(5, "CREATE TABLE %s (k int, c int, v1 int, v2 int, v3 int, PRIMARY KEY(k, c))");
assertCreateTableAborts(6, "CREATE TABLE %s (k int, c int, v1 int, v2 int, v3 int, v4 int, PRIMARY KEY(k, c))");
assertCreateTableFails(5, "CREATE TABLE %s (k int, c int, v1 int, v2 int, v3 int, PRIMARY KEY(k, c))");
assertCreateTableFails(6, "CREATE TABLE %s (k int, c int, v1 int, v2 int, v3 int, v4 int, PRIMARY KEY(k, c))");
// udt
String udt = createType("CREATE TYPE %s (a int, b int, c int, d int)");
@ -101,16 +99,16 @@ public class GuardrailColumnsPerTableTest extends ThresholdTester
createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int)");
assertAddColumnWarns("ALTER TABLE %s ADD v2 int");
assertAddColumnWarns("ALTER TABLE %s ADD v3 int");
assertAddColumnAborts("ALTER TABLE %s ADD v4 int");
assertAddColumnFails("ALTER TABLE %s ADD v4 int");
// skinny table at threshold
createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int, v2 int, v3 int)");
assertAddColumnAborts("ALTER TABLE %s ADD v4 int");
assertAddColumnFails("ALTER TABLE %s ADD v4 int");
// wide table
createTable("CREATE TABLE %s (k int, c int, v1 int, v2 int, PRIMARY KEY(k, c))");
assertAddColumnAborts("ALTER TABLE %s ADD v3 int");
assertAddColumnAborts("ALTER TABLE %s ADD s int STATIC");
assertAddColumnFails("ALTER TABLE %s ADD v3 int");
assertAddColumnFails("ALTER TABLE %s ADD s int STATIC");
// udt
createTable("CREATE TABLE %s (k int PRIMARY KEY, v1 int)");
@ -128,7 +126,7 @@ public class GuardrailColumnsPerTableTest extends ThresholdTester
guardrails().setColumnsPerTableThreshold(2, 2);
assertDropColumnValid("ALTER TABLE %s DROP v2");
assertDropColumnValid("ALTER TABLE %s DROP v3");
assertAddColumnAborts("ALTER TABLE %s ADD v2 int");
assertAddColumnFails("ALTER TABLE %s ADD v2 int");
}
@Test
@ -169,22 +167,22 @@ public class GuardrailColumnsPerTableTest extends ThresholdTester
format(query, keyspace() + '.' + tableName));
}
private void assertAddColumnAborts(String query) throws Throwable
private void assertAddColumnFails(String query) throws Throwable
{
assertAborts(currentValue() + 1, query, currentTable());
assertFails(currentValue() + 1, query, currentTable());
}
private void assertCreateTableAborts(long numColumns, String query) throws Throwable
private void assertCreateTableFails(long numColumns, String query) throws Throwable
{
assertAborts(numColumns, query, ABORT_TABLE);
assertFails(numColumns, query, FAIL_TABLE);
}
private void assertAborts(long numColumns, String query, String tableName) throws Throwable
private void assertFails(long numColumns, String query, String tableName) throws Throwable
{
assertThresholdAborts(format("Tables cannot have more than %s columns, but %s provided for table %s",
guardrails().getColumnsPerTableAbortThreshold(),
numColumns,
tableName),
format(query, keyspace() + '.' + tableName));
assertThresholdFails(format("Tables cannot have more than %s columns, but %s provided for table %s",
guardrails().getColumnsPerTableFailThreshold(),
numColumns,
tableName),
format(query, keyspace() + '.' + tableName));
}
}

View File

@ -20,7 +20,6 @@ package org.apache.cassandra.db.guardrails;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.schema.Schema;
import static java.lang.String.format;
@ -31,16 +30,16 @@ import static java.lang.String.format;
public class GuardrailKeyspacesTest extends ThresholdTester
{
private static final int WARN_THRESHOLD = 3; // CQLTester creates two keyspaces
private static final int ABORT_THRESHOLD = WARN_THRESHOLD + 1;
private static final int FAIL_THRESHOLD = WARN_THRESHOLD + 1;
public GuardrailKeyspacesTest()
{
super(WARN_THRESHOLD,
ABORT_THRESHOLD,
DatabaseDescriptor.getGuardrailsConfig().getKeyspaces(),
FAIL_THRESHOLD,
"keyspaces",
Guardrails::setKeyspacesThreshold,
Guardrails::getKeyspacesWarnThreshold,
Guardrails::getKeyspacesAbortThreshold);
Guardrails::getKeyspacesFailThreshold);
}
@Override
@ -52,22 +51,22 @@ public class GuardrailKeyspacesTest extends ThresholdTester
@Test
public void testCreateKeyspace() throws Throwable
{
// create keyspaces until hitting the two warn/abort thresholds
// create keyspaces until hitting the two warn/fail thresholds
String k1 = assertCreateKeyspaceValid();
String k2 = assertCreateKeyspaceWarns();
assertCreateKeyspaceAborts();
assertCreateKeyspaceFails();
// drop a keyspace and hit the warn/abort threshold again
// drop a keyspace and hit the warn/fail threshold again
dropKeyspace(k2);
String k3 = assertCreateKeyspaceWarns();
assertCreateKeyspaceAborts();
assertCreateKeyspaceFails();
// drop two keyspaces and hit the warn/abort threshold again
// drop two keyspaces and hit the warn/fail threshold again
dropKeyspace(k1);
dropKeyspace(k3);
assertCreateKeyspaceValid();
assertCreateKeyspaceWarns();
assertCreateKeyspaceAborts();
assertCreateKeyspaceFails();
// test excluded users
testExcludedUsers(this::createKeyspaceQuery,
@ -96,12 +95,12 @@ public class GuardrailKeyspacesTest extends ThresholdTester
return keyspaceName;
}
private void assertCreateKeyspaceAborts() throws Throwable
private void assertCreateKeyspaceFails() throws Throwable
{
String keyspaceName = createKeyspaceName();
assertThresholdAborts(format("Cannot have more than %d keyspaces, aborting the creation of keyspace %s",
ABORT_THRESHOLD, keyspaceName),
createKeyspaceQuery(keyspaceName));
assertThresholdFails(format("Cannot have more than %d keyspaces, aborting the creation of keyspace %s",
FAIL_THRESHOLD, keyspaceName),
createKeyspaceQuery(keyspaceName));
}
private String createKeyspaceQuery()

View File

@ -23,7 +23,6 @@ import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.CQLStatement;
import org.apache.cassandra.cql3.QueryOptions;
import org.apache.cassandra.cql3.QueryProcessor;
@ -40,16 +39,16 @@ import static java.lang.String.format;
public class GuardrailPageSizeTest extends ThresholdTester
{
private static final int PAGE_SIZE_WARN_THRESHOLD = 5;
private static final int PAGE_SIZE_ABORT_THRESHOLD = 10;
private static final int PAGE_SIZE_FAIL_THRESHOLD = 10;
public GuardrailPageSizeTest()
{
super(PAGE_SIZE_WARN_THRESHOLD,
PAGE_SIZE_ABORT_THRESHOLD,
DatabaseDescriptor.getGuardrailsConfig().getPageSize(),
PAGE_SIZE_FAIL_THRESHOLD,
"page_size",
Guardrails::setPageSizeThreshold,
Guardrails::getPageSizeWarnThreshold,
Guardrails::getPageSizeAbortThreshold);
Guardrails::getPageSizeFailThreshold);
}
@Before
@ -66,31 +65,31 @@ public class GuardrailPageSizeTest extends ThresholdTester
assertPagingValid(query, 3);
assertPagingValid(query, PAGE_SIZE_WARN_THRESHOLD);
assertPagingWarns(query, 6);
assertPagingWarns(query, PAGE_SIZE_ABORT_THRESHOLD);
assertPagingAborts(query, 11);
assertPagingWarns(query, PAGE_SIZE_FAIL_THRESHOLD);
assertPagingFails(query, 11);
// aggregation query
query = "SELECT COUNT(*) FROM %s WHERE k=0";
assertPagingValid(query, 3);
assertPagingValid(query, PAGE_SIZE_WARN_THRESHOLD);
assertPagingWarns(query, 6);
assertPagingWarns(query, PAGE_SIZE_ABORT_THRESHOLD);
assertPagingAborts(query, 11);
assertPagingWarns(query, PAGE_SIZE_FAIL_THRESHOLD);
assertPagingFails(query, 11);
// query with limit over thresholds
query = "SELECT * FROM %s LIMIT 100";
assertPagingValid(query, 3);
assertPagingValid(query, PAGE_SIZE_WARN_THRESHOLD);
assertPagingWarns(query, 6);
assertPagingWarns(query, PAGE_SIZE_ABORT_THRESHOLD);
assertPagingAborts(query, 11);
assertPagingWarns(query, PAGE_SIZE_FAIL_THRESHOLD);
assertPagingFails(query, 11);
// query with limit under thresholds
query = "SELECT * FROM %s LIMIT 1";
assertPagingValid(query, 3);
assertPagingValid(query, PAGE_SIZE_WARN_THRESHOLD);
assertPagingValid(query, 6);
assertPagingValid(query, PAGE_SIZE_ABORT_THRESHOLD);
assertPagingValid(query, PAGE_SIZE_FAIL_THRESHOLD);
assertPagingValid(query, 11);
}
@ -98,7 +97,7 @@ public class GuardrailPageSizeTest extends ThresholdTester
public void testExcludedUsers() throws Throwable
{
assertPagingIgnored("SELECT * FROM %s", PAGE_SIZE_WARN_THRESHOLD + 1);
assertPagingIgnored("SELECT * FROM %s", PAGE_SIZE_ABORT_THRESHOLD + 1);
assertPagingIgnored("SELECT * FROM %s", PAGE_SIZE_FAIL_THRESHOLD + 1);
}
private void assertPagingValid(String query, int pageSize) throws Throwable
@ -119,11 +118,11 @@ public class GuardrailPageSizeTest extends ThresholdTester
currentTable(), pageSize, PAGE_SIZE_WARN_THRESHOLD));
}
private void assertPagingAborts(String query, int pageSize) throws Throwable
private void assertPagingFails(String query, int pageSize) throws Throwable
{
assertAborts(() -> executeWithPaging(userClientState, query, pageSize),
format("Aborting query for table %s, page size %s exceeds abort threshold of %s.",
currentTable(), pageSize, PAGE_SIZE_ABORT_THRESHOLD));
assertFails(() -> executeWithPaging(userClientState, query, pageSize),
format("Aborting query for table %s, page size %s exceeds fail threshold of %s.",
currentTable(), pageSize, PAGE_SIZE_FAIL_THRESHOLD));
}
private void executeWithPaging(ClientState state, String query, int pageSize)

View File

@ -166,7 +166,7 @@ public class GuardrailReadBeforeWriteListOperationsTest extends GuardrailTester
}
else
{
assertAborts(expectedMessage, query);
assertFails(expectedMessage, query);
}
}

View File

@ -21,8 +21,6 @@ package org.apache.cassandra.db.guardrails;
import com.google.common.base.Strings;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import static java.lang.String.format;
/**
@ -31,16 +29,16 @@ import static java.lang.String.format;
public class GuardrailSecondaryIndexesPerTable extends ThresholdTester
{
private static final int INDEXES_PER_TABLE_WARN_THRESHOLD = 1;
private static final int INDEXES_PER_TABLE_ABORT_THRESHOLD = 3;
private static final int INDEXES_PER_TABLE_FAIL_THRESHOLD = 3;
public GuardrailSecondaryIndexesPerTable()
{
super(INDEXES_PER_TABLE_WARN_THRESHOLD,
INDEXES_PER_TABLE_ABORT_THRESHOLD,
DatabaseDescriptor.getGuardrailsConfig().getSecondaryIndexesPerTable(),
INDEXES_PER_TABLE_FAIL_THRESHOLD,
"secondary_indexes_per_table",
Guardrails::setSecondaryIndexesPerTableThreshold,
Guardrails::getSecondaryIndexesPerTableWarnThreshold,
Guardrails::getSecondaryIndexesPerTableAbortThreshold);
Guardrails::getSecondaryIndexesPerTableFailThreshold);
}
@Override
@ -58,19 +56,19 @@ public class GuardrailSecondaryIndexesPerTable extends ThresholdTester
assertCreateIndexWarns("v2", "");
assertCreateIndexWarns("v3", "v3_idx");
assertCreateIndexAborts("v4", "");
assertCreateIndexAborts("v2", "v2_idx");
assertCreateIndexFails("v4", "");
assertCreateIndexFails("v2", "v2_idx");
assertCurrentValue(3);
// 2i guardrail will also affect custom indexes
assertCreateCustomIndexAborts("v2");
assertCreateCustomIndexFails("v2");
// drop the two first indexes, we should be able to create new indexes again
dropIndex(format("DROP INDEX %s.%s", keyspace(), "v3_idx"));
assertCurrentValue(2);
assertCreateIndexWarns("v3", "");
assertCreateCustomIndexAborts("v4");
assertCreateCustomIndexFails("v4");
assertCurrentValue(3);
// previous guardrail should not apply to another base table
@ -78,7 +76,7 @@ public class GuardrailSecondaryIndexesPerTable extends ThresholdTester
assertCreateIndexSucceeds("v4", "");
assertCreateIndexWarns("v3", "");
assertCreateIndexWarns("v2", "");
assertCreateIndexAborts("v1", "");
assertCreateIndexFails("v1", "");
assertCurrentValue(3);
}
@ -107,16 +105,16 @@ public class GuardrailSecondaryIndexesPerTable extends ThresholdTester
format("CREATE INDEX %s ON %%s(%s)", indexName, column));
}
private void assertCreateIndexAborts(String column, String indexName) throws Throwable
private void assertCreateIndexFails(String column, String indexName) throws Throwable
{
assertThresholdAborts(format("aborting the creation of secondary index %son table %s",
assertThresholdFails(format("aborting the creation of secondary index %son table %s",
Strings.isNullOrEmpty(indexName) ? "" : indexName + " ", currentTable()),
format("CREATE INDEX %s ON %%s(%s)", indexName, column));
format("CREATE INDEX %s ON %%s(%s)", indexName, column));
}
private void assertCreateCustomIndexAborts(String column) throws Throwable
private void assertCreateCustomIndexFails(String column) throws Throwable
{
assertThresholdAborts(format("aborting the creation of secondary index on table %s", currentTable()),
format("CREATE CUSTOM INDEX ON %%s (%s) USING 'org.apache.cassandra.index.sasi.SASIIndex'", column));
assertThresholdFails(format("aborting the creation of secondary index on table %s", currentTable()),
format("CREATE CUSTOM INDEX ON %%s (%s) USING 'org.apache.cassandra.index.sasi.SASIIndex'", column));
}
}

View File

@ -30,7 +30,6 @@ import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.statements.schema.TableAttributes;
import static java.lang.String.format;
@ -46,9 +45,8 @@ public class GuardrailTablePropertiesTest extends GuardrailTester
"WHERE pk IS NOT null and ck IS NOT null PRIMARY KEY(ck, pk) %s";
private static final String ALTER_VIEW = "ALTER MATERIALIZED VIEW %s.%s WITH %s";
private static final String PROPERTY_NAME = DatabaseDescriptor.getGuardrailsConfig().getTableProperties().getName();
private static final String IGNORED_PROPERTY_NAME = PROPERTY_NAME + ".ignored";
private static final String DISALLOWED_PROPERTY_NAME = PROPERTY_NAME + ".disallowed";
private static final String IGNORED_PROPERTY_NAME = "table_properties_ignored";
private static final String DISALLOWED_PROPERTY_NAME = "table_properties_disallowed";
@Before
public void before()
@ -97,11 +95,11 @@ public class GuardrailTablePropertiesTest extends GuardrailTester
{
// most table properties are not allowed
assertValid(this::createTableWithProperties);
assertAborts(() -> createTableWithProperties("with id = " + UUID.randomUUID()), "[id]");
assertAborts(() -> createTableWithProperties("with compression = { 'enabled': 'false' }"), "[compression]");
assertAborts(() -> createTableWithProperties("with compression = { 'enabled': 'false' } AND id = " + UUID.randomUUID()), "[compression, id]");
assertAborts(() -> createTableWithProperties("with compaction = { 'class': 'SizeTieredCompactionStrategy' }"), "[compaction]");
assertAborts(() -> createTableWithProperties("with gc_grace_seconds = 1000 and compression = { 'enabled': 'false' }"), "[compression]");
assertFails(() -> createTableWithProperties("with id = " + UUID.randomUUID()), "[id]");
assertFails(() -> createTableWithProperties("with compression = { 'enabled': 'false' }"), "[compression]");
assertFails(() -> createTableWithProperties("with compression = { 'enabled': 'false' } AND id = " + UUID.randomUUID()), "[compression, id]");
assertFails(() -> createTableWithProperties("with compaction = { 'class': 'SizeTieredCompactionStrategy' }"), "[compaction]");
assertFails(() -> createTableWithProperties("with gc_grace_seconds = 1000 and compression = { 'enabled': 'false' }"), "[compression]");
// though gc_grace_seconds alone is
assertValid(() -> createTableWithProperties("with gc_grace_seconds = 1000"));
@ -127,15 +125,15 @@ public class GuardrailTablePropertiesTest extends GuardrailTester
// view properties is not allowed
createTableWithProperties();
assertValid(() -> createViewWithProperties(""));
assertAborts(() -> createViewWithProperties("with compression = { 'enabled': 'false' }"), "[compression]");
assertFails(() -> createViewWithProperties("with compression = { 'enabled': 'false' }"), "[compression]");
assertValid(() -> createViewWithProperties("with gc_grace_seconds = 1000"));
// alter mv properties except "gc_grace_seconds" is not allowed
assertValid(() -> alterViewWithProperties("gc_grace_seconds = 1000"));
assertAborts(() -> alterViewWithProperties("compaction = { 'class': 'SizeTieredCompactionStrategy' } AND default_time_to_live = 1"),
"[compaction, default_time_to_live]");
assertAborts(() -> alterViewWithProperties("compaction = { 'class': 'SizeTieredCompactionStrategy' } AND crc_check_chance = 1"),
"[compaction, crc_check_chance]");
assertFails(() -> alterViewWithProperties("compaction = { 'class': 'SizeTieredCompactionStrategy' } AND default_time_to_live = 1"),
"[compaction, default_time_to_live]");
assertFails(() -> alterViewWithProperties("compaction = { 'class': 'SizeTieredCompactionStrategy' } AND crc_check_chance = 1"),
"[compaction, crc_check_chance]");
}
@Test

View File

@ -20,7 +20,6 @@ package org.apache.cassandra.db.guardrails;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.Keyspace;
import static java.lang.String.format;
@ -31,16 +30,16 @@ import static java.lang.String.format;
public class GuardrailTablesTest extends ThresholdTester
{
private static final int TABLES_LIMIT_WARN_THRESHOLD = 1;
private static final int TABLES_LIMIT_ABORT_THRESHOLD = 2;
private static final int TABLES_LIMIT_FAIL_THRESHOLD = 2;
public GuardrailTablesTest()
{
super(TABLES_LIMIT_WARN_THRESHOLD,
TABLES_LIMIT_ABORT_THRESHOLD,
DatabaseDescriptor.getGuardrailsConfig().getTables(),
TABLES_LIMIT_FAIL_THRESHOLD,
"tables",
Guardrails::setTablesThreshold,
Guardrails::getTablesWarnThreshold,
Guardrails::getTablesAbortThreshold);
Guardrails::getTablesFailThreshold);
}
@Override
@ -52,22 +51,22 @@ public class GuardrailTablesTest extends ThresholdTester
@Test
public void testCreateTable() throws Throwable
{
// create tables until hitting the two warn/abort thresholds
// create tables until hitting the two warn/fail thresholds
String t1 = assertCreateTableValid();
String t2 = assertCreateTableWarns();
assertCreateTableAborts();
assertCreateTableFails();
// drop a table and hit the warn/abort threshold again
// drop a table and hit the warn/fail threshold again
dropTable(t2);
String t3 = assertCreateTableWarns();
assertCreateTableAborts();
assertCreateTableFails();
// drop two tables and hit the warn/abort threshold again
// drop two tables and hit the warn/fail threshold again
dropTable(t1);
dropTable(t3);
assertCreateTableValid();
assertCreateTableWarns();
assertCreateTableAborts();
assertCreateTableFails();
// test excluded users
testExcludedUsers(this::createTableQuery,
@ -96,11 +95,11 @@ public class GuardrailTablesTest extends ThresholdTester
return tableName;
}
private void assertCreateTableAborts() throws Throwable
private void assertCreateTableFails() throws Throwable
{
String tableName = createTableName();
assertThresholdAborts(format("Cannot have more than 2 tables, aborting the creation of table %s", tableName),
createTableQuery(tableName));
assertThresholdFails(format("Cannot have more than 2 tables, aborting the creation of table %s", tableName),
createTableQuery(tableName));
}
private String createTableQuery()

View File

@ -53,10 +53,10 @@ import static org.junit.Assert.fail;
public abstract class GuardrailTester extends CQLTester
{
// Name used when testing CREATE TABLE that should be aborted (we need to provide it as assertAborts, which
// Name used when testing CREATE TABLE that should be aborted (we need to provide it as assertFails, which
// is used to assert the failure, does not know that it is a CREATE TABLE and would thus reuse the name of the
// previously created table, which is not what we want).
protected static final String ABORT_TABLE = "abort_table_creation_test";
protected static final String FAIL_TABLE = "abort_table_creation_test";
private static final String USERNAME = "guardrail_user";
private static final String PASSWORD = "guardrail_password";
@ -184,12 +184,12 @@ public abstract class GuardrailTester extends CQLTester
assertWarns(() -> execute(userClientState, query), message);
}
protected void assertAborts(CheckedFunction function, String message) throws Throwable
protected void assertFails(CheckedFunction function, String message) throws Throwable
{
assertAborts(function, message, true);
assertFails(function, message, true);
}
protected void assertAborts(CheckedFunction function, String message, boolean thrown) throws Throwable
protected void assertFails(CheckedFunction function, String message, boolean thrown) throws Throwable
{
ClientWarn.instance.captureWarnings();
try
@ -214,9 +214,9 @@ public abstract class GuardrailTester extends CQLTester
}
}
protected void assertAborts(String message, String query) throws Throwable
protected void assertFails(String message, String query) throws Throwable
{
assertAborts(() -> execute(userClientState, query), message);
assertFails(() -> execute(userClientState, query), message);
}
private void assertWarnings(String message)

View File

@ -41,7 +41,7 @@ public class GuardrailUserTimestampsTest extends GuardrailTester
public void testInsertWithDisabledUserTimestamps() throws Throwable
{
setGuardrail(false);
assertAborts("INSERT INTO %s (k, c, v) VALUES (1, 2, 'val') USING TIMESTAMP 1");
assertFails("INSERT INTO %s (k, c, v) VALUES (1, 2, 'val') USING TIMESTAMP 1");
}
@Test
@ -55,7 +55,7 @@ public class GuardrailUserTimestampsTest extends GuardrailTester
public void testUpdateWithDisabledUserTimestamps() throws Throwable
{
setGuardrail(false);
assertAborts("UPDATE %s USING TIMESTAMP 1 SET v = 'val2' WHERE k = 1 and c = 2");
assertFails("UPDATE %s USING TIMESTAMP 1 SET v = 'val2' WHERE k = 1 and c = 2");
}
@Test
@ -69,7 +69,7 @@ public class GuardrailUserTimestampsTest extends GuardrailTester
public void testDeleteWithDisabledUserTimestamps() throws Throwable
{
setGuardrail(false);
assertAborts("DELETE FROM %s USING TIMESTAMP 1 WHERE k=1");
assertFails("DELETE FROM %s USING TIMESTAMP 1 WHERE k=1");
}
@Test
@ -86,9 +86,9 @@ public class GuardrailUserTimestampsTest extends GuardrailTester
assertValid("BEGIN BATCH USING TIMESTAMP 1 " +
"INSERT INTO %s (k, c, v) VALUES (1, 2, 'val') " +
"APPLY BATCH");
assertAborts("BEGIN BATCH " +
"INSERT INTO %s (k, c, v) VALUES (1, 2, 'val') USING TIMESTAMP 1 " +
"APPLY BATCH");
assertFails("BEGIN BATCH " +
"INSERT INTO %s (k, c, v) VALUES (1, 2, 'val') USING TIMESTAMP 1 " +
"APPLY BATCH");
}
@Test
@ -117,8 +117,8 @@ public class GuardrailUserTimestampsTest extends GuardrailTester
}
}
private void assertAborts(String query) throws Throwable
private void assertFails(String query) throws Throwable
{
assertAborts("User provided timestamps (USING TIMESTAMP) is not allowed", query);
assertFails("User provided timestamps (USING TIMESTAMP) is not allowed", query);
}
}

View File

@ -21,8 +21,6 @@ package org.apache.cassandra.db.guardrails;
import org.junit.Before;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import static java.lang.String.format;
/**
@ -31,7 +29,7 @@ import static java.lang.String.format;
public class GuardrailViewsPerTableTest extends ThresholdTester
{
private static final int VIEWS_PER_TABLE_WARN_THRESHOLD = 1;
private static final int VIEWS_PER_TABLE_ABORT_THRESHOLD = 3;
private static final int VIEWS_PER_TABLE_FAIL_THRESHOLD = 3;
private static final String CREATE_TABLE = "CREATE TABLE %s (k int PRIMARY KEY, v int)";
private static final String CREATE_VIEW = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s " +
@ -40,11 +38,11 @@ public class GuardrailViewsPerTableTest extends ThresholdTester
public GuardrailViewsPerTableTest()
{
super(VIEWS_PER_TABLE_WARN_THRESHOLD,
VIEWS_PER_TABLE_ABORT_THRESHOLD,
DatabaseDescriptor.getGuardrailsConfig().getMaterializedViewsPerTable(),
VIEWS_PER_TABLE_FAIL_THRESHOLD,
"materialized_views_per_table",
Guardrails::setMaterializedViewsPerTableThreshold,
Guardrails::getMaterializedViewsPerTableWarnThreshold,
Guardrails::getMaterializedViewsPerTableAbortThreshold);
Guardrails::getMaterializedViewsPerTableFailThreshold);
}
@Override
@ -68,14 +66,14 @@ public class GuardrailViewsPerTableTest extends ThresholdTester
assertCreateViewWarns();
assertCreateViewWarns();
assertCreateViewAborts();
assertCreateViewFails();
assertCurrentValue(3);
// drop the first view, we should be able to create new MV again
dropView(view1);
assertCurrentValue(2);
assertCreateViewWarns();
assertCreateViewAborts();
assertCreateViewFails();
assertCurrentValue(3);
// previous guardrail should not apply to another base table
@ -83,7 +81,7 @@ public class GuardrailViewsPerTableTest extends ThresholdTester
assertCreateViewSucceeds();
assertCreateViewWarns();
assertCreateViewWarns();
assertCreateViewAborts();
assertCreateViewFails();
assertCurrentValue(3);
}
@ -115,11 +113,11 @@ public class GuardrailViewsPerTableTest extends ThresholdTester
format(CREATE_VIEW, viewName));
}
private void assertCreateViewAborts() throws Throwable
private void assertCreateViewFails() throws Throwable
{
String viewName = createViewName();
assertThresholdAborts(format("aborting the creation of materialized view %s on table %s",
viewName, currentTable()),
format(CREATE_VIEW, viewName));
assertThresholdFails(format("aborting the creation of materialized view %s on table %s",
viewName, currentTable()),
format(CREATE_VIEW, viewName));
}
}

View File

@ -20,6 +20,8 @@ package org.apache.cassandra.db.guardrails;
import org.junit.Test;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.GuardrailsOptions;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.service.ClientState;
@ -34,16 +36,16 @@ public class GuardrailsConfigProviderTest extends GuardrailTester
{
String name = getClass().getCanonicalName() + '$' + CustomProvider.class.getSimpleName();
GuardrailsConfigProvider provider = GuardrailsConfigProvider.build(name);
Threshold guard = new Threshold(state -> provider.getOrCreate(state).getTables().getWarnThreshold(),
state -> provider.getOrCreate(state).getTables().getAbortThreshold(),
Threshold guard = new Threshold(state -> provider.getOrCreate(state).getTablesWarnThreshold(),
state -> provider.getOrCreate(state).getTablesFailThreshold(),
(isWarn, what, v, t) -> format("%s: for %s, %s > %s",
isWarn ? "Warning" : "Aborting", what, v, t));
assertValid(() -> guard.guard(5, "Z", userClientState));
assertWarns(() -> guard.guard(25, "A", userClientState), "Warning: for A, 25 > 10");
assertWarns(() -> guard.guard(100, "B", userClientState), "Warning: for B, 100 > 10");
assertAborts(() -> guard.guard(101, "X", userClientState), "Aborting: for X, 101 > 100");
assertAborts(() -> guard.guard(200, "Y", userClientState), "Aborting: for Y, 200 > 100");
assertFails(() -> guard.guard(101, "X", userClientState), "Aborting: for X, 101 > 100");
assertFails(() -> guard.guard(200, "Y", userClientState), "Aborting: for Y, 200 > 100");
assertValid(() -> guard.guard(5, "Z", userClientState));
Assertions.assertThatThrownBy(() -> GuardrailsConfigProvider.build("unexistent_class"))
@ -58,23 +60,27 @@ public class GuardrailsConfigProviderTest extends GuardrailTester
{
public GuardrailsConfig getOrCreate(ClientState state)
{
return new CustomConfig();
return new CustomConfig(DatabaseDescriptor.getRawConfig());
}
}
public static class CustomConfig extends GuardrailsOptions
{
private final IntThreshold tables = new IntThreshold();
public CustomConfig()
public CustomConfig(Config config)
{
tables.setThresholds(10, 100);
super(config);
}
@Override
public IntThreshold getTables()
public int getTablesWarnThreshold()
{
return tables;
return 10;
}
@Override
public int getTablesFailThreshold()
{
return 100;
}
}
}

View File

@ -68,8 +68,8 @@ public class GuardrailsTest extends GuardrailTester
assertValid(() -> guard.guard(5, "Z", userClientState));
assertWarns(() -> guard.guard(25, "A", userClientState), "Warning: for A, 25 > 10");
assertWarns(() -> guard.guard(100, "B", userClientState), "Warning: for B, 100 > 10");
assertAborts(() -> guard.guard(101, "X", userClientState), "Aborting: for X, 101 > 100");
assertAborts(() -> guard.guard(200, "Y", userClientState), "Aborting: for Y, 200 > 100");
assertFails(() -> guard.guard(101, "X", userClientState), "Aborting: for X, 101 > 100");
assertFails(() -> guard.guard(200, "Y", userClientState), "Aborting: for Y, 200 > 100");
assertValid(() -> guard.guard(5, "Z", userClientState));
}
@ -88,7 +88,7 @@ public class GuardrailsTest extends GuardrailTester
}
@Test
public void testAbortOnlyThreshold() throws Throwable
public void testFailOnlyThreshold() throws Throwable
{
Threshold guard = new Threshold(state -> DISABLED,
state -> 10,
@ -98,7 +98,7 @@ public class GuardrailsTest extends GuardrailTester
assertTrue(guard.enabled(userClientState));
assertValid(() -> guard.guard(5, "Z", userClientState));
assertAborts(() -> guard.guard(11, "A", userClientState), "Aborting: for A, 11 > 10");
assertFails(() -> guard.guard(11, "A", userClientState), "Aborting: for A, 11 > 10");
}
@Test
@ -121,9 +121,9 @@ public class GuardrailsTest extends GuardrailTester
assertValid(() -> guard.guard(100, "y", systemClientState));
assertValid(() -> guard.guard(100, "y", superClientState));
// value over abort threshold
assertAborts(() -> guard.guard(101, "z", null), "Aborting: for z, 101 > 100");
assertAborts(() -> guard.guard(101, "z", userClientState), "Aborting: for z, 101 > 100");
// value over fail threshold
assertFails(() -> guard.guard(101, "z", null), "Aborting: for z, 101 > 100");
assertFails(() -> guard.guard(101, "z", userClientState), "Aborting: for z, 101 > 100");
assertValid(() -> guard.guard(101, "z", systemClientState));
assertValid(() -> guard.guard(101, "z", superClientState));
}
@ -131,10 +131,10 @@ public class GuardrailsTest extends GuardrailTester
@Test
public void testDisableFlag() throws Throwable
{
assertAborts(() -> new DisableFlag(state -> true, "X").ensureEnabled(userClientState), "X is not allowed");
assertFails(() -> new DisableFlag(state -> true, "X").ensureEnabled(userClientState), "X is not allowed");
assertValid(() -> new DisableFlag(state -> false, "X").ensureEnabled(userClientState));
assertAborts(() -> new DisableFlag(state -> true, "X").ensureEnabled("Y", userClientState), "Y is not allowed");
assertFails(() -> new DisableFlag(state -> true, "X").ensureEnabled("Y", userClientState), "Y is not allowed");
assertValid(() -> new DisableFlag(state -> false, "X").ensureEnabled("Y", userClientState));
}
@ -148,8 +148,8 @@ public class GuardrailsTest extends GuardrailTester
assertValid(() -> enabled.ensureEnabled(superClientState));
DisableFlag disabled = new DisableFlag(state -> true, "X");
assertAborts(() -> disabled.ensureEnabled(null), "X is not allowed");
assertAborts(() -> disabled.ensureEnabled(userClientState), "X is not allowed");
assertFails(() -> disabled.ensureEnabled(null), "X is not allowed");
assertFails(() -> disabled.ensureEnabled(userClientState), "X is not allowed");
assertValid(() -> disabled.ensureEnabled(systemClientState));
assertValid(() -> disabled.ensureEnabled(superClientState));
}
@ -164,18 +164,18 @@ public class GuardrailsTest extends GuardrailTester
Consumer<Integer> action = i -> Assert.fail("The ignore action shouldn't have been triggered");
assertValid(() -> disallowed.guard(set(3), action, userClientState));
assertAborts(() -> disallowed.guard(set(4), action, userClientState),
"Provided values [4] are not allowed for integer (disallowed values are: [4, 6, 20])");
assertFails(() -> disallowed.guard(set(4), action, userClientState),
"Provided values [4] are not allowed for integer (disallowed values are: [4, 6, 20])");
assertValid(() -> disallowed.guard(set(10), action, userClientState));
assertAborts(() -> disallowed.guard(set(20), action, userClientState),
"Provided values [20] are not allowed for integer (disallowed values are: [4, 6, 20])");
assertFails(() -> disallowed.guard(set(20), action, userClientState),
"Provided values [20] are not allowed for integer (disallowed values are: [4, 6, 20])");
assertValid(() -> disallowed.guard(set(200), action, userClientState));
assertValid(() -> disallowed.guard(set(1, 2, 3), action, userClientState));
assertAborts(() -> disallowed.guard(set(4, 6), action, null),
"Provided values [4, 6] are not allowed for integer (disallowed values are: [4, 6, 20])");
assertAborts(() -> disallowed.guard(set(4, 5, 6, 7), action, null),
"Provided values [4, 6] are not allowed for integer (disallowed values are: [4, 6, 20])");
assertFails(() -> disallowed.guard(set(4, 6), action, null),
"Provided values [4, 6] are not allowed for integer (disallowed values are: [4, 6, 20])");
assertFails(() -> disallowed.guard(set(4, 5, 6, 7), action, null),
"Provided values [4, 6] are not allowed for integer (disallowed values are: [4, 6, 20])");
}
@Test
@ -192,8 +192,8 @@ public class GuardrailsTest extends GuardrailTester
assertValid(() -> disallowed.guard(set(1), action, superClientState));
String message = "Provided values [2] are not allowed for integer (disallowed values are: [2])";
assertAborts(() -> disallowed.guard(set(2), action, null), message);
assertAborts(() -> disallowed.guard(set(2), action, userClientState), message);
assertFails(() -> disallowed.guard(set(2), action, null), message);
assertFails(() -> disallowed.guard(set(2), action, userClientState), message);
assertValid(() -> disallowed.guard(set(2), action, systemClientState));
assertValid(() -> disallowed.guard(set(2), action, superClientState));
@ -205,8 +205,8 @@ public class GuardrailsTest extends GuardrailTester
Set<Integer> disallowedValues = set(2);
message = "Provided values [2] are not allowed for integer (disallowed values are: [2])";
assertAborts(() -> disallowed.guard(disallowedValues, action, null), message);
assertAborts(() -> disallowed.guard(disallowedValues, action, userClientState), message);
assertFails(() -> disallowed.guard(disallowedValues, action, null), message);
assertFails(() -> disallowed.guard(disallowedValues, action, userClientState), message);
assertValid(() -> disallowed.guard(disallowedValues, action, systemClientState));
assertValid(() -> disallowed.guard(disallowedValues, action, superClientState));
}

View File

@ -25,7 +25,7 @@ import java.util.function.ToLongFunction;
import org.junit.Before;
import org.junit.Test;
import org.apache.cassandra.config.GuardrailsOptions;
import org.apache.cassandra.config.Config;
import org.assertj.core.api.Assertions;
import static java.lang.String.format;
@ -39,41 +39,40 @@ public abstract class ThresholdTester extends GuardrailTester
{
private final String name;
private final long warnThreshold;
private final long abortThreshold;
private final GuardrailsOptions.Threshold config;
private final long failThreshold;
private final TriConsumer<Guardrails, Long, Long> setter;
private final ToLongFunction<Guardrails> warnGetter;
private final ToLongFunction<Guardrails> abortGetter;
private final ToLongFunction<Guardrails> failGetter;
private final long maxValue = Integer.MAX_VALUE;
protected ThresholdTester(long warnThreshold,
long abortThreshold,
GuardrailsOptions.Threshold config,
long failThreshold,
String name,
TriConsumer<Guardrails, Long, Long> setter,
ToLongFunction<Guardrails> warnGetter,
ToLongFunction<Guardrails> abortGetter)
ToLongFunction<Guardrails> failGetter)
{
this.name = config.getName();
this.name = name;
this.warnThreshold = warnThreshold;
this.abortThreshold = abortThreshold;
this.config = config;
this.failThreshold = failThreshold;
this.setter = setter;
this.warnGetter = warnGetter;
this.abortGetter = abortGetter;
this.failGetter = failGetter;
}
protected ThresholdTester(int warnThreshold,
int abortThreshold,
GuardrailsOptions.IntThreshold config,
int failThreshold,
String name,
TriConsumer<Guardrails, Integer, Integer> setter,
ToIntFunction<Guardrails> warnGetter,
ToIntFunction<Guardrails> abortGetter)
ToIntFunction<Guardrails> failGetter)
{
this(warnThreshold,
abortThreshold,
(GuardrailsOptions.Threshold) config,
(g, w, a) -> setter.accept(g, w.intValue(), a.intValue()),
g -> (long) warnGetter.applyAsInt(g),
g -> (long) abortGetter.applyAsInt(g));
this.name = name;
this.warnThreshold = warnThreshold;
this.failThreshold = failThreshold;
this.setter = (g, w, a) -> setter.accept(g, w.intValue(), a.intValue());
this.warnGetter = g -> (long) warnGetter.applyAsInt(g);
this.failGetter = g -> (long) failGetter.applyAsInt(g);
}
protected abstract long currentValue();
@ -86,26 +85,26 @@ public abstract class ThresholdTester extends GuardrailTester
@Before
public void before()
{
setter.accept(guardrails(), warnThreshold, abortThreshold);
setter.accept(guardrails(), warnThreshold, failThreshold);
}
@Test
public void testConfigValidation()
{
testValidationOfThresholdProperties(name + ".warn_threshold", name + ".abort_threshold");
testValidationOfThresholdProperties(name + "_warn_threshold", name + "_fail_threshold");
}
protected void testValidationOfThresholdProperties(String warnName, String abortName)
protected void testValidationOfThresholdProperties(String warnName, String failName)
{
setter.accept(guardrails(), -1L, -1L);
testValidationOfStrictlyPositiveProperty((g, a) -> setter.accept(g, -1L, a), abortName);
testValidationOfStrictlyPositiveProperty((g, a) -> setter.accept(g, -1L, a), failName);
testValidationOfStrictlyPositiveProperty((g, w) -> setter.accept(g, w, -1L), warnName);
setter.accept(guardrails(), -1L, -1L);
Assertions.assertThatThrownBy(() -> setter.accept(guardrails(), 2L, 1L))
.hasMessageContaining(format("The warn threshold 2 for %s should be lower than the abort threshold 1",
name));
.hasMessageContaining(format("The warn threshold 2 for %s should be lower than the fail threshold 1",
name + "_warn_threshold"));
}
protected void assertThresholdValid(String query) throws Throwable
@ -114,7 +113,7 @@ public abstract class ThresholdTester extends GuardrailTester
Assertions.assertThat(currentValue())
.isLessThanOrEqualTo(warnGetter.applyAsLong(guardrails()))
.isLessThanOrEqualTo(abortGetter.applyAsLong(guardrails()));
.isLessThanOrEqualTo(failGetter.applyAsLong(guardrails()));
}
protected void assertThresholdWarns(String message, String query) throws Throwable
@ -123,16 +122,16 @@ public abstract class ThresholdTester extends GuardrailTester
Assertions.assertThat(currentValue())
.isGreaterThan(warnGetter.applyAsLong(guardrails()))
.isLessThanOrEqualTo(abortGetter.applyAsLong(guardrails()));
.isLessThanOrEqualTo(failGetter.applyAsLong(guardrails()));
}
protected void assertThresholdAborts(String message, String query) throws Throwable
protected void assertThresholdFails(String message, String query) throws Throwable
{
assertAborts(message, query);
assertFails(message, query);
Assertions.assertThat(currentValue())
.isGreaterThanOrEqualTo(warnGetter.applyAsLong(guardrails()))
.isEqualTo(abortGetter.applyAsLong(guardrails()));
.isEqualTo(failGetter.applyAsLong(guardrails()));
}
private void assertInvalidPositiveProperty(BiConsumer<Guardrails, Long> setter,
@ -155,12 +154,12 @@ public abstract class ThresholdTester extends GuardrailTester
value, name, maxValue);
if (value == 0 && !allowZero)
expectedMessage = format("Invalid value for %s: 0 is not allowed; if attempting to disable use %s",
name, GuardrailsOptions.Threshold.DISABLED);
name, Config.DISABLED_GUARDRAIL);
if (value < GuardrailsOptions.Threshold.DISABLED)
if (value < Config.DISABLED_GUARDRAIL)
expectedMessage = format("Invalid value %d for %s: negative values are not "
+ "allowed, outside of %s which disables the guardrail",
value, name, GuardrailsOptions.Threshold.DISABLED);
value, name, Config.DISABLED_GUARDRAIL);
assertEquals(format("Exception message '%s' does not contain '%s'", e.getMessage(), expectedMessage),
expectedMessage, e.getMessage());
@ -169,18 +168,18 @@ public abstract class ThresholdTester extends GuardrailTester
private void assertInvalidStrictlyPositiveProperty(BiConsumer<Guardrails, Long> setter, long value, String name)
{
assertInvalidPositiveProperty(setter, value, config.maxValue(), config.allowZero(), name);
assertInvalidPositiveProperty(setter, value, maxValue, false, name);
}
protected void testValidationOfStrictlyPositiveProperty(BiConsumer<Guardrails, Long> setter, String name)
{
assertInvalidStrictlyPositiveProperty(setter, Integer.MIN_VALUE, name);
assertInvalidStrictlyPositiveProperty(setter, -2, name);
assertValidProperty(setter, GuardrailsOptions.Threshold.DISABLED); // disabled
assertValidProperty(setter, (long) Config.DISABLED_GUARDRAIL); // disabled
assertInvalidStrictlyPositiveProperty(setter, 0, name);
assertValidProperty(setter, 1L);
assertValidProperty(setter, 2L);
assertValidProperty(setter, config.maxValue());
assertValidProperty(setter, maxValue);
}
@FunctionalInterface