mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-23 13:26:02 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
efe5a75d26
@ -216,7 +216,6 @@
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]JNANatives.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]JVMCheck.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]JarHell.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]Seccomp.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]bootstrap[/\\]Security.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]ElasticsearchClient.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]FilterClient.java" checks="LineLength" />
|
||||
|
@ -310,7 +310,6 @@ import org.elasticsearch.rest.action.search.RestExplainAction;
|
||||
import org.elasticsearch.rest.action.search.RestMultiSearchAction;
|
||||
import org.elasticsearch.rest.action.search.RestSearchAction;
|
||||
import org.elasticsearch.rest.action.search.RestSearchScrollAction;
|
||||
import org.elasticsearch.rest.action.search.RestSuggestAction;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
@ -550,7 +549,6 @@ public class ActionModule extends AbstractModule {
|
||||
registerRestHandler(handlers, RestMultiGetAction.class);
|
||||
registerRestHandler(handlers, RestDeleteAction.class);
|
||||
registerRestHandler(handlers, org.elasticsearch.rest.action.document.RestCountAction.class);
|
||||
registerRestHandler(handlers, RestSuggestAction.class);
|
||||
registerRestHandler(handlers, RestTermVectorsAction.class);
|
||||
registerRestHandler(handlers, RestMultiTermVectorsAction.class);
|
||||
registerRestHandler(handlers, RestBulkAction.class);
|
||||
|
@ -30,11 +30,13 @@ import org.apache.lucene.util.IOUtils;
|
||||
import org.apache.lucene.util.StringHelper;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cli.ExitCodes;
|
||||
import org.elasticsearch.cli.Terminal;
|
||||
import org.elasticsearch.cli.UserException;
|
||||
import org.elasticsearch.common.PidFile;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
import org.elasticsearch.common.inject.CreationException;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||
import org.elasticsearch.common.logging.LogConfigurator;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
@ -56,7 +58,9 @@ import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
@ -93,7 +97,7 @@ final class Bootstrap {
|
||||
}
|
||||
|
||||
/** initialize native resources */
|
||||
public static void initializeNatives(Path tmpFile, boolean mlockAll, boolean seccomp, boolean ctrlHandler) {
|
||||
public static void initializeNatives(Path tmpFile, boolean mlockAll, boolean systemCallFilter, boolean ctrlHandler) {
|
||||
final Logger logger = Loggers.getLogger(Bootstrap.class);
|
||||
|
||||
// check if the user is running as root, and bail
|
||||
@ -101,9 +105,9 @@ final class Bootstrap {
|
||||
throw new RuntimeException("can not run elasticsearch as root");
|
||||
}
|
||||
|
||||
// enable secure computing mode
|
||||
if (seccomp) {
|
||||
Natives.trySeccomp(tmpFile);
|
||||
// enable system call filter
|
||||
if (systemCallFilter) {
|
||||
Natives.tryInstallSystemCallFilter(tmpFile);
|
||||
}
|
||||
|
||||
// mlockall if requested
|
||||
@ -177,7 +181,7 @@ final class Bootstrap {
|
||||
initializeNatives(
|
||||
environment.tmpFile(),
|
||||
BootstrapSettings.MEMORY_LOCK_SETTING.get(settings),
|
||||
BootstrapSettings.SECCOMP_SETTING.get(settings),
|
||||
BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.get(settings),
|
||||
BootstrapSettings.CTRLHANDLER_SETTING.get(settings));
|
||||
|
||||
// initialize probes before the security manager is installed
|
||||
|
@ -166,7 +166,7 @@ final class BootstrapChecks {
|
||||
}
|
||||
checks.add(new ClientJvmCheck());
|
||||
checks.add(new UseSerialGCCheck());
|
||||
checks.add(new SystemCallFilterCheck(BootstrapSettings.SECCOMP_SETTING.get(settings)));
|
||||
checks.add(new SystemCallFilterCheck(BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.get(settings)));
|
||||
checks.add(new OnErrorCheck());
|
||||
checks.add(new OnOutOfMemoryErrorCheck());
|
||||
checks.add(new G1GCCheck());
|
||||
@ -463,12 +463,12 @@ final class BootstrapChecks {
|
||||
|
||||
@Override
|
||||
public boolean check() {
|
||||
return areSystemCallFiltersEnabled && !isSeccompInstalled();
|
||||
return areSystemCallFiltersEnabled && !isSystemCallFilterInstalled();
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
boolean isSeccompInstalled() {
|
||||
return Natives.isSeccompInstalled();
|
||||
boolean isSystemCallFilterInstalled() {
|
||||
return Natives.isSystemCallFilterInstalled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -483,12 +483,12 @@ final class BootstrapChecks {
|
||||
|
||||
@Override
|
||||
public boolean check() {
|
||||
return isSeccompInstalled() && mightFork();
|
||||
return isSystemCallFilterInstalled() && mightFork();
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
boolean isSeccompInstalled() {
|
||||
return Natives.isSeccompInstalled();
|
||||
boolean isSystemCallFilterInstalled() {
|
||||
return Natives.isSystemCallFilterInstalled();
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
@ -521,7 +521,7 @@ final class BootstrapChecks {
|
||||
"OnError [%s] requires forking but is prevented by system call filters ([%s=true]);" +
|
||||
" upgrade to at least Java 8u92 and use ExitOnOutOfMemoryError",
|
||||
onError(),
|
||||
BootstrapSettings.SECCOMP_SETTING.getKey());
|
||||
BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.getKey());
|
||||
}
|
||||
|
||||
}
|
||||
@ -546,7 +546,7 @@ final class BootstrapChecks {
|
||||
"OnOutOfMemoryError [%s] requires forking but is prevented by system call filters ([%s=true]);" +
|
||||
" upgrade to at least Java 8u92 and use ExitOnOutOfMemoryError",
|
||||
onOutOfMemoryError(),
|
||||
BootstrapSettings.SECCOMP_SETTING.getKey());
|
||||
BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.getKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,16 +24,16 @@ import org.elasticsearch.common.SuppressForbidden;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* Exposes system startup information
|
||||
/**
|
||||
* Exposes system startup information
|
||||
*/
|
||||
@SuppressForbidden(reason = "exposes read-only view of system properties")
|
||||
public final class BootstrapInfo {
|
||||
|
||||
/** no instantiation */
|
||||
private BootstrapInfo() {}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Returns true if we successfully loaded native libraries.
|
||||
* <p>
|
||||
* If this returns false, then native operations such as locking
|
||||
@ -42,19 +42,19 @@ public final class BootstrapInfo {
|
||||
public static boolean isNativesAvailable() {
|
||||
return Natives.JNA_AVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Returns true if we were able to lock the process's address space.
|
||||
*/
|
||||
public static boolean isMemoryLocked() {
|
||||
return Natives.isMemoryLocked();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if secure computing mode is enabled (supported systems only)
|
||||
* Returns true if system call filter is installed (supported systems only)
|
||||
*/
|
||||
public static boolean isSeccompInstalled() {
|
||||
return Natives.isSeccompInstalled();
|
||||
public static boolean isSystemCallFilterInstalled() {
|
||||
return Natives.isSystemCallFilterInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,8 +33,8 @@ public final class BootstrapSettings {
|
||||
|
||||
public static final Setting<Boolean> MEMORY_LOCK_SETTING =
|
||||
Setting.boolSetting("bootstrap.memory_lock", false, Property.NodeScope);
|
||||
public static final Setting<Boolean> SECCOMP_SETTING =
|
||||
Setting.boolSetting("bootstrap.seccomp", true, Property.NodeScope);
|
||||
public static final Setting<Boolean> SYSTEM_CALL_FILTER_SETTING =
|
||||
Setting.boolSetting("bootstrap.system_call_filter", true, Property.NodeScope);
|
||||
public static final Setting<Boolean> CTRLHANDLER_SETTING =
|
||||
Setting.boolSetting("bootstrap.ctrlhandler", true, Property.NodeScope);
|
||||
|
||||
|
@ -43,11 +43,11 @@ class JNANatives {
|
||||
|
||||
// Set to true, in case native mlockall call was successful
|
||||
static boolean LOCAL_MLOCKALL = false;
|
||||
// Set to true, in case native seccomp call was successful
|
||||
static boolean LOCAL_SECCOMP = false;
|
||||
// Set to true, in case native system call filter install was successful
|
||||
static boolean LOCAL_SYSTEM_CALL_FILTER = false;
|
||||
// Set to true, in case policy can be applied to all threads of the process (even existing ones)
|
||||
// otherwise they are only inherited for new threads (ES app threads)
|
||||
static boolean LOCAL_SECCOMP_ALL = false;
|
||||
static boolean LOCAL_SYSTEM_CALL_FILTER_ALL = false;
|
||||
// set to the maximum number of threads that can be created for
|
||||
// the user ID that owns the running Elasticsearch process
|
||||
static long MAX_NUMBER_OF_THREADS = -1;
|
||||
@ -210,12 +210,12 @@ class JNANatives {
|
||||
}
|
||||
}
|
||||
|
||||
static void trySeccomp(Path tmpFile) {
|
||||
static void tryInstallSystemCallFilter(Path tmpFile) {
|
||||
try {
|
||||
int ret = Seccomp.init(tmpFile);
|
||||
LOCAL_SECCOMP = true;
|
||||
int ret = SystemCallFilter.init(tmpFile);
|
||||
LOCAL_SYSTEM_CALL_FILTER = true;
|
||||
if (ret == 1) {
|
||||
LOCAL_SECCOMP_ALL = true;
|
||||
LOCAL_SYSTEM_CALL_FILTER_ALL = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// this is likely to happen unless the kernel is newish, its a best effort at the moment
|
||||
|
@ -91,12 +91,12 @@ final class Natives {
|
||||
return JNANatives.LOCAL_MLOCKALL;
|
||||
}
|
||||
|
||||
static void trySeccomp(Path tmpFile) {
|
||||
static void tryInstallSystemCallFilter(Path tmpFile) {
|
||||
if (!JNA_AVAILABLE) {
|
||||
logger.warn("cannot install syscall filters because JNA is not available");
|
||||
logger.warn("cannot install system call filter because JNA is not available");
|
||||
return;
|
||||
}
|
||||
JNANatives.trySeccomp(tmpFile);
|
||||
JNANatives.tryInstallSystemCallFilter(tmpFile);
|
||||
}
|
||||
|
||||
static void trySetMaxNumberOfThreads() {
|
||||
@ -115,10 +115,10 @@ final class Natives {
|
||||
JNANatives.trySetMaxSizeVirtualMemory();
|
||||
}
|
||||
|
||||
static boolean isSeccompInstalled() {
|
||||
static boolean isSystemCallFilterInstalled() {
|
||||
if (!JNA_AVAILABLE) {
|
||||
return false;
|
||||
}
|
||||
return JNANatives.LOCAL_SECCOMP;
|
||||
return JNANatives.LOCAL_SYSTEM_CALL_FILTER;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Spawns native plugin controller processes if present. Will only work prior to seccomp being set up.
|
||||
* Spawns native plugin controller processes if present. Will only work prior to a system call filter being installed.
|
||||
*/
|
||||
final class Spawner implements Closeable {
|
||||
|
||||
|
@ -43,8 +43,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Installs a limited form of secure computing mode,
|
||||
* to filters system calls to block process execution.
|
||||
* Installs a system call filter to block process execution.
|
||||
* <p>
|
||||
* This is supported on Linux, Solaris, FreeBSD, OpenBSD, Mac OS X, and Windows.
|
||||
* <p>
|
||||
@ -91,8 +90,8 @@ import java.util.Map;
|
||||
* https://docs.oracle.com/cd/E23824_01/html/821-1456/prbac-2.html</a>
|
||||
*/
|
||||
// not an example of how to write code!!!
|
||||
final class Seccomp {
|
||||
private static final Logger logger = Loggers.getLogger(Seccomp.class);
|
||||
final class SystemCallFilter {
|
||||
private static final Logger logger = Loggers.getLogger(SystemCallFilter.class);
|
||||
|
||||
// Linux implementation, based on seccomp(2) or prctl(2) with bpf filtering
|
||||
|
||||
@ -269,7 +268,8 @@ final class Seccomp {
|
||||
|
||||
// we couldn't link methods, could be some really ancient kernel (e.g. < 2.1.57) or some bug
|
||||
if (linux_libc == null) {
|
||||
throw new UnsupportedOperationException("seccomp unavailable: could not link methods. requires kernel 3.5+ with CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in");
|
||||
throw new UnsupportedOperationException("seccomp unavailable: could not link methods. requires kernel 3.5+ " +
|
||||
"with CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in");
|
||||
}
|
||||
|
||||
// pure paranoia:
|
||||
@ -319,7 +319,8 @@ final class Seccomp {
|
||||
switch (errno) {
|
||||
case ENOSYS: break; // ok
|
||||
case EINVAL: break; // ok
|
||||
default: throw new UnsupportedOperationException("seccomp(SECCOMP_SET_MODE_FILTER, BOGUS_FLAG): " + JNACLibrary.strerror(errno));
|
||||
default: throw new UnsupportedOperationException("seccomp(SECCOMP_SET_MODE_FILTER, BOGUS_FLAG): "
|
||||
+ JNACLibrary.strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,7 +347,8 @@ final class Seccomp {
|
||||
int errno = Native.getLastError();
|
||||
if (errno == EINVAL) {
|
||||
// friendly error, this will be the typical case for an old kernel
|
||||
throw new UnsupportedOperationException("seccomp unavailable: requires kernel 3.5+ with CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in");
|
||||
throw new UnsupportedOperationException("seccomp unavailable: requires kernel 3.5+ with" +
|
||||
" CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in");
|
||||
} else {
|
||||
throw new UnsupportedOperationException("prctl(PR_GET_NO_NEW_PRIVS): " + JNACLibrary.strerror(errno));
|
||||
}
|
||||
@ -358,7 +360,8 @@ final class Seccomp {
|
||||
default:
|
||||
int errno = Native.getLastError();
|
||||
if (errno == EINVAL) {
|
||||
throw new UnsupportedOperationException("seccomp unavailable: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed");
|
||||
throw new UnsupportedOperationException("seccomp unavailable: CONFIG_SECCOMP not compiled into kernel," +
|
||||
" CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed");
|
||||
} else {
|
||||
throw new UnsupportedOperationException("prctl(PR_GET_SECCOMP): " + JNACLibrary.strerror(errno));
|
||||
}
|
||||
@ -368,7 +371,8 @@ final class Seccomp {
|
||||
int errno = Native.getLastError();
|
||||
switch (errno) {
|
||||
case EFAULT: break; // available
|
||||
case EINVAL: throw new UnsupportedOperationException("seccomp unavailable: CONFIG_SECCOMP_FILTER not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed");
|
||||
case EINVAL: throw new UnsupportedOperationException("seccomp unavailable: CONFIG_SECCOMP_FILTER not" +
|
||||
" compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed");
|
||||
default: throw new UnsupportedOperationException("prctl(PR_SET_SECCOMP): " + JNACLibrary.strerror(errno));
|
||||
}
|
||||
}
|
||||
@ -380,10 +384,12 @@ final class Seccomp {
|
||||
|
||||
// check it worked
|
||||
if (linux_prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) != 1) {
|
||||
throw new UnsupportedOperationException("seccomp filter did not really succeed: prctl(PR_GET_NO_NEW_PRIVS): " + JNACLibrary.strerror(Native.getLastError()));
|
||||
throw new UnsupportedOperationException("seccomp filter did not really succeed: prctl(PR_GET_NO_NEW_PRIVS): " +
|
||||
JNACLibrary.strerror(Native.getLastError()));
|
||||
}
|
||||
|
||||
// BPF installed to check arch, limit, then syscall. See https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt for details.
|
||||
// BPF installed to check arch, limit, then syscall.
|
||||
// See https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt for details.
|
||||
SockFilter insns[] = {
|
||||
/* 1 */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, SECCOMP_DATA_ARCH_OFFSET), //
|
||||
/* 2 */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch.audit, 0, 7), // if (arch != audit) goto fail;
|
||||
@ -408,7 +414,8 @@ final class Seccomp {
|
||||
method = 0;
|
||||
int errno1 = Native.getLastError();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("seccomp(SECCOMP_SET_MODE_FILTER): {}, falling back to prctl(PR_SET_SECCOMP)...", JNACLibrary.strerror(errno1));
|
||||
logger.debug("seccomp(SECCOMP_SET_MODE_FILTER): {}, falling back to prctl(PR_SET_SECCOMP)...",
|
||||
JNACLibrary.strerror(errno1));
|
||||
}
|
||||
if (linux_prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, pointer, 0, 0) != 0) {
|
||||
int errno2 = Native.getLastError();
|
||||
@ -419,7 +426,8 @@ final class Seccomp {
|
||||
|
||||
// now check that the filter was really installed, we should be in filter mode.
|
||||
if (linux_prctl(PR_GET_SECCOMP, 0, 0, 0, 0) != 2) {
|
||||
throw new UnsupportedOperationException("seccomp filter installation did not really succeed. seccomp(PR_GET_SECCOMP): " + JNACLibrary.strerror(Native.getLastError()));
|
||||
throw new UnsupportedOperationException("seccomp filter installation did not really succeed. seccomp(PR_GET_SECCOMP): "
|
||||
+ JNACLibrary.strerror(Native.getLastError()));
|
||||
}
|
||||
|
||||
logger.debug("Linux seccomp filter installation successful, threads: [{}]", method == 1 ? "all" : "app" );
|
@ -390,7 +390,7 @@ public final class ClusterSettings extends AbstractScopedSettings {
|
||||
PluginsService.MANDATORY_SETTING,
|
||||
BootstrapSettings.SECURITY_FILTER_BAD_DEFAULTS_SETTING,
|
||||
BootstrapSettings.MEMORY_LOCK_SETTING,
|
||||
BootstrapSettings.SECCOMP_SETTING,
|
||||
BootstrapSettings.SYSTEM_CALL_FILTER_SETTING,
|
||||
BootstrapSettings.CTRLHANDLER_SETTING,
|
||||
IndexingMemoryController.INDEX_BUFFER_SIZE_SETTING,
|
||||
IndexingMemoryController.MIN_INDEX_BUFFER_SIZE_SETTING,
|
||||
|
@ -141,7 +141,12 @@ public class XContentFactory {
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided char sequence.
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContentType xContentType(CharSequence content) {
|
||||
int length = content.length() < GUESS_HEADER_LENGTH ? content.length() : GUESS_HEADER_LENGTH;
|
||||
if (length == 0) {
|
||||
@ -174,8 +179,13 @@ public class XContentFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the content (type) based on the provided char sequence.
|
||||
* Guesses the content (type) based on the provided char sequence and returns the corresponding {@link XContent}
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContent xContent(CharSequence content) {
|
||||
XContentType type = xContentType(content);
|
||||
if (type == null) {
|
||||
@ -185,15 +195,24 @@ public class XContentFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided bytes.
|
||||
* Guesses the content type based on the provided bytes and returns the corresponding {@link XContent}
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContent xContent(byte[] data) {
|
||||
return xContent(data, 0, data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided bytes.
|
||||
* Guesses the content type based on the provided bytes and returns the corresponding {@link XContent}
|
||||
*
|
||||
* @deprecated guessing the content type should not be needed ideally. We should rather know the content type upfront or read it
|
||||
* from headers. Till we fixed the REST layer to read the Content-Type header, that should be the only place where guessing is needed.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContent xContent(byte[] data, int offset, int length) {
|
||||
XContentType type = xContentType(data, offset, length);
|
||||
if (type == null) {
|
||||
@ -204,14 +223,24 @@ public class XContentFactory {
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided bytes.
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContentType xContentType(byte[] data) {
|
||||
return xContentType(data, 0, data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided input stream without consuming it.
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContentType xContentType(InputStream si) throws IOException {
|
||||
if (si.markSupported() == false) {
|
||||
throw new IllegalArgumentException("Cannot guess the xcontent type without mark/reset support on " + si.getClass());
|
||||
@ -228,11 +257,24 @@ public class XContentFactory {
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided bytes.
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContentType xContentType(byte[] data, int offset, int length) {
|
||||
return xContentType(new BytesArray(data, offset, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided bytes and returns the corresponding {@link XContent}
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContent xContent(BytesReference bytes) {
|
||||
XContentType type = xContentType(bytes);
|
||||
if (type == null) {
|
||||
@ -243,7 +285,12 @@ public class XContentFactory {
|
||||
|
||||
/**
|
||||
* Guesses the content type based on the provided bytes.
|
||||
*
|
||||
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
|
||||
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
|
||||
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
|
||||
*/
|
||||
@Deprecated
|
||||
public static XContentType xContentType(BytesReference bytes) {
|
||||
int length = bytes.length();
|
||||
if (length == 0) {
|
||||
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.rest.action.search;
|
||||
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.RestBuilderListener;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.search.suggest.Suggest;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.action.RestActions.buildBroadcastShardsHeader;
|
||||
|
||||
public class RestSuggestAction extends BaseRestHandler {
|
||||
|
||||
private final SearchRequestParsers searchRequestParsers;
|
||||
|
||||
@Inject
|
||||
public RestSuggestAction(Settings settings, RestController controller,
|
||||
SearchRequestParsers searchRequestParsers) {
|
||||
super(settings);
|
||||
this.searchRequestParsers = searchRequestParsers;
|
||||
controller.registerAsDeprecatedHandler(POST, "/_suggest", this,
|
||||
"[POST /_suggest] is deprecated! Use [POST /_search] instead.", deprecationLogger);
|
||||
controller.registerAsDeprecatedHandler(GET, "/_suggest", this,
|
||||
"[GET /_suggest] is deprecated! Use [GET /_search] instead.", deprecationLogger);
|
||||
controller.registerAsDeprecatedHandler(POST, "/{index}/_suggest", this,
|
||||
"[POST /{index}/_suggest] is deprecated! Use [POST /{index}/_search] instead.", deprecationLogger);
|
||||
controller.registerAsDeprecatedHandler(GET, "/{index}/_suggest", this,
|
||||
"[GET /{index}/_suggest] is deprecated! Use [GET /{index}/_search] instead.", deprecationLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||
final SearchRequest searchRequest = new SearchRequest(
|
||||
Strings.splitStringByCommaToArray(request.param("index")), new SearchSourceBuilder());
|
||||
searchRequest.indicesOptions(IndicesOptions.fromRequest(request, searchRequest.indicesOptions()));
|
||||
try (XContentParser parser = request.contentOrSourceParamParser()) {
|
||||
final QueryParseContext context = new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher);
|
||||
searchRequest.source().suggest(SuggestBuilder.fromXContent(context, searchRequestParsers.suggesters));
|
||||
}
|
||||
searchRequest.routing(request.param("routing"));
|
||||
searchRequest.preference(request.param("preference"));
|
||||
return channel -> client.search(searchRequest, new RestBuilderListener<SearchResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(SearchResponse response, XContentBuilder builder) throws Exception {
|
||||
RestStatus restStatus = RestStatus.status(response.getSuccessfulShards(),
|
||||
response.getTotalShards(), response.getShardFailures());
|
||||
builder.startObject();
|
||||
buildBroadcastShardsHeader(builder, request, response.getTotalShards(),
|
||||
response.getSuccessfulShards(), response.getFailedShards(), response.getShardFailures());
|
||||
Suggest suggest = response.getSuggest();
|
||||
if (suggest != null) {
|
||||
suggest.toInnerXContent(builder, request);
|
||||
}
|
||||
builder.endObject();
|
||||
return new BytesRestResponse(restStatus, builder);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -150,18 +150,10 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(NAME);
|
||||
toInnerXContent(builder, params);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* use to write suggestion entries without <code>NAME</code> object
|
||||
*/
|
||||
public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
for (Suggestion<?> suggestion : suggestions) {
|
||||
suggestion.toXContent(builder, params);
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
@ -409,11 +409,11 @@ public class BootstrapCheckTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testSystemCallFilterCheck() throws NodeValidationException {
|
||||
final AtomicBoolean isSecompInstalled = new AtomicBoolean();
|
||||
final AtomicBoolean isSystemCallFilterInstalled = new AtomicBoolean();
|
||||
final BootstrapChecks.SystemCallFilterCheck systemCallFilterEnabledCheck = new BootstrapChecks.SystemCallFilterCheck(true) {
|
||||
@Override
|
||||
boolean isSeccompInstalled() {
|
||||
return isSecompInstalled.get();
|
||||
boolean isSystemCallFilterInstalled() {
|
||||
return isSystemCallFilterInstalled.get();
|
||||
}
|
||||
};
|
||||
|
||||
@ -425,28 +425,28 @@ public class BootstrapCheckTests extends ESTestCase {
|
||||
containsString("system call filters failed to install; " +
|
||||
"check the logs and fix your configuration or disable system call filters at your own risk"));
|
||||
|
||||
isSecompInstalled.set(true);
|
||||
isSystemCallFilterInstalled.set(true);
|
||||
BootstrapChecks.check(true, Collections.singletonList(systemCallFilterEnabledCheck), "testSystemCallFilterCheck");
|
||||
|
||||
final BootstrapChecks.SystemCallFilterCheck systemCallFilterNotEnabledCheck = new BootstrapChecks.SystemCallFilterCheck(false) {
|
||||
@Override
|
||||
boolean isSeccompInstalled() {
|
||||
return isSecompInstalled.get();
|
||||
boolean isSystemCallFilterInstalled() {
|
||||
return isSystemCallFilterInstalled.get();
|
||||
}
|
||||
};
|
||||
isSecompInstalled.set(false);
|
||||
isSystemCallFilterInstalled.set(false);
|
||||
BootstrapChecks.check(true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
|
||||
isSecompInstalled.set(true);
|
||||
isSystemCallFilterInstalled.set(true);
|
||||
BootstrapChecks.check(true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
|
||||
}
|
||||
|
||||
public void testMightForkCheck() throws NodeValidationException {
|
||||
final AtomicBoolean isSeccompInstalled = new AtomicBoolean();
|
||||
final AtomicBoolean isSystemCallFilterInstalled = new AtomicBoolean();
|
||||
final AtomicBoolean mightFork = new AtomicBoolean();
|
||||
final BootstrapChecks.MightForkCheck check = new BootstrapChecks.MightForkCheck() {
|
||||
@Override
|
||||
boolean isSeccompInstalled() {
|
||||
return isSeccompInstalled.get();
|
||||
boolean isSystemCallFilterInstalled() {
|
||||
return isSystemCallFilterInstalled.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -462,19 +462,19 @@ public class BootstrapCheckTests extends ESTestCase {
|
||||
|
||||
runMightForkTest(
|
||||
check,
|
||||
isSeccompInstalled,
|
||||
isSystemCallFilterInstalled,
|
||||
() -> mightFork.set(false),
|
||||
() -> mightFork.set(true),
|
||||
e -> assertThat(e.getMessage(), containsString("error")));
|
||||
}
|
||||
|
||||
public void testOnErrorCheck() throws NodeValidationException {
|
||||
final AtomicBoolean isSeccompInstalled = new AtomicBoolean();
|
||||
final AtomicBoolean isSystemCallFilterInstalled = new AtomicBoolean();
|
||||
final AtomicReference<String> onError = new AtomicReference<>();
|
||||
final BootstrapChecks.MightForkCheck check = new BootstrapChecks.OnErrorCheck() {
|
||||
@Override
|
||||
boolean isSeccompInstalled() {
|
||||
return isSeccompInstalled.get();
|
||||
boolean isSystemCallFilterInstalled() {
|
||||
return isSystemCallFilterInstalled.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -486,23 +486,23 @@ public class BootstrapCheckTests extends ESTestCase {
|
||||
final String command = randomAsciiOfLength(16);
|
||||
runMightForkTest(
|
||||
check,
|
||||
isSeccompInstalled,
|
||||
isSystemCallFilterInstalled,
|
||||
() -> onError.set(randomBoolean() ? "" : null),
|
||||
() -> onError.set(command),
|
||||
e -> assertThat(
|
||||
e.getMessage(),
|
||||
containsString(
|
||||
"OnError [" + command + "] requires forking but is prevented by system call filters ([bootstrap.seccomp=true]);"
|
||||
+ " upgrade to at least Java 8u92 and use ExitOnOutOfMemoryError")));
|
||||
"OnError [" + command + "] requires forking but is prevented by system call filters " +
|
||||
"([bootstrap.system_call_filter=true]); upgrade to at least Java 8u92 and use ExitOnOutOfMemoryError")));
|
||||
}
|
||||
|
||||
public void testOnOutOfMemoryErrorCheck() throws NodeValidationException {
|
||||
final AtomicBoolean isSeccompInstalled = new AtomicBoolean();
|
||||
final AtomicBoolean isSystemCallFilterInstalled = new AtomicBoolean();
|
||||
final AtomicReference<String> onOutOfMemoryError = new AtomicReference<>();
|
||||
final BootstrapChecks.MightForkCheck check = new BootstrapChecks.OnOutOfMemoryErrorCheck() {
|
||||
@Override
|
||||
boolean isSeccompInstalled() {
|
||||
return isSeccompInstalled.get();
|
||||
boolean isSystemCallFilterInstalled() {
|
||||
return isSystemCallFilterInstalled.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -514,28 +514,28 @@ public class BootstrapCheckTests extends ESTestCase {
|
||||
final String command = randomAsciiOfLength(16);
|
||||
runMightForkTest(
|
||||
check,
|
||||
isSeccompInstalled,
|
||||
isSystemCallFilterInstalled,
|
||||
() -> onOutOfMemoryError.set(randomBoolean() ? "" : null),
|
||||
() -> onOutOfMemoryError.set(command),
|
||||
e -> assertThat(
|
||||
e.getMessage(),
|
||||
containsString(
|
||||
"OnOutOfMemoryError [" + command + "]"
|
||||
+ " requires forking but is prevented by system call filters ([bootstrap.seccomp=true]);"
|
||||
+ " requires forking but is prevented by system call filters ([bootstrap.system_call_filter=true]);"
|
||||
+ " upgrade to at least Java 8u92 and use ExitOnOutOfMemoryError")));
|
||||
}
|
||||
|
||||
private void runMightForkTest(
|
||||
final BootstrapChecks.MightForkCheck check,
|
||||
final AtomicBoolean isSeccompInstalled,
|
||||
final AtomicBoolean isSystemCallFilterInstalled,
|
||||
final Runnable disableMightFork,
|
||||
final Runnable enableMightFork,
|
||||
final Consumer<NodeValidationException> consumer) throws NodeValidationException {
|
||||
|
||||
final String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
|
||||
|
||||
// if seccomp is disabled, nothing should happen
|
||||
isSeccompInstalled.set(false);
|
||||
// if system call filter is disabled, nothing should happen
|
||||
isSystemCallFilterInstalled.set(false);
|
||||
if (randomBoolean()) {
|
||||
disableMightFork.run();
|
||||
} else {
|
||||
@ -543,16 +543,15 @@ public class BootstrapCheckTests extends ESTestCase {
|
||||
}
|
||||
BootstrapChecks.check(true, Collections.singletonList(check), methodName);
|
||||
|
||||
// if seccomp is enabled, but we will not fork, nothing should
|
||||
// if system call filter is enabled, but we will not fork, nothing should
|
||||
// happen
|
||||
isSeccompInstalled.set(true);
|
||||
isSystemCallFilterInstalled.set(true);
|
||||
disableMightFork.run();
|
||||
BootstrapChecks.check(true, Collections.singletonList(check), methodName);
|
||||
|
||||
// if seccomp is enabled, and we might fork, the check should
|
||||
// be enforced, regardless of bootstrap checks being enabled or
|
||||
// not
|
||||
isSeccompInstalled.set(true);
|
||||
// if system call filter is enabled, and we might fork, the check should be enforced, regardless of bootstrap checks being enabled
|
||||
// or not
|
||||
isSystemCallFilterInstalled.set(true);
|
||||
enableMightFork.run();
|
||||
|
||||
final NodeValidationException e = expectThrows(
|
||||
|
@ -27,7 +27,7 @@ public class BootstrapSettingsTests extends ESTestCase {
|
||||
public void testDefaultSettings() {
|
||||
assertTrue(BootstrapSettings.SECURITY_FILTER_BAD_DEFAULTS_SETTING.get(Settings.EMPTY));
|
||||
assertFalse(BootstrapSettings.MEMORY_LOCK_SETTING.get(Settings.EMPTY));
|
||||
assertTrue(BootstrapSettings.SECCOMP_SETTING.get(Settings.EMPTY));
|
||||
assertTrue(BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.get(Settings.EMPTY));
|
||||
assertTrue(BootstrapSettings.CTRLHANDLER_SETTING.get(Settings.EMPTY));
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ import org.elasticsearch.test.ESTestCase;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Doesn't actually test spawning a process, as seccomp is installed before tests run and forbids it.
|
||||
* Doesn't actually test spawning a process, as a system call filter is installed before tests run and forbids it.
|
||||
*/
|
||||
public class SpawnerTests extends ESTestCase {
|
||||
|
||||
@ -48,4 +48,5 @@ public class SpawnerTests extends ESTestCase {
|
||||
assertEquals("windows-x86_64", Spawner.makePlatformName("Windows 8.1", "amd64"));
|
||||
assertEquals("sunos-x86_64", Spawner.makePlatformName("SunOS", "amd64"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1473,6 +1473,7 @@ Converts a JSON string into a structured JSON object.
|
||||
| Name | Required | Default | Description
|
||||
| `field` | yes | - | The field to be parsed
|
||||
| `target_field` | no | `field` | The field to insert the converted structured object into
|
||||
| `add_to_root` | no | false | Flag that forces the serialized json to be injected into the top level of the document. `target_field` must not be set when this option is chosen.
|
||||
|======
|
||||
|
||||
[source,js]
|
||||
|
@ -156,7 +156,7 @@ The system call filter check ensures that if system call filters are enabled,
|
||||
then they were successfully installed. To pass the system call filter check you
|
||||
must either fix any configuration errors on your system that prevented system
|
||||
call filters from installing (check your logs), or *at your own risk* disable
|
||||
system call filters by setting `bootstrap.seccomp` to `false`.
|
||||
system call filters by setting `bootstrap.system_call_filter` to `false`.
|
||||
|
||||
=== OnError and OnOutOfMemoryError checks
|
||||
|
||||
|
@ -28,6 +28,8 @@ import org.elasticsearch.ingest.Processor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.ingest.ConfigurationUtils.newConfigurationException;
|
||||
|
||||
/**
|
||||
* Processor that serializes a string-valued field into a
|
||||
* map of maps.
|
||||
@ -38,11 +40,13 @@ public final class JsonProcessor extends AbstractProcessor {
|
||||
|
||||
private final String field;
|
||||
private final String targetField;
|
||||
private final boolean addToRoot;
|
||||
|
||||
JsonProcessor(String tag, String field, String targetField) {
|
||||
JsonProcessor(String tag, String field, String targetField, boolean addToRoot) {
|
||||
super(tag);
|
||||
this.field = field;
|
||||
this.targetField = targetField;
|
||||
this.addToRoot = addToRoot;
|
||||
}
|
||||
|
||||
public String getField() {
|
||||
@ -53,12 +57,22 @@ public final class JsonProcessor extends AbstractProcessor {
|
||||
return targetField;
|
||||
}
|
||||
|
||||
boolean isAddToRoot() {
|
||||
return addToRoot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(IngestDocument document) throws Exception {
|
||||
String stringValue = document.getFieldValue(field, String.class);
|
||||
try {
|
||||
Map<String, Object> mapValue = JsonXContent.jsonXContent.createParser(stringValue).map();
|
||||
document.setFieldValue(targetField, mapValue);
|
||||
if (addToRoot) {
|
||||
for (Map.Entry<String, Object> entry : mapValue.entrySet()) {
|
||||
document.setFieldValue(entry.getKey(), entry.getValue());
|
||||
}
|
||||
} else {
|
||||
document.setFieldValue(targetField, mapValue);
|
||||
}
|
||||
} catch (JsonParseException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
@ -74,8 +88,19 @@ public final class JsonProcessor extends AbstractProcessor {
|
||||
public JsonProcessor create(Map<String, Processor.Factory> registry, String processorTag,
|
||||
Map<String, Object> config) throws Exception {
|
||||
String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field");
|
||||
String targetField = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "target_field", field);
|
||||
return new JsonProcessor(processorTag, field, targetField);
|
||||
String targetField = ConfigurationUtils.readOptionalStringProperty(TYPE, processorTag, config, "target_field");
|
||||
boolean addToRoot = ConfigurationUtils.readBooleanProperty(TYPE, processorTag, config, "add_to_root", false);
|
||||
|
||||
if (addToRoot && targetField != null) {
|
||||
throw newConfigurationException(TYPE, processorTag, "target_field",
|
||||
"Cannot set a target field while also setting `add_to_root` to true");
|
||||
}
|
||||
|
||||
if (targetField == null) {
|
||||
targetField = field;
|
||||
}
|
||||
|
||||
return new JsonProcessor(processorTag, field, targetField, addToRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,19 @@ public class JsonProcessorFactoryTests extends ESTestCase {
|
||||
assertThat(jsonProcessor.getTargetField(), equalTo(randomTargetField));
|
||||
}
|
||||
|
||||
public void testCreateWithAddToRoot() throws Exception {
|
||||
String processorTag = randomAsciiOfLength(10);
|
||||
String randomField = randomAsciiOfLength(10);
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("field", randomField);
|
||||
config.put("add_to_root", true);
|
||||
JsonProcessor jsonProcessor = FACTORY.create(null, processorTag, config);
|
||||
assertThat(jsonProcessor.getTag(), equalTo(processorTag));
|
||||
assertThat(jsonProcessor.getField(), equalTo(randomField));
|
||||
assertThat(jsonProcessor.getTargetField(), equalTo(randomField));
|
||||
assertTrue(jsonProcessor.isAddToRoot());
|
||||
}
|
||||
|
||||
public void testCreateWithDefaultTarget() throws Exception {
|
||||
String processorTag = randomAsciiOfLength(10);
|
||||
String randomField = randomAsciiOfLength(10);
|
||||
@ -66,4 +79,16 @@ public class JsonProcessorFactoryTests extends ESTestCase {
|
||||
() -> FACTORY.create(null, processorTag, config));
|
||||
assertThat(exception.getMessage(), equalTo("[field] required property is missing"));
|
||||
}
|
||||
|
||||
public void testCreateWithBothTargetFieldAndAddToRoot() throws Exception {
|
||||
String randomField = randomAsciiOfLength(10);
|
||||
String randomTargetField = randomAsciiOfLength(5);
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("field", randomField);
|
||||
config.put("target_field", randomTargetField);
|
||||
config.put("add_to_root", true);
|
||||
ElasticsearchException exception = expectThrows(ElasticsearchParseException.class,
|
||||
() -> FACTORY.create(null, randomAsciiOfLength(10), config));
|
||||
assertThat(exception.getMessage(), equalTo("[target_field] Cannot set a target field while also setting `add_to_root` to true"));
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class JsonProcessorTests extends ESTestCase {
|
||||
String processorTag = randomAsciiOfLength(3);
|
||||
String randomField = randomAsciiOfLength(3);
|
||||
String randomTargetField = randomAsciiOfLength(2);
|
||||
JsonProcessor jsonProcessor = new JsonProcessor(processorTag, randomField, randomTargetField);
|
||||
JsonProcessor jsonProcessor = new JsonProcessor(processorTag, randomField, randomTargetField, false);
|
||||
Map<String, Object> document = new HashMap<>();
|
||||
|
||||
Map<String, Object> randomJsonMap = RandomDocumentPicks.randomSource(random());
|
||||
@ -54,7 +54,7 @@ public class JsonProcessorTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testInvalidJson() {
|
||||
JsonProcessor jsonProcessor = new JsonProcessor("tag", "field", "target_field");
|
||||
JsonProcessor jsonProcessor = new JsonProcessor("tag", "field", "target_field", false);
|
||||
Map<String, Object> document = new HashMap<>();
|
||||
document.put("field", "invalid json");
|
||||
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), document);
|
||||
@ -66,11 +66,34 @@ public class JsonProcessorTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testFieldMissing() {
|
||||
JsonProcessor jsonProcessor = new JsonProcessor("tag", "field", "target_field");
|
||||
JsonProcessor jsonProcessor = new JsonProcessor("tag", "field", "target_field", false);
|
||||
Map<String, Object> document = new HashMap<>();
|
||||
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), document);
|
||||
|
||||
Exception exception = expectThrows(IllegalArgumentException.class, () -> jsonProcessor.execute(ingestDocument));
|
||||
assertThat(exception.getMessage(), equalTo("field [field] not present as part of path [field]"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testAddToRoot() throws Exception {
|
||||
String processorTag = randomAsciiOfLength(3);
|
||||
String randomTargetField = randomAsciiOfLength(2);
|
||||
JsonProcessor jsonProcessor = new JsonProcessor(processorTag, "a", randomTargetField, true);
|
||||
Map<String, Object> document = new HashMap<>();
|
||||
|
||||
String json = "{\"a\": 1, \"b\": 2}";
|
||||
document.put("a", json);
|
||||
document.put("c", "see");
|
||||
|
||||
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), document);
|
||||
jsonProcessor.execute(ingestDocument);
|
||||
|
||||
Map<String, Object> expected = new HashMap<>();
|
||||
expected.put("a", 1);
|
||||
expected.put("b", 2);
|
||||
expected.put("c", "see");
|
||||
IngestDocument expectedIngestDocument = RandomDocumentPicks.randomIngestDocument(random(), expected);
|
||||
|
||||
assertIngestDocument(ingestDocument, expectedIngestDocument);
|
||||
}
|
||||
}
|
||||
|
@ -22,30 +22,30 @@ package org.elasticsearch.bootstrap;
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
/** Simple tests seccomp filter is working. */
|
||||
public class SeccompTests extends ESTestCase {
|
||||
|
||||
/** Simple tests system call filter is working. */
|
||||
public class SystemCallFilterTests extends ESTestCase {
|
||||
|
||||
/** command to try to run in tests */
|
||||
static final String EXECUTABLE = Constants.WINDOWS ? "calc" : "ls";
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
assumeTrue("requires seccomp filter installation", Natives.isSeccompInstalled());
|
||||
assumeTrue("requires system call filter installation", Natives.isSystemCallFilterInstalled());
|
||||
// otherwise security manager will block the execution, no fun
|
||||
assumeTrue("cannot test with security manager enabled", System.getSecurityManager() == null);
|
||||
// otherwise, since we don't have TSYNC support, rules are not applied to the test thread
|
||||
// (randomizedrunner class initialization happens in its own thread, after the test thread is created)
|
||||
// instead we just forcefully run it for the test thread here.
|
||||
if (!JNANatives.LOCAL_SECCOMP_ALL) {
|
||||
if (!JNANatives.LOCAL_SYSTEM_CALL_FILTER_ALL) {
|
||||
try {
|
||||
Seccomp.init(createTempDir());
|
||||
SystemCallFilter.init(createTempDir());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("unable to forcefully apply seccomp to test thread", e);
|
||||
throw new RuntimeException("unable to forcefully apply system call filter to test thread", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testNoExecution() throws Exception {
|
||||
try {
|
||||
Runtime.getRuntime().exec(EXECUTABLE);
|
||||
@ -63,11 +63,11 @@ public class SeccompTests extends ESTestCase {
|
||||
at java.lang.UNIXProcess.<init>(UNIXProcess.java:248)
|
||||
at java.lang.ProcessImpl.start(ProcessImpl.java:134)
|
||||
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
|
||||
...
|
||||
...
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// make sure thread inherits this too (its documented that way)
|
||||
public void testNoExecutionFromThread() throws Exception {
|
||||
Thread t = new Thread() {
|
@ -39,9 +39,8 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* Create a simple "daemon controller", put it in the right place and check that it runs.
|
||||
*
|
||||
* Extends LuceneTestCase rather than ESTestCase as ESTestCase installs seccomp, and that
|
||||
* prevents the Spawner class doing its job. Also needs to run in a separate JVM to other
|
||||
* tests that extend ESTestCase for the same reason.
|
||||
* Extends LuceneTestCase rather than ESTestCase as ESTestCase installs a system call filter, and that prevents the Spawner class doing its
|
||||
* job. Also needs to run in a separate JVM to other tests that extend ESTestCase for the same reason.
|
||||
*/
|
||||
public class SpawnerNoBootstrapTests extends LuceneTestCase {
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
{
|
||||
"suggest": {
|
||||
"documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-suggesters.html",
|
||||
"methods": ["POST"],
|
||||
"url": {
|
||||
"path": "/_suggest",
|
||||
"paths": ["/_suggest", "/{index}/_suggest"],
|
||||
"parts": {
|
||||
"index": {
|
||||
"type" : "list",
|
||||
"description" : "A comma-separated list of index names to restrict the operation; use `_all` or empty string to perform the operation on all indices"
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"ignore_unavailable": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether specified concrete indices should be ignored when unavailable (missing or closed)"
|
||||
},
|
||||
"allow_no_indices": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)"
|
||||
},
|
||||
"expand_wildcards": {
|
||||
"type" : "enum",
|
||||
"options" : ["open","closed","none","all"],
|
||||
"default" : "open",
|
||||
"description" : "Whether to expand wildcard expression to concrete indices that are open, closed or both."
|
||||
},
|
||||
"preference": {
|
||||
"type" : "string",
|
||||
"description" : "Specify the node or shard the operation should be performed on (default: random)"
|
||||
},
|
||||
"routing": {
|
||||
"type" : "string",
|
||||
"description" : "Specific routing value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"description" : "The request definition",
|
||||
"required" : true
|
||||
}
|
||||
}
|
||||
}
|
@ -24,19 +24,3 @@ setup:
|
||||
- match: {suggest.test_suggestion.1.options.0.text: amsterdam}
|
||||
- match: {suggest.test_suggestion.2.options.0.text: meetup}
|
||||
|
||||
---
|
||||
"Suggest API should have deprecation warning":
|
||||
- skip:
|
||||
features: 'warnings'
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
test_suggestion:
|
||||
text: "The Amsterdma meetpu"
|
||||
term:
|
||||
field: body
|
||||
|
||||
- match: {test_suggestion.1.options.0.text: amsterdam}
|
||||
- match: {test_suggestion.2.options.0.text: meetup}
|
||||
|
@ -1,314 +0,0 @@
|
||||
# This test creates one huge mapping in the setup
|
||||
# Every test should use its own field to make sure it works
|
||||
|
||||
setup:
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: test
|
||||
body:
|
||||
mappings:
|
||||
test:
|
||||
"properties":
|
||||
"suggest_1":
|
||||
"type" : "completion"
|
||||
"suggest_2":
|
||||
"type" : "completion"
|
||||
"suggest_3":
|
||||
"type" : "completion"
|
||||
"suggest_4":
|
||||
"type" : "completion"
|
||||
"suggest_5a":
|
||||
"type" : "completion"
|
||||
"suggest_5b":
|
||||
"type" : "completion"
|
||||
"suggest_6":
|
||||
"type" : "completion"
|
||||
title:
|
||||
type: keyword
|
||||
|
||||
---
|
||||
"Simple suggestion should work":
|
||||
- skip:
|
||||
features: 'warnings'
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_1: "bar"
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_1: "baz"
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "b"
|
||||
completion:
|
||||
field: suggest_1
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 2 }
|
||||
|
||||
---
|
||||
"Simple suggestion array should work":
|
||||
- skip:
|
||||
features: 'warnings'
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_2: ["bar", "foo"]
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "f"
|
||||
completion:
|
||||
field: suggest_2
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "foo" }
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "b"
|
||||
completion:
|
||||
field: suggest_2
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "bar" }
|
||||
|
||||
---
|
||||
"Suggestion entry should work":
|
||||
- skip:
|
||||
features: 'warnings'
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_3:
|
||||
input: "bar"
|
||||
weight: 2
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_3:
|
||||
input: "baz"
|
||||
weight: 3
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "b"
|
||||
completion:
|
||||
field: suggest_3
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 2 }
|
||||
- match: { result.0.options.0.text: "baz" }
|
||||
- match: { result.0.options.1.text: "bar" }
|
||||
|
||||
---
|
||||
"Suggestion entry array should work":
|
||||
- skip:
|
||||
features: 'warnings'
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_4:
|
||||
- input: "bar"
|
||||
weight: 3
|
||||
- input: "fo"
|
||||
weight: 3
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_4:
|
||||
- input: "baz"
|
||||
weight: 2
|
||||
- input: "foo"
|
||||
weight: 1
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "b"
|
||||
completion:
|
||||
field: suggest_4
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 2 }
|
||||
- match: { result.0.options.0.text: "bar" }
|
||||
- match: { result.0.options.1.text: "baz" }
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "f"
|
||||
completion:
|
||||
field: suggest_4
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 2 }
|
||||
- match: { result.0.options.0.text: "fo" }
|
||||
- match: { result.0.options.1.text: "foo" }
|
||||
|
||||
---
|
||||
"Multiple Completion fields should work":
|
||||
- skip:
|
||||
features: 'warnings'
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_5a: "bar"
|
||||
suggest_5b: "baz"
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "b"
|
||||
completion:
|
||||
field: suggest_5a
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "bar" }
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "b"
|
||||
completion:
|
||||
field: suggest_5b
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "baz" }
|
||||
|
||||
---
|
||||
"Suggestions with source should work":
|
||||
- skip:
|
||||
features: 'warnings'
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_6:
|
||||
input: "bar"
|
||||
weight: 2
|
||||
title: "title_bar"
|
||||
count: 4
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_6:
|
||||
input: "baz"
|
||||
weight: 3
|
||||
title: "title_baz"
|
||||
count: 3
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
warnings:
|
||||
- "[POST /_suggest] is deprecated! Use [POST /_search] instead."
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "b"
|
||||
completion:
|
||||
field: suggest_6
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 2 }
|
||||
- match: { result.0.options.0.text: "baz" }
|
||||
- match: { result.0.options.0._index: "test" }
|
||||
- match: { result.0.options.0._type: "test" }
|
||||
- match: { result.0.options.0._source.title: "title_baz" }
|
||||
- match: { result.0.options.0._source.count: 3 }
|
||||
- match: { result.0.options.1.text: "bar" }
|
||||
- match: { result.0.options.1._index: "test" }
|
||||
- match: { result.0.options.1._type: "test" }
|
||||
- match: { result.0.options.1._source.title: "title_bar" }
|
||||
- match: { result.0.options.1._source.count: 4 }
|
Loading…
x
Reference in New Issue
Block a user