Correct warning header to be compliant
The warning header used by Elasticsearch for delivering deprecation warnings has a specific format (RFC 7234, section 5.5). The format specifies that the warning header should be of the form warn-code warn-agent warn-text [warn-date] Here, the warn-code is a three-digit code which communicates various meanings. The warn-agent is a string used to identify the source of the warning (either a host:port combination, or some other identifier). The warn-text is quoted string which conveys the semantic meaning of the warning. The warn-date is an optional quoted date that can be in a few different formats. This commit corrects the warning header within Elasticsearch to follow this specification. We use the warn-code 299 which means a "miscellaneous persistent warning." For the warn-agent, we use the version of Elasticsearch that produced the warning. The warn-text is unchanged from what we deliver today, but is wrapped in quotes as specified (this is important as a problem that exists today is that multiple warnings can not be split by comma to obtain the individual warnings as the warnings might themselves contain commas). For the warn-date, we use the RFC 1123 format. Relates #23275
This commit is contained in:
parent
2fb0466f66
commit
577e6a5e14
|
@ -21,13 +21,21 @@ package org.elasticsearch.common.logging;
|
|||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.Build;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.SuppressLoggerChecks;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A logger that logs deprecation notices.
|
||||
|
@ -36,14 +44,6 @@ public class DeprecationLogger {
|
|||
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* The "Warning" Header comes from RFC-7234. As the RFC describes, it's generally used for caching purposes, but it can be
|
||||
* used for <em>any</em> warning.
|
||||
*
|
||||
* https://tools.ietf.org/html/rfc7234#section-5.5
|
||||
*/
|
||||
public static final String WARNING_HEADER = "Warning";
|
||||
|
||||
/**
|
||||
* This is set once by the {@code Node} constructor, but it uses {@link CopyOnWriteArraySet} to ensure that tests can run in parallel.
|
||||
* <p>
|
||||
|
@ -112,6 +112,57 @@ public class DeprecationLogger {
|
|||
deprecated(THREAD_CONTEXT, msg, params);
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC7234 specifies the warning format as warn-code <space> warn-agent <space> "warn-text" [<space> "warn-date"]. Here, warn-code is a
|
||||
* three-digit number with various standard warn codes specified. The warn code 299 is apt for our purposes as it represents a
|
||||
* miscellaneous persistent warning (can be presented to a human, or logged, and must not be removed by a cache). The warn-agent is an
|
||||
* arbitrary token; here we use the Elasticsearch version and build hash. The warn text must be quoted. The warn-date is an optional
|
||||
* quoted field that can be in a variety of specified date formats; here we use RFC 1123 format.
|
||||
*/
|
||||
private static final String WARNING_FORMAT =
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"299 Elasticsearch-%s%s-%s ",
|
||||
Version.CURRENT.toString(),
|
||||
Build.CURRENT.isSnapshot() ? "-SNAPSHOT" : "",
|
||||
Build.CURRENT.shortHash()) +
|
||||
"\"%s\" \"%s\"";
|
||||
|
||||
private static final ZoneId GMT = ZoneId.of("GMT");
|
||||
|
||||
/**
|
||||
* Regular expression to test if a string matches the RFC7234 specification for warning headers. This pattern assumes that the warn code
|
||||
* is always 299. Further, this pattern assumes that the warn agent represents a version of Elasticsearch including the build hash.
|
||||
*/
|
||||
public static Pattern WARNING_HEADER_PATTERN = Pattern.compile(
|
||||
"299 " + // warn code
|
||||
"Elasticsearch-\\d+\\.\\d+\\.\\d+(?:-(?:alpha|beta|rc)\\d+)?(?:-SNAPSHOT)?-(?:[a-f0-9]{7}|Unknown) " + // warn agent
|
||||
"\"((?:\t| |!|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x80-\\xff]|\\\\|\\\\\")*)\" " + // quoted warning value, captured
|
||||
// quoted RFC 1123 date format
|
||||
"\"" + // opening quote
|
||||
"(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), " + // weekday
|
||||
"\\d{2} " + // 2-digit day
|
||||
"(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) " + // month
|
||||
"\\d{4} " + // 4-digit year
|
||||
"\\d{2}:\\d{2}:\\d{2} " + // (two-digit hour):(two-digit minute):(two-digit second)
|
||||
"GMT" + // GMT
|
||||
"\""); // closing quote
|
||||
|
||||
/**
|
||||
* Extracts the warning value from the value of a warning header that is formatted according to RFC 7234. That is, given a string
|
||||
* {@code 299 Elasticsearch-6.0.0 "warning value" "Sat, 25 Feb 2017 10:27:43 GMT"}, the return value of this method would be {@code
|
||||
* warning value}.
|
||||
*
|
||||
* @param s the value of a warning header formatted according to RFC 7234.
|
||||
* @return the extracted warning value
|
||||
*/
|
||||
public static String extractWarningValueFromWarningHeader(final String s) {
|
||||
final Matcher matcher = WARNING_HEADER_PATTERN.matcher(s);
|
||||
final boolean matches = matcher.matches();
|
||||
assert matches;
|
||||
return matcher.group(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a deprecated message to the deprecation log, as well as to the local {@link ThreadContext}.
|
||||
*
|
||||
|
@ -120,16 +171,19 @@ public class DeprecationLogger {
|
|||
* @param params The parameters used to fill in the message, if any exist.
|
||||
*/
|
||||
@SuppressLoggerChecks(reason = "safely delegates to logger")
|
||||
void deprecated(Set<ThreadContext> threadContexts, String message, Object... params) {
|
||||
Iterator<ThreadContext> iterator = threadContexts.iterator();
|
||||
void deprecated(final Set<ThreadContext> threadContexts, final String message, final Object... params) {
|
||||
final Iterator<ThreadContext> iterator = threadContexts.iterator();
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
final String formattedMessage = LoggerMessageFormat.format(message, params);
|
||||
|
||||
final String warningHeaderValue = formatWarning(formattedMessage);
|
||||
assert WARNING_HEADER_PATTERN.matcher(warningHeaderValue).matches();
|
||||
assert extractWarningValueFromWarningHeader(warningHeaderValue).equals(escape(formattedMessage));
|
||||
while (iterator.hasNext()) {
|
||||
try {
|
||||
iterator.next().addResponseHeader(WARNING_HEADER, formattedMessage);
|
||||
} catch (IllegalStateException e) {
|
||||
final ThreadContext next = iterator.next();
|
||||
next.addResponseHeader("Warning", warningHeaderValue, DeprecationLogger::extractWarningValueFromWarningHeader);
|
||||
} catch (final IllegalStateException e) {
|
||||
// ignored; it should be removed shortly
|
||||
}
|
||||
}
|
||||
|
@ -139,4 +193,25 @@ public class DeprecationLogger {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a warning string in the proper warning format by prepending a warn code, warn agent, wrapping the warning string in quotes,
|
||||
* and appending the RFC 1123 date.
|
||||
*
|
||||
* @param s the warning string to format
|
||||
* @return a warning value formatted according to RFC 7234
|
||||
*/
|
||||
public static String formatWarning(final String s) {
|
||||
return String.format(Locale.ROOT, WARNING_FORMAT, escape(s), DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(GMT)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape backslashes and quotes in the specified string.
|
||||
*
|
||||
* @param s the string to escape
|
||||
* @return the escaped string
|
||||
*/
|
||||
public static String escape(String s) {
|
||||
return s.replaceAll("(\\\\|\")", "\\\\$1");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,9 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -257,12 +259,25 @@ public final class ThreadContext implements Closeable, Writeable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add the <em>unique</em> response {@code value} for the specified {@code key}.
|
||||
* <p>
|
||||
* Any duplicate {@code value} is ignored.
|
||||
* Add the {@code value} for the specified {@code key} Any duplicate {@code value} is ignored.
|
||||
*
|
||||
* @param key the header name
|
||||
* @param value the header value
|
||||
*/
|
||||
public void addResponseHeader(String key, String value) {
|
||||
threadLocal.set(threadLocal.get().putResponse(key, value));
|
||||
public void addResponseHeader(final String key, final String value) {
|
||||
addResponseHeader(key, value, v -> v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the {@code value} for the specified {@code key} with the specified {@code uniqueValue} used for de-duplication. Any duplicate
|
||||
* {@code value} after applying {@code uniqueValue} is ignored.
|
||||
*
|
||||
* @param key the header name
|
||||
* @param value the header value
|
||||
* @param uniqueValue the function that produces de-duplication values
|
||||
*/
|
||||
public void addResponseHeader(final String key, final String value, final Function<String, String> uniqueValue) {
|
||||
threadLocal.set(threadLocal.get().putResponse(key, value, uniqueValue));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -396,14 +411,16 @@ public final class ThreadContext implements Closeable, Writeable {
|
|||
return new ThreadContextStruct(requestHeaders, newResponseHeaders, transientHeaders);
|
||||
}
|
||||
|
||||
private ThreadContextStruct putResponse(String key, String value) {
|
||||
private ThreadContextStruct putResponse(final String key, final String value, final Function<String, String> uniqueValue) {
|
||||
assert value != null;
|
||||
|
||||
final Map<String, List<String>> newResponseHeaders = new HashMap<>(this.responseHeaders);
|
||||
final List<String> existingValues = newResponseHeaders.get(key);
|
||||
|
||||
if (existingValues != null) {
|
||||
if (existingValues.contains(value)) {
|
||||
final Set<String> existingUniqueValues = existingValues.stream().map(uniqueValue).collect(Collectors.toSet());
|
||||
assert existingValues.size() == existingUniqueValues.size();
|
||||
if (existingUniqueValues.contains(uniqueValue.apply(value))) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
*/
|
||||
package org.elasticsearch.common.logging;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.hamcrest.RegexMatcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
@ -28,17 +30,22 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.elasticsearch.common.logging.DeprecationLogger.WARNING_HEADER_PATTERN;
|
||||
import static org.elasticsearch.test.hamcrest.RegexMatcher.matches;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
/**
|
||||
* Tests {@link DeprecationLogger}
|
||||
*/
|
||||
public class DeprecationLoggerTests extends ESTestCase {
|
||||
|
||||
private static final RegexMatcher warningValueMatcher = matches(WARNING_HEADER_PATTERN.pattern());
|
||||
|
||||
private final DeprecationLogger logger = new DeprecationLogger(Loggers.getLogger(getClass()));
|
||||
|
||||
@Override
|
||||
|
@ -48,43 +55,42 @@ public class DeprecationLoggerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testAddsHeaderWithThreadContext() throws IOException {
|
||||
String msg = "A simple message [{}]";
|
||||
String param = randomAsciiOfLengthBetween(1, 5);
|
||||
String formatted = LoggerMessageFormat.format(msg, (Object)param);
|
||||
|
||||
try (ThreadContext threadContext = new ThreadContext(Settings.EMPTY)) {
|
||||
Set<ThreadContext> threadContexts = Collections.singleton(threadContext);
|
||||
final Set<ThreadContext> threadContexts = Collections.singleton(threadContext);
|
||||
|
||||
logger.deprecated(threadContexts, msg, param);
|
||||
final String param = randomAsciiOfLengthBetween(1, 5);
|
||||
logger.deprecated(threadContexts, "A simple message [{}]", param);
|
||||
|
||||
Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
final Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
|
||||
assertEquals(1, responseHeaders.size());
|
||||
assertEquals(formatted, responseHeaders.get(DeprecationLogger.WARNING_HEADER).get(0));
|
||||
assertThat(responseHeaders.size(), equalTo(1));
|
||||
final List<String> responses = responseHeaders.get("Warning");
|
||||
assertThat(responses, hasSize(1));
|
||||
assertThat(responses.get(0), warningValueMatcher);
|
||||
assertThat(responses.get(0), containsString("\"A simple message [" + param + "]\""));
|
||||
}
|
||||
}
|
||||
|
||||
public void testAddsCombinedHeaderWithThreadContext() throws IOException {
|
||||
String msg = "A simple message [{}]";
|
||||
String param = randomAsciiOfLengthBetween(1, 5);
|
||||
String formatted = LoggerMessageFormat.format(msg, (Object)param);
|
||||
String formatted2 = randomAsciiOfLengthBetween(1, 10);
|
||||
|
||||
try (ThreadContext threadContext = new ThreadContext(Settings.EMPTY)) {
|
||||
Set<ThreadContext> threadContexts = Collections.singleton(threadContext);
|
||||
final Set<ThreadContext> threadContexts = Collections.singleton(threadContext);
|
||||
|
||||
logger.deprecated(threadContexts, msg, param);
|
||||
logger.deprecated(threadContexts, formatted2);
|
||||
final String param = randomAsciiOfLengthBetween(1, 5);
|
||||
logger.deprecated(threadContexts, "A simple message [{}]", param);
|
||||
final String second = randomAsciiOfLengthBetween(1, 10);
|
||||
logger.deprecated(threadContexts, second);
|
||||
|
||||
Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
final Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
|
||||
assertEquals(1, responseHeaders.size());
|
||||
|
||||
List<String> responses = responseHeaders.get(DeprecationLogger.WARNING_HEADER);
|
||||
final List<String> responses = responseHeaders.get("Warning");
|
||||
|
||||
assertEquals(2, responses.size());
|
||||
assertEquals(formatted, responses.get(0));
|
||||
assertEquals(formatted2, responses.get(1));
|
||||
assertThat(responses.get(0), warningValueMatcher);
|
||||
assertThat(responses.get(0), containsString("\"A simple message [" + param + "]\""));
|
||||
assertThat(responses.get(1), warningValueMatcher);
|
||||
assertThat(responses.get(1), containsString("\"" + second + "\""));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,28 +99,30 @@ public class DeprecationLoggerTests extends ESTestCase {
|
|||
final String unexpected = "testCannotRemoveThreadContext";
|
||||
|
||||
try (ThreadContext threadContext = new ThreadContext(Settings.EMPTY)) {
|
||||
// NOTE: by adding it to the logger, we allow any concurrent test to write to it (from their own threads)
|
||||
DeprecationLogger.setThreadContext(threadContext);
|
||||
|
||||
logger.deprecated(expected);
|
||||
|
||||
Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
List<String> responses = responseHeaders.get(DeprecationLogger.WARNING_HEADER);
|
||||
{
|
||||
final Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
final List<String> responses = responseHeaders.get("Warning");
|
||||
|
||||
// ensure it works (note: concurrent tests may be adding to it, but in different threads, so it should have no impact)
|
||||
assertThat(responses, hasSize(atLeast(1)));
|
||||
assertThat(responses, hasItem(equalTo(expected)));
|
||||
assertThat(responses, hasSize(1));
|
||||
assertThat(responses.get(0), warningValueMatcher);
|
||||
assertThat(responses.get(0), containsString(expected));
|
||||
}
|
||||
|
||||
DeprecationLogger.removeThreadContext(threadContext);
|
||||
|
||||
logger.deprecated(unexpected);
|
||||
|
||||
responseHeaders = threadContext.getResponseHeaders();
|
||||
responses = responseHeaders.get(DeprecationLogger.WARNING_HEADER);
|
||||
{
|
||||
final Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
final List<String> responses = responseHeaders.get("Warning");
|
||||
|
||||
assertThat(responses, hasSize(atLeast(1)));
|
||||
assertThat(responses, hasItem(expected));
|
||||
assertThat(responses, not(hasItem(unexpected)));
|
||||
assertThat(responses, hasSize(1));
|
||||
assertThat(responses.get(0), warningValueMatcher);
|
||||
assertThat(responses.get(0), containsString(expected));
|
||||
assertThat(responses.get(0), not(containsString(unexpected)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,4 +166,28 @@ public class DeprecationLoggerTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testWarningValueFromWarningHeader() throws InterruptedException {
|
||||
final String s = randomAsciiOfLength(16);
|
||||
final String first = DeprecationLogger.formatWarning(s);
|
||||
assertThat(DeprecationLogger.extractWarningValueFromWarningHeader(first), equalTo(s));
|
||||
}
|
||||
|
||||
public void testEscape() {
|
||||
assertThat(DeprecationLogger.escape("\\"), equalTo("\\\\"));
|
||||
assertThat(DeprecationLogger.escape("\""), equalTo("\\\""));
|
||||
assertThat(DeprecationLogger.escape("\\\""), equalTo("\\\\\\\""));
|
||||
assertThat(DeprecationLogger.escape("\"foo\\bar\""),equalTo("\\\"foo\\\\bar\\\""));
|
||||
// test that characters other than '\' and '"' are left unchanged
|
||||
String chars = "\t !" + range(0x23, 0x5b + 1) + range(0x5d, 0x73 + 1) + range(0x80, 0xff + 1);
|
||||
final String s = new CodepointSetGenerator(chars.toCharArray()).ofCodePointsLength(random(), 16, 16);
|
||||
assertThat(DeprecationLogger.escape(s), equalTo(s));
|
||||
}
|
||||
|
||||
private String range(int lowerInclusive, int upperInclusive) {
|
||||
return IntStream
|
||||
.range(lowerInclusive, upperInclusive + 1)
|
||||
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.elasticsearch.common.util.concurrent;
|
||||
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
|
@ -178,6 +179,14 @@ public class ThreadContextTests extends ESTestCase {
|
|||
threadContext.addResponseHeader("foo", "bar");
|
||||
}
|
||||
|
||||
final String value = DeprecationLogger.formatWarning("qux");
|
||||
threadContext.addResponseHeader("baz", value, DeprecationLogger::extractWarningValueFromWarningHeader);
|
||||
// pretend that another thread created the same response at a different time
|
||||
if (randomBoolean()) {
|
||||
final String duplicateValue = DeprecationLogger.formatWarning("qux");
|
||||
threadContext.addResponseHeader("baz", duplicateValue, DeprecationLogger::extractWarningValueFromWarningHeader);
|
||||
}
|
||||
|
||||
threadContext.addResponseHeader("Warning", "One is the loneliest number");
|
||||
threadContext.addResponseHeader("Warning", "Two can be as bad as one");
|
||||
if (expectThird) {
|
||||
|
@ -186,11 +195,14 @@ public class ThreadContextTests extends ESTestCase {
|
|||
|
||||
final Map<String, List<String>> responseHeaders = threadContext.getResponseHeaders();
|
||||
final List<String> foo = responseHeaders.get("foo");
|
||||
final List<String> baz = responseHeaders.get("baz");
|
||||
final List<String> warnings = responseHeaders.get("Warning");
|
||||
final int expectedWarnings = expectThird ? 3 : 2;
|
||||
|
||||
assertThat(foo, hasSize(1));
|
||||
assertThat(baz, hasSize(1));
|
||||
assertEquals("bar", foo.get(0));
|
||||
assertEquals(value, baz.get(0));
|
||||
assertThat(warnings, hasSize(expectedWarnings));
|
||||
assertThat(warnings, hasItem(equalTo("One is the loneliest number")));
|
||||
assertThat(warnings, hasItem(equalTo("Two can be as bad as one")));
|
||||
|
|
|
@ -102,9 +102,9 @@ public class AzureDiscoveryPlugin extends Plugin implements DiscoveryPlugin {
|
|||
// setting existed. This check looks for the legacy setting, and sets hosts provider if set
|
||||
String discoveryType = DiscoveryModule.DISCOVERY_TYPE_SETTING.get(settings);
|
||||
if (discoveryType.equals(AZURE)) {
|
||||
deprecationLogger.deprecated("Using " + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
|
||||
" setting to set hosts provider is deprecated. " +
|
||||
"Set \"" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + AZURE + "\" instead");
|
||||
deprecationLogger.deprecated("using [" + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
|
||||
"] to set hosts provider is deprecated; " +
|
||||
"set \"" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + AZURE + "\" instead");
|
||||
if (DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.exists(settings) == false) {
|
||||
return Settings.builder().put(DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey(), AZURE).build();
|
||||
}
|
||||
|
|
|
@ -165,9 +165,9 @@ public class Ec2DiscoveryPlugin extends Plugin implements DiscoveryPlugin, Close
|
|||
// setting existed. This check looks for the legacy setting, and sets hosts provider if set
|
||||
String discoveryType = DiscoveryModule.DISCOVERY_TYPE_SETTING.get(settings);
|
||||
if (discoveryType.equals(EC2)) {
|
||||
deprecationLogger.deprecated("Using " + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
|
||||
" setting to set hosts provider is deprecated. " +
|
||||
"Set \"" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + EC2 + "\" instead");
|
||||
deprecationLogger.deprecated("using [" + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
|
||||
"] setting to set hosts provider is deprecated; " +
|
||||
"set [" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + EC2 + "] instead");
|
||||
if (DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.exists(settings) == false) {
|
||||
builder.put(DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey(), EC2).build();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import com.amazonaws.ClientConfiguration;
|
|||
import com.amazonaws.Protocol;
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.AWSCredentialsProvider;
|
||||
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.repositories.s3.S3Repository;
|
||||
|
@ -65,8 +64,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(AwsS3Service.SECRET_SETTING.getKey(), "aws_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "aws_key", "aws_secret");
|
||||
assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(AwsS3Service.KEY_SETTING, AwsS3Service.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchS3SettingsBackcompat() {
|
||||
|
@ -75,8 +73,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey(), "s3_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "s3_key", "s3_secret");
|
||||
assertWarnings("[" + AwsS3Service.CLOUD_S3.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(AwsS3Service.CLOUD_S3.KEY_SETTING, AwsS3Service.CLOUD_S3.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchAwsAndS3SettingsBackcompat() {
|
||||
|
@ -87,10 +84,11 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey(), "s3_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "s3_key", "s3_secret");
|
||||
assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(
|
||||
AwsS3Service.KEY_SETTING,
|
||||
AwsS3Service.SECRET_SETTING,
|
||||
AwsS3Service.CLOUD_S3.KEY_SETTING,
|
||||
AwsS3Service.CLOUD_S3.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchRepositoriesSettingsBackcompat() {
|
||||
|
@ -99,8 +97,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "repositories_key", "repositories_secret");
|
||||
assertWarnings("[" + S3Repository.Repositories.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repositories.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(S3Repository.Repositories.KEY_SETTING, S3Repository.Repositories.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchAwsAndRepositoriesSettingsBackcompat() {
|
||||
|
@ -111,10 +108,11 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "repositories_key", "repositories_secret");
|
||||
assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repositories.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repositories.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(
|
||||
AwsS3Service.KEY_SETTING,
|
||||
AwsS3Service.SECRET_SETTING,
|
||||
S3Repository.Repositories.KEY_SETTING,
|
||||
S3Repository.Repositories.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchAwsAndS3AndRepositoriesSettingsBackcompat() {
|
||||
|
@ -127,12 +125,13 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "repositories_key", "repositories_secret");
|
||||
assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repositories.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repositories.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(
|
||||
AwsS3Service.KEY_SETTING,
|
||||
AwsS3Service.SECRET_SETTING,
|
||||
AwsS3Service.CLOUD_S3.KEY_SETTING,
|
||||
AwsS3Service.CLOUD_S3.SECRET_SETTING,
|
||||
S3Repository.Repositories.KEY_SETTING,
|
||||
S3Repository.Repositories.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchRepositoriesSettingsAndRepositorySettingsBackcompat() {
|
||||
|
@ -142,8 +141,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(repositorySettings, settings, "repository_key", "repository_secret");
|
||||
assertWarnings("[" + S3Repository.Repository.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repository.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(S3Repository.Repository.KEY_SETTING, S3Repository.Repository.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchAwsAndRepositoriesSettingsAndRepositorySettingsBackcompat() {
|
||||
|
@ -155,8 +153,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(repositorySettings, settings, "repository_key", "repository_secret");
|
||||
assertWarnings("[" + S3Repository.Repository.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repository.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(S3Repository.Repository.KEY_SETTING, S3Repository.Repository.SECRET_SETTING);
|
||||
}
|
||||
|
||||
public void testAWSCredentialsWithElasticsearchAwsAndS3AndRepositoriesSettingsAndRepositorySettingsBackcompat() {
|
||||
|
@ -170,8 +167,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
|
||||
.build();
|
||||
launchAWSCredentialsWithElasticsearchSettingsTest(repositorySettings, settings, "repository_key", "repository_secret");
|
||||
assertWarnings("[" + S3Repository.Repository.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + S3Repository.Repository.SECRET_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(S3Repository.Repository.KEY_SETTING, S3Repository.Repository.SECRET_SETTING);
|
||||
}
|
||||
|
||||
protected void launchAWSCredentialsWithElasticsearchSettingsTest(Settings singleRepositorySettings, Settings settings,
|
||||
|
@ -215,13 +211,14 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.build();
|
||||
launchAWSConfigurationTest(settings, Settings.EMPTY, Protocol.HTTP, "aws_proxy_host", 8080, "aws_proxy_username",
|
||||
"aws_proxy_password", "AWS3SignerType", 3, false, 10000);
|
||||
assertWarnings("[" + AwsS3Service.PROXY_USERNAME_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROXY_PASSWORD_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROTOCOL_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROXY_HOST_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROXY_PORT_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.SIGNER_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.READ_TIMEOUT.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(
|
||||
AwsS3Service.PROXY_USERNAME_SETTING,
|
||||
AwsS3Service.PROXY_PASSWORD_SETTING,
|
||||
AwsS3Service.PROTOCOL_SETTING,
|
||||
AwsS3Service.PROXY_HOST_SETTING,
|
||||
AwsS3Service.PROXY_PORT_SETTING,
|
||||
AwsS3Service.SIGNER_SETTING,
|
||||
AwsS3Service.READ_TIMEOUT);
|
||||
}
|
||||
|
||||
public void testAWSConfigurationWithAwsAndS3SettingsBackcompat() {
|
||||
|
@ -243,20 +240,21 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
.build();
|
||||
launchAWSConfigurationTest(settings, Settings.EMPTY, Protocol.HTTPS, "s3_proxy_host", 8081, "s3_proxy_username",
|
||||
"s3_proxy_password", "NoOpSignerType", 3, false, 10000);
|
||||
assertWarnings("[" + AwsS3Service.PROXY_USERNAME_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROXY_PASSWORD_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROTOCOL_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROXY_HOST_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.PROXY_PORT_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.SIGNER_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.READ_TIMEOUT.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.PROXY_USERNAME_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.PROXY_PASSWORD_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.PROTOCOL_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.PROXY_HOST_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.PROXY_PORT_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.SIGNER_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + AwsS3Service.CLOUD_S3.READ_TIMEOUT.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(
|
||||
AwsS3Service.PROXY_USERNAME_SETTING,
|
||||
AwsS3Service.PROXY_PASSWORD_SETTING,
|
||||
AwsS3Service.PROTOCOL_SETTING,
|
||||
AwsS3Service.PROXY_HOST_SETTING,
|
||||
AwsS3Service.PROXY_PORT_SETTING,
|
||||
AwsS3Service.SIGNER_SETTING,
|
||||
AwsS3Service.READ_TIMEOUT,
|
||||
AwsS3Service.CLOUD_S3.PROXY_USERNAME_SETTING,
|
||||
AwsS3Service.CLOUD_S3.PROXY_PASSWORD_SETTING,
|
||||
AwsS3Service.CLOUD_S3.PROTOCOL_SETTING,
|
||||
AwsS3Service.CLOUD_S3.PROXY_HOST_SETTING,
|
||||
AwsS3Service.CLOUD_S3.PROXY_PORT_SETTING,
|
||||
AwsS3Service.CLOUD_S3.SIGNER_SETTING,
|
||||
AwsS3Service.CLOUD_S3.READ_TIMEOUT);
|
||||
}
|
||||
|
||||
public void testGlobalMaxRetries() {
|
||||
|
@ -338,13 +336,13 @@ public class AwsS3ServiceImplTests extends ESTestCase {
|
|||
public void testEndpointSettingBackcompat() {
|
||||
assertEndpoint(generateRepositorySettings("repository_key", "repository_secret", "repository.endpoint", null),
|
||||
Settings.EMPTY, "repository.endpoint");
|
||||
assertWarnings("[" + S3Repository.Repository.ENDPOINT_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(S3Repository.Repository.ENDPOINT_SETTING);
|
||||
Settings settings = Settings.builder()
|
||||
.put(S3Repository.Repositories.ENDPOINT_SETTING.getKey(), "repositories.endpoint")
|
||||
.build();
|
||||
assertEndpoint(generateRepositorySettings("repository_key", "repository_secret", null, null), settings,
|
||||
"repositories.endpoint");
|
||||
assertWarnings("[" + S3Repository.Repositories.ENDPOINT_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(S3Repository.Repositories.ENDPOINT_SETTING);
|
||||
}
|
||||
|
||||
private void assertEndpoint(Settings repositorySettings, Settings settings,
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.elasticsearch.repositories.s3;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.amazonaws.services.s3.AbstractAmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import org.elasticsearch.cloud.aws.AwsS3Service;
|
||||
|
@ -35,6 +33,8 @@ import org.elasticsearch.repositories.RepositoryException;
|
|||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.repositories.s3.S3Repository.Repositories;
|
||||
import static org.elasticsearch.repositories.s3.S3Repository.Repository;
|
||||
import static org.elasticsearch.repositories.s3.S3Repository.getValue;
|
||||
|
@ -78,8 +78,7 @@ public class S3RepositoryTests extends ESTestCase {
|
|||
getValue(Settings.EMPTY, globalSettings, Repository.KEY_SETTING, Repositories.KEY_SETTING));
|
||||
assertEquals(new SecureString("".toCharArray()),
|
||||
getValue(Settings.EMPTY, Settings.EMPTY, Repository.KEY_SETTING, Repositories.KEY_SETTING));
|
||||
assertWarnings("[" + Repository.KEY_SETTING.getKey() + "] setting was deprecated",
|
||||
"[" + Repositories.KEY_SETTING.getKey() + "] setting was deprecated");
|
||||
assertSettingDeprecations(Repository.KEY_SETTING, Repositories.KEY_SETTING);
|
||||
}
|
||||
|
||||
public void testInvalidChunkBufferSizeSettings() throws IOException {
|
||||
|
|
|
@ -59,6 +59,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
|
|||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.common.util.MockBigArrays;
|
||||
|
@ -134,10 +135,8 @@ import java.util.stream.Collectors;
|
|||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.elasticsearch.common.util.CollectionUtils.arrayAsArrayList;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
|
||||
/**
|
||||
* Base testcase for randomized unit testing with Elasticsearch
|
||||
|
@ -297,21 +296,33 @@ public abstract class ESTestCase extends LuceneTestCase {
|
|||
//Check that there are no unaccounted warning headers. These should be checked with {@link #assertWarnings(String...)} in the
|
||||
//appropriate test
|
||||
try {
|
||||
final List<String> warnings = threadContext.getResponseHeaders().get(DeprecationLogger.WARNING_HEADER);
|
||||
final List<String> warnings = threadContext.getResponseHeaders().get("Warning");
|
||||
assertNull("unexpected warning headers", warnings);
|
||||
} finally {
|
||||
resetDeprecationLogger();
|
||||
}
|
||||
}
|
||||
|
||||
protected final void assertSettingDeprecations(Setting... settings) {
|
||||
assertWarnings(
|
||||
Arrays
|
||||
.stream(settings)
|
||||
.map(Setting::getKey)
|
||||
.map(k -> "[" + k + "] setting was deprecated in Elasticsearch and will be removed in a future release! " +
|
||||
"See the breaking changes documentation for the next major version.")
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
|
||||
protected final void assertWarnings(String... expectedWarnings) {
|
||||
if (enableWarningsCheck() == false) {
|
||||
throw new IllegalStateException("unable to check warning headers if the test is not set to do so");
|
||||
}
|
||||
try {
|
||||
final List<String> actualWarnings = threadContext.getResponseHeaders().get(DeprecationLogger.WARNING_HEADER);
|
||||
final List<String> actualWarnings = threadContext.getResponseHeaders().get("Warning");
|
||||
final Set<String> actualWarningValues =
|
||||
actualWarnings.stream().map(DeprecationLogger::extractWarningValueFromWarningHeader).collect(Collectors.toSet());
|
||||
for (String msg : expectedWarnings) {
|
||||
assertThat(actualWarnings, hasItem(containsString(msg)));
|
||||
assertTrue(actualWarningValues.contains(DeprecationLogger.escape(msg)));
|
||||
}
|
||||
assertEquals("Expected " + expectedWarnings.length + " warnings but found " + actualWarnings.size() + "\nExpected: "
|
||||
+ Arrays.asList(expectedWarnings) + "\nActual: " + actualWarnings,
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.test.rest.yaml.section;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentLocation;
|
||||
|
@ -39,10 +41,13 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static org.elasticsearch.common.collect.Tuple.tuple;
|
||||
import static org.elasticsearch.common.logging.DeprecationLogger.WARNING_HEADER_PATTERN;
|
||||
import static org.elasticsearch.test.hamcrest.RegexMatcher.matches;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -247,33 +252,48 @@ public class DoSection implements ExecutableSection {
|
|||
/**
|
||||
* Check that the response contains only the warning headers that we expect.
|
||||
*/
|
||||
void checkWarningHeaders(List<String> warningHeaders) {
|
||||
StringBuilder failureMessage = null;
|
||||
void checkWarningHeaders(final List<String> warningHeaders) {
|
||||
final List<String> unexpected = new ArrayList<>();
|
||||
final List<String> unmatched = new ArrayList<>();
|
||||
final List<String> missing = new ArrayList<>();
|
||||
// LinkedHashSet so that missing expected warnings come back in a predictable order which is nice for testing
|
||||
Set<String> expected = new LinkedHashSet<>(expectedWarningHeaders);
|
||||
for (String header : warningHeaders) {
|
||||
if (expected.remove(header)) {
|
||||
// Was expected, all good.
|
||||
continue;
|
||||
final Set<String> expected =
|
||||
new LinkedHashSet<>(expectedWarningHeaders.stream().map(DeprecationLogger::escape).collect(Collectors.toList()));
|
||||
for (final String header : warningHeaders) {
|
||||
final Matcher matcher = WARNING_HEADER_PATTERN.matcher(header);
|
||||
final boolean matches = matcher.matches();
|
||||
if (matches) {
|
||||
final String message = matcher.group(1);
|
||||
if (expected.remove(message) == false) {
|
||||
unexpected.add(header);
|
||||
}
|
||||
if (failureMessage == null) {
|
||||
failureMessage = new StringBuilder("got unexpected warning headers [");
|
||||
}
|
||||
failureMessage.append('\n').append(header);
|
||||
}
|
||||
if (false == expected.isEmpty()) {
|
||||
if (failureMessage == null) {
|
||||
failureMessage = new StringBuilder();
|
||||
} else {
|
||||
failureMessage.append("\n] ");
|
||||
}
|
||||
failureMessage.append("didn't get expected warning headers [");
|
||||
for (String header : expected) {
|
||||
failureMessage.append('\n').append(header);
|
||||
unmatched.add(header);
|
||||
}
|
||||
}
|
||||
if (failureMessage != null) {
|
||||
fail(failureMessage + "\n]");
|
||||
if (expected.isEmpty() == false) {
|
||||
for (final String header : expected) {
|
||||
missing.add(header);
|
||||
}
|
||||
}
|
||||
|
||||
if (unexpected.isEmpty() == false || unmatched.isEmpty() == false || missing.isEmpty() == false) {
|
||||
final StringBuilder failureMessage = new StringBuilder();
|
||||
appendBadHeaders(failureMessage, unexpected, "got unexpected warning header" + (unexpected.size() > 1 ? "s" : ""));
|
||||
appendBadHeaders(failureMessage, unmatched, "got unmatched warning header" + (unmatched.size() > 1 ? "s" : ""));
|
||||
appendBadHeaders(failureMessage, missing, "did not get expected warning header" + (missing.size() > 1 ? "s" : ""));
|
||||
fail(failureMessage.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void appendBadHeaders(final StringBuilder sb, final List<String> headers, final String message) {
|
||||
if (headers.isEmpty() == false) {
|
||||
sb.append(message).append(" [\n");
|
||||
for (final String header : headers) {
|
||||
sb.append("\t").append(header).append("\n");
|
||||
}
|
||||
sb.append("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
package org.elasticsearch.test.rest.yaml.section;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.hash.MessageDigests;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
import org.elasticsearch.common.xcontent.XContent;
|
||||
import org.elasticsearch.common.xcontent.XContentLocation;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -26,6 +29,7 @@ import org.elasticsearch.common.xcontent.yaml.YamlXContent;
|
|||
import org.hamcrest.MatcherAssert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -37,40 +41,81 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class DoSectionTests extends AbstractClientYamlTestFragmentParserTestCase {
|
||||
|
||||
public void testWarningHeaders() throws IOException {
|
||||
DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
{
|
||||
final DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
|
||||
// No warning headers doesn't throw an exception
|
||||
section.checkWarningHeaders(emptyList());
|
||||
}
|
||||
|
||||
final String testHeader = DeprecationLogger.formatWarning("test");
|
||||
final String anotherHeader = DeprecationLogger.formatWarning("another");
|
||||
final String someMoreHeader = DeprecationLogger.formatWarning("some more");
|
||||
final String catHeader = DeprecationLogger.formatWarning("cat");
|
||||
// Any warning headers fail
|
||||
AssertionError e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(singletonList("test")));
|
||||
assertEquals("got unexpected warning headers [\ntest\n]", e.getMessage());
|
||||
e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList("test", "another", "some more")));
|
||||
assertEquals("got unexpected warning headers [\ntest\nanother\nsome more\n]", e.getMessage());
|
||||
{
|
||||
final DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
|
||||
final AssertionError one = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(singletonList(testHeader)));
|
||||
assertEquals("got unexpected warning header [\n\t" + testHeader + "\n]\n", one.getMessage());
|
||||
|
||||
final AssertionError multiple =
|
||||
expectThrows(
|
||||
AssertionError.class,
|
||||
() -> section.checkWarningHeaders(Arrays.asList(testHeader, anotherHeader, someMoreHeader)));
|
||||
assertEquals(
|
||||
"got unexpected warning headers [\n\t" +
|
||||
testHeader + "\n\t" +
|
||||
anotherHeader + "\n\t" +
|
||||
someMoreHeader + "\n]\n",
|
||||
multiple.getMessage());
|
||||
}
|
||||
|
||||
// But not when we expect them
|
||||
{
|
||||
final DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
section.setExpectedWarningHeaders(singletonList("test"));
|
||||
section.checkWarningHeaders(singletonList("test"));
|
||||
section.checkWarningHeaders(singletonList(testHeader));
|
||||
}
|
||||
{
|
||||
final DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
|
||||
section.checkWarningHeaders(Arrays.asList("test", "another", "some more"));
|
||||
section.checkWarningHeaders(Arrays.asList(testHeader, anotherHeader, someMoreHeader));
|
||||
}
|
||||
|
||||
// But if you don't get some that you did expect, that is an error
|
||||
{
|
||||
final DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
section.setExpectedWarningHeaders(singletonList("test"));
|
||||
e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
|
||||
assertEquals("didn't get expected warning headers [\ntest\n]", e.getMessage());
|
||||
final AssertionError e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
|
||||
assertEquals("did not get expected warning header [\n\ttest\n]\n", e.getMessage());
|
||||
}
|
||||
{
|
||||
final DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
|
||||
e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
|
||||
assertEquals("didn't get expected warning headers [\ntest\nanother\nsome more\n]", e.getMessage());
|
||||
e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList("test", "some more")));
|
||||
assertEquals("didn't get expected warning headers [\nanother\n]", e.getMessage());
|
||||
|
||||
final AssertionError multiple = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
|
||||
assertEquals("did not get expected warning headers [\n\ttest\n\tanother\n\tsome more\n]\n", multiple.getMessage());
|
||||
|
||||
final AssertionError one =
|
||||
expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList(testHeader, someMoreHeader)));
|
||||
assertEquals("did not get expected warning header [\n\tanother\n]\n", one.getMessage());
|
||||
}
|
||||
|
||||
// It is also an error if you get some warning you want and some you don't want
|
||||
{
|
||||
final DoSection section = new DoSection(new XContentLocation(1, 1));
|
||||
section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
|
||||
e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList("test", "cat")));
|
||||
assertEquals("got unexpected warning headers [\ncat\n] didn't get expected warning headers [\nanother\nsome more\n]",
|
||||
final AssertionError e =
|
||||
expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList(testHeader, catHeader)));
|
||||
assertEquals("got unexpected warning header [\n\t" +
|
||||
catHeader + "\n]\n" +
|
||||
"did not get expected warning headers [\n\tanother\n\tsome more\n]\n",
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testParseDoSectionNoBody() throws Exception {
|
||||
parser = createParser(YamlXContent.yamlXContent,
|
||||
|
|
Loading…
Reference in New Issue