1
0
Эх сурвалжийг харах

Script: Implicit context cache (#81552)

The script context cache is deprecated.

In 7.16 the default value of `script.max_compilation_rate` was switched from `"use-context"`,
to `"150/5m"`.

That means uses would have to explicitly set `"use-context"` to use any of the context cache families of settings:
`script.context.*.max_compilations_rate`
`script.context.*.cache_max_size`
`script.context.*.cache_expire`

On upgrades to 7.16, if the customer was using the default and had set any of those settings without setting
`script.max_compilation_rate: "use-context"`, the upgrade would be fail.

To avoid an unintentional breaking change, the script service will now **implicitly** use the script context cache if 
`script.max_compilation_rate` is **unset** and any of the context cache family of settings is set.

The context cache will also be used if `script.max_compilation_rate: "use-context"`, as before.

Fixes: #81486
Stuart Tettemer 3 жил өмнө
parent
commit
ba6c17d30f

+ 5 - 0
docs/changelog/81552.yaml

@@ -0,0 +1,5 @@
+pr: 81552
+summary: "Script: Implicit context cache"
+area: Infra/Scripting
+type: bug
+issues: []

+ 158 - 39
server/src/main/java/org/elasticsearch/script/ScriptService.java

@@ -299,6 +299,14 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
         return SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings).equals(USE_CONTEXT_RATE_VALUE);
     }
 
+    public static boolean isImplicitContextCacheSet(Settings settings) {
+        return new ScriptService.ContextSettings(settings).implicitContextCache();
+    }
+
+    public static String contextDeprecationMessage(Settings settings) {
+        return new ScriptService.ContextSettings(settings).deprecationMessage();
+    }
+
     /**
      * This is overridden in tests to disable compilation rate limiting.
      */
@@ -345,53 +353,26 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
      * when using the general cache.
      */
     void validateCacheSettings(Settings settings) {
-        boolean useContext = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings).equals(USE_CONTEXT_RATE_VALUE);
-        if (useContext) {
+        ContextSettings contextSettings = new ContextSettings(settings, contexts.keySet());
+        if (contextSettings.useContextSet) {
             deprecationLogger.warn(DeprecationCategory.SCRIPTING, "scripting-context-cache", USE_CONTEXT_RATE_KEY_DEPRECATION_MESSAGE);
+        } else if (contextSettings.hasContextSettings()) {
+            deprecationLogger.warn(DeprecationCategory.SCRIPTING, "scripting-context-cache", contextSettings.deprecationMessage());
         }
-        List<Setting.AffixSetting<?>> affixes = Arrays.asList(
-            SCRIPT_MAX_COMPILATIONS_RATE_SETTING,
-            SCRIPT_CACHE_EXPIRE_SETTING,
-            SCRIPT_CACHE_SIZE_SETTING
-        );
-        List<String> customRates = new ArrayList<>();
-        List<String> keys = new ArrayList<>();
-        for (Setting.AffixSetting<?> affix : affixes) {
-            for (String context : affix.getAsMap(settings).keySet()) {
-                String s = affix.getConcreteSettingForNamespace(context).getKey();
-                if (contexts.containsKey(context) == false) {
-                    throw new IllegalArgumentException("Context [" + context + "] doesn't exist for setting [" + s + "]");
-                }
-                keys.add(s);
-                if (affix.equals(SCRIPT_MAX_COMPILATIONS_RATE_SETTING)) {
-                    customRates.add(s);
-                }
-            }
-        }
-        if (useContext == false && keys.isEmpty() == false) {
-            keys.sort(Comparator.naturalOrder());
-            throw new IllegalArgumentException(
-                "Context cache settings ["
-                    + String.join(", ", keys)
-                    + "] requires ["
-                    + SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
-                    + "] to be ["
-                    + USE_CONTEXT_RATE_KEY
-                    + "]"
-            );
+        if (contextSettings.incompatibleSettings()) {
+            throw new IllegalArgumentException(contextSettings.incompatibleSettingsMessage());
         }
         if (SCRIPT_DISABLE_MAX_COMPILATIONS_RATE_SETTING.get(settings)) {
-            if (customRates.size() > 0) {
-                customRates.sort(Comparator.naturalOrder());
+            if (contextSettings.compilationContexts.size() > 0) {
                 throw new IllegalArgumentException(
                     "Cannot set custom context compilation rates ["
-                        + String.join(", ", customRates)
+                        + String.join(", ", contextSettings.contextCompilationKeys())
                         + "] if compile rates disabled via ["
                         + SCRIPT_DISABLE_MAX_COMPILATIONS_RATE_SETTING.getKey()
                         + "]"
                 );
             }
-            if (useContext == false && SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.exists(settings)) {
+            if (contextSettings.useContextSet == false && contextSettings.isGeneralCompilationRateSet) {
                 throw new IllegalArgumentException(
                     "Cannot set custom general compilation rates ["
                         + SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
@@ -405,6 +386,144 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
         }
     }
 
+    /**
+     * Collect settings related to script context and general caches.
+     *
+     * The general cache is used by default.
+     * The context cache is used if {@code script.max_compilations_rate} is {@code "use-context"}, a deprecated value.
+     * The context cache is used implicitly if {@code script.max_compilations_rate} is unset and any of the context
+     * cache family of settings is used:
+     *   {@code script.context.*.max_compilations_rate}, {@link ScriptService#SCRIPT_MAX_COMPILATIONS_RATE_SETTING}
+     *   {@code script.context.*.cache_max_size}, {@link ScriptService#SCRIPT_CACHE_SIZE_SETTING}
+     *   {@code script.context.*.cache_expire}, {@link ScriptService#SCRIPT_CACHE_EXPIRE_SETTING}
+     */
+    public static class ContextSettings {
+        public final Settings settings;
+        public final boolean useContextSet;
+        public final boolean isGeneralCompilationRateSet;
+        public final ScriptCache.CompilationRate generalCompilationRate;
+        public final List<String> compilationContexts;
+        public final List<String> sizeContexts;
+        public final List<String> expireContexts;
+
+        public ContextSettings(Settings settings, Set<String> contexts) {
+            this.settings = settings;
+            generalCompilationRate = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings);
+            useContextSet = generalCompilationRate.equals(USE_CONTEXT_RATE_VALUE);
+            isGeneralCompilationRateSet = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.exists(settings);
+            compilationContexts = getContexts(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, settings, contexts);
+            sizeContexts = getContexts(SCRIPT_CACHE_SIZE_SETTING, settings, contexts);
+            expireContexts = getContexts(SCRIPT_CACHE_EXPIRE_SETTING, settings, contexts);
+        }
+
+        public ContextSettings(Settings settings) {
+            this(settings, Collections.emptySet());
+        }
+
+        protected static List<String> getContexts(Setting.AffixSetting<?> setting, Settings settings, Set<String> contexts) {
+            List<String> contextSettings = new ArrayList<>();
+            for (String context : setting.getAsMap(settings).keySet()) {
+                if (contexts.isEmpty() == false && contexts.contains(context) == false) {
+                    String settingKey = setting.getConcreteSettingForNamespace(context).getKey();
+                    throw new IllegalArgumentException("Context [" + context + "] doesn't exist for setting [" + settingKey + "]");
+                }
+                contextSettings.add(context);
+            }
+            contextSettings.sort(Comparator.naturalOrder());
+            return contextSettings;
+        }
+
+        /** Are there any context specific settings */
+        public boolean hasContextSettings() {
+            return compilationContexts.isEmpty() == false || expireContexts.isEmpty() == false || sizeContexts.isEmpty() == false;
+        }
+
+        /** deprecation message for implicitly using the context cache */
+        public String deprecationMessage() {
+            // Implicitly using the script context cache is deprecated, remove the following deprecated settings to use the script general
+            // cache.
+            if (hasContextSettings() == false) {
+                return "";
+            }
+            List<String> settingsKeys = new ArrayList<>();
+            settingsKeys.addAll(fullKeys(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, compilationContexts));
+            settingsKeys.addAll(fullKeys(SCRIPT_CACHE_SIZE_SETTING, sizeContexts));
+            settingsKeys.addAll(fullKeys(SCRIPT_CACHE_EXPIRE_SETTING, expireContexts));
+            settingsKeys.sort(Comparator.naturalOrder());
+            return "Implicitly using the script context cache is deprecated, remove settings "
+                + "["
+                + String.join(", ", settingsKeys)
+                + "] to use the script general cache.";
+        }
+
+        /** the context specific max compilation keys */
+        public List<String> contextCompilationKeys() {
+            return fullKeys(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, compilationContexts);
+        }
+
+        /** the full keys for the contexts in the context affix setting */
+        protected static List<String> fullKeys(Setting.AffixSetting<?> affix, List<String> contexts) {
+            return contexts.stream().map(ctx -> affix.getConcreteSettingForNamespace(ctx).getKey()).collect(Collectors.toList());
+        }
+
+        /**
+         *  Should the context cache be used?  This is true if "use-context" is set explicitly or implicitly, see above for implicit
+         *  definition.
+         */
+        public boolean useContextCache() {
+            return useContextSet || implicitContextCache();
+        }
+
+        /**
+         * Implicitly use the script context cache.  False if context cache is explicitly used as well as context cache is unused.
+         */
+        public boolean implicitContextCache() {
+            return useContextSet == false && hasContextSettings() && isGeneralCompilationRateSet == false;
+        }
+
+        /**
+         * Is the set of settings incompatible?  This is the case if:
+         * 1) {@code script.max_compilations_rate}, {@link ScriptService#SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING} is set but not
+         *    set to "use-context".
+         * 2) Any of the context cache family of settings is set.
+         */
+        public boolean incompatibleSettings() {
+            return useContextSet == false && hasContextSettings() && isGeneralCompilationRateSet;
+        }
+
+        /**
+         * All context specific settings
+         */
+        public List<String> contextSettings() {
+            List<String> contextSettings = fullKeys(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, compilationContexts);
+            contextSettings.addAll(fullKeys(SCRIPT_CACHE_SIZE_SETTING, sizeContexts));
+            contextSettings.addAll(fullKeys(SCRIPT_CACHE_EXPIRE_SETTING, expireContexts));
+            return contextSettings;
+        }
+
+        /**
+         * Error message if there are incompatible settings.
+         */
+        public String incompatibleSettingsMessage() {
+            if (incompatibleSettings() == false) {
+                return "";
+            }
+            List<String> incompatible = contextSettings();
+            return "Context cache settings ["
+                + String.join(",", incompatible)
+                + "] are incompatible with ["
+                + SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
+                + "] set to non-default value ["
+                + generalCompilationRate
+                + "]."
+                + " Either remove the incompatible settings (recommended) or set ["
+                + SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
+                + "] to ["
+                + USE_CONTEXT_RATE_KEY
+                + "] to use per-context settings";
+        }
+    }
+
     @Override
     public void close() throws IOException {
         IOUtils.close(engines.values());
@@ -692,10 +811,10 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
 
     void setCacheHolder(Settings settings) {
         CacheHolder current = cacheHolder.get();
-        boolean useContext = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings).equals(USE_CONTEXT_RATE_VALUE);
+        ContextSettings contextSettings = new ContextSettings(settings, contexts.keySet());
 
         if (current == null) {
-            if (useContext) {
+            if (contextSettings.useContextCache()) {
                 cacheHolder.set(contextCacheHolder(settings));
             } else {
                 cacheHolder.set(generalCacheHolder(settings));
@@ -704,7 +823,7 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
         }
 
         // Update
-        if (useContext) {
+        if (contextSettings.useContextCache()) {
             if (current.general != null) {
                 // Flipping to context specific
                 cacheHolder.set(contextCacheHolder(settings));

+ 73 - 17
server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java

@@ -27,6 +27,7 @@ import org.elasticsearch.xcontent.XContentType;
 import org.junit.Before;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -500,45 +501,44 @@ public class ScriptServiceTests extends ESTestCase {
     }
 
     public void testConflictContextSettings() throws IOException {
+        String fieldCacheKey = ScriptService.SCRIPT_CACHE_SIZE_SETTING.getConcreteSettingForNamespace("field").getKey();
         IllegalArgumentException illegal = expectThrows(IllegalArgumentException.class, () -> {
             buildScriptService(
-                Settings.builder()
-                    .put(SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey(), "10/1m")
-                    .put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getConcreteSettingForNamespace("field").getKey(), 123)
-                    .build()
+                Settings.builder().put(SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey(), "10/1m").put(fieldCacheKey, 123).build()
             );
         });
         assertEquals(
-            "Context cache settings [script.context.field.cache_max_size] requires " + "[script.max_compilations_rate] to be [use-context]",
+            "Context cache settings [script.context.field.cache_max_size] are incompatible with [script.max_compilations_rate]"
+                + " set to non-default value [10/1m]. Either remove the incompatible settings (recommended) or set"
+                + " [script.max_compilations_rate] to [use-context] to use per-context settings",
             illegal.getMessage()
         );
 
+        String ingestExpireKey = ScriptService.SCRIPT_CACHE_EXPIRE_SETTING.getConcreteSettingForNamespace("ingest").getKey();
         illegal = expectThrows(IllegalArgumentException.class, () -> {
             buildScriptService(
-                Settings.builder()
-                    .put(SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey(), "10/1m")
-                    .put(ScriptService.SCRIPT_CACHE_EXPIRE_SETTING.getConcreteSettingForNamespace("ingest").getKey(), "5m")
-                    .build()
+                Settings.builder().put(SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey(), "10/1m").put(ingestExpireKey, "5m").build()
             );
         });
 
         assertEquals(
-            "Context cache settings [script.context.ingest.cache_expire] requires " + "[script.max_compilations_rate] to be [use-context]",
+            "Context cache settings [script.context.ingest.cache_expire] are incompatible with [script.max_compilations_rate]"
+                + " set to non-default value [10/1m]. Either remove the incompatible settings (recommended) or set"
+                + " [script.max_compilations_rate] to [use-context] to use per-context settings",
             illegal.getMessage()
         );
 
+        String scoreCompileKey = ScriptService.SCRIPT_MAX_COMPILATIONS_RATE_SETTING.getConcreteSettingForNamespace("score").getKey();
         illegal = expectThrows(IllegalArgumentException.class, () -> {
             buildScriptService(
-                Settings.builder()
-                    .put(SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey(), "10/1m")
-                    .put(ScriptService.SCRIPT_MAX_COMPILATIONS_RATE_SETTING.getConcreteSettingForNamespace("score").getKey(), "50/5m")
-                    .build()
+                Settings.builder().put(SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey(), "10/1m").put(scoreCompileKey, "50/5m").build()
             );
         });
 
         assertEquals(
-            "Context cache settings [script.context.score.max_compilations_rate] requires "
-                + "[script.max_compilations_rate] to be [use-context]",
+            "Context cache settings [script.context.score.max_compilations_rate] are incompatible with [script.max_compilations_rate]"
+                + " set to non-default value [10/1m]. Either remove the incompatible settings (recommended) or set"
+                + " [script.max_compilations_rate] to [use-context] to use per-context settings",
             illegal.getMessage()
         );
 
@@ -556,10 +556,19 @@ public class ScriptServiceTests extends ESTestCase {
         );
         assertSettingDeprecationsAndWarnings(
             new Setting<?>[] { ingestExpire, fieldSize, scoreCompilation },
-            new DeprecationWarning(Level.WARN, USE_CONTEXT_RATE_KEY_DEPRECATION_MESSAGE)
+            new DeprecationWarning(Level.WARN, USE_CONTEXT_RATE_KEY_DEPRECATION_MESSAGE),
+            new DeprecationWarning(Level.WARN, implicitContextCacheMessage(fieldCacheKey)),
+            new DeprecationWarning(Level.WARN, implicitContextCacheMessage(ingestExpireKey)),
+            new DeprecationWarning(Level.WARN, implicitContextCacheMessage(scoreCompileKey))
         );
     }
 
+    protected static String implicitContextCacheMessage(String... settings) {
+        return "Implicitly using the script context cache is deprecated, remove settings ["
+            + Arrays.stream(settings).sorted().collect(Collectors.joining(", "))
+            + "] to use the script general cache.";
+    }
+
     public void testFallbackContextSettings() {
         int cacheSizeBackup = randomIntBetween(0, 1024);
         int cacheSizeFoo = randomValueOtherThan(cacheSizeBackup, () -> randomIntBetween(0, 1024));
@@ -643,6 +652,53 @@ public class ScriptServiceTests extends ESTestCase {
         );
     }
 
+    public void testImplicitContextCache() throws IOException {
+        String a = randomFrom(rateLimitedContexts.keySet());
+        String b = randomValueOtherThan(a, () -> randomFrom(rateLimitedContexts.keySet()));
+        String aCompilationRate = "77/5m";
+        String bCompilationRate = "78/6m";
+
+        Setting<?> aSetting = SCRIPT_MAX_COMPILATIONS_RATE_SETTING.getConcreteSettingForNamespace(a);
+        Setting<?> bSetting = SCRIPT_MAX_COMPILATIONS_RATE_SETTING.getConcreteSettingForNamespace(b);
+        buildScriptService(Settings.builder().put(aSetting.getKey(), aCompilationRate).put(bSetting.getKey(), bCompilationRate).build());
+
+        assertNull(scriptService.cacheHolder.get().general);
+        assertNotNull(scriptService.cacheHolder.get().contextCache);
+        assertEquals(contexts.keySet(), scriptService.cacheHolder.get().contextCache.keySet());
+
+        assertEquals(new ScriptCache.CompilationRate(aCompilationRate), scriptService.cacheHolder.get().contextCache.get(a).get().rate);
+        assertEquals(new ScriptCache.CompilationRate(bCompilationRate), scriptService.cacheHolder.get().contextCache.get(b).get().rate);
+        assertSettingDeprecationsAndWarnings(
+            new Setting<?>[] { aSetting, bSetting },
+            new DeprecationWarning(Level.WARN, implicitContextCacheMessage(aSetting.getKey(), bSetting.getKey()))
+        );
+    }
+
+    public void testImplicitContextCacheWithoutCompilationRate() throws IOException {
+        String a = randomFrom(rateLimitedContexts.keySet());
+        String b = randomValueOtherThan(a, () -> randomFrom(rateLimitedContexts.keySet()));
+        String aExpire = "20m";
+        int bSize = 2000;
+
+        Setting<?> aSetting = SCRIPT_CACHE_EXPIRE_SETTING.getConcreteSettingForNamespace(a);
+        Setting<?> bSetting = SCRIPT_CACHE_SIZE_SETTING.getConcreteSettingForNamespace(b);
+        buildScriptService(Settings.builder().put(aSetting.getKey(), aExpire).put(bSetting.getKey(), bSize).build());
+
+        assertNull(scriptService.cacheHolder.get().general);
+        assertNotNull(scriptService.cacheHolder.get().contextCache);
+        assertEquals(contexts.keySet(), scriptService.cacheHolder.get().contextCache.keySet());
+
+        assertEquals(
+            TimeValue.parseTimeValue("20m", aSetting.getKey()),
+            scriptService.cacheHolder.get().contextCache.get(a).get().cacheExpire
+        );
+        assertEquals(bSize, scriptService.cacheHolder.get().contextCache.get(b).get().cacheSize);
+        assertSettingDeprecationsAndWarnings(
+            new Setting<?>[] { aSetting, bSetting },
+            new DeprecationWarning(Level.WARN, implicitContextCacheMessage(aSetting.getKey(), bSetting.getKey()))
+        );
+    }
+
     public void testCompilationRateUnlimitedContextOnly() throws IOException {
         IllegalArgumentException illegal = expectThrows(IllegalArgumentException.class, () -> {
             buildScriptService(

+ 12 - 1
x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/NodeDeprecationChecks.java

@@ -482,7 +482,18 @@ public class NodeDeprecationChecks {
     ) {
         Setting.AffixSetting<?> maxSetting = ScriptService.SCRIPT_MAX_COMPILATIONS_RATE_SETTING;
         Set<String> contextCompilationRates = maxSetting.getAsMap(settings).keySet();
-        if (contextCompilationRates.isEmpty() == false) {
+        if (ScriptService.isImplicitContextCacheSet(settings)) {
+            return new DeprecationIssue(
+                DeprecationIssue.Level.WARNING,
+                ScriptService.contextDeprecationMessage(settings),
+                "https://ela.st/es-deprecation-7-script-context-cache",
+                "Remove the context-specific cache settings and set [script.max_compilations_rate] to configure the rate limit for the "
+                    + "general cache. If no limit is set, the rate defaults to 150 compilations per five minutes: 150/5m. Context-specific "
+                    + "caches are no longer needed to prevent system scripts from triggering rate limits.",
+                false,
+                null
+            );
+        } else if (contextCompilationRates.isEmpty() == false) {
             String maxSettings = contextCompilationRates.stream()
                 .sorted()
                 .map(c -> maxSetting.getConcreteSettingForNamespace(c).getKey())

+ 35 - 0
x-pack/plugin/deprecation/src/test/java/org/elasticsearch/xpack/deprecation/NodeDeprecationChecksTests.java

@@ -498,6 +498,41 @@ public class NodeDeprecationChecksTests extends ESTestCase {
         );
     }
 
+    public void testImplicitScriptContextCacheSetting() {
+        List<String> contexts = List.of("update", "filter");
+        Settings settings = Settings.builder()
+            .put(ScriptService.SCRIPT_MAX_COMPILATIONS_RATE_SETTING.getConcreteSettingForNamespace(contexts.get(0)).getKey(), "123/5m")
+            .put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getConcreteSettingForNamespace(contexts.get(1)).getKey(), "2453")
+            .build();
+
+        List<DeprecationIssue> issues = DeprecationChecks.filterChecks(NODE_SETTINGS_CHECKS, c -> c.apply(settings, null));
+
+        assertThat(
+            issues,
+            hasItem(
+                new DeprecationIssue(
+                    DeprecationIssue.Level.WARNING,
+                    "Implicitly using the script context cache is deprecated, remove settings "
+                        + "[script.context.filter.cache_max_size, script.context.update.max_compilations_rate] "
+                        + "to use the script general cache.",
+                    "https://ela.st/es-deprecation-7-script-context-cache",
+                    "Remove the context-specific cache settings and set [script.max_compilations_rate] to configure the rate limit for "
+                        + "the general cache. If no limit is set, the rate defaults to 150 compilations per five minutes: 150/5m. "
+                        + "Context-specific caches are no longer needed to prevent system scripts from triggering rate limits.",
+                    false,
+                    null
+                )
+            )
+        );
+
+        assertWarnings(
+            "[script.context.update.max_compilations_rate] setting was deprecated in Elasticsearch and will be"
+                + " removed in a future release! See the breaking changes documentation for the next major version.",
+            "[script.context.filter.cache_max_size] setting was deprecated in Elasticsearch and will be removed in a future"
+                + " release! See the breaking changes documentation for the next major version."
+        );
+    }
+
     public void testScriptContextCacheSizeSetting() {
         List<String> contexts = List.of("filter", "update");
         Settings settings = Settings.builder()