mirror of
https://github.com/wazuh/wazuh-indexer-plugins.git
synced 2025-12-10 00:28:51 -06:00
Implement spotless gradle pre-commit hook (#105)
* Add precommit hook definition to perform basic formatting using spotless on indexer plugins * Add formatter configuration file for spotless tool * Update command-manager's build.gradle to use the spotless tool * Update spotless implementation on setup plugin - Order build.gradle blocks - Add spotless plugin to build.gradle - Update formatting.gradle for both plugins * Add formatter config for spotless on setup plugin * Add license header validation on java files - Add license-header.txt file with the expected content of the headers - Update formatting.gradle on both plugins to validate the license header - Rename buildSrc directory to formatter * Update formatter settings * Implement custom import order based on wazuh-indexer defined convention * Apply format-related changes requested by spotless formatter * Initialize a gradle base project to handle generic processes for the subprojects - Move spotless-related configuration to main project directory - Add pre-commit hook script to run spotlessCheck - Add block on build.gradle to automatically apply pre-commit script into local .git dir - Remove duplicated spotless-related code * Apply spotless formatting to command-manager classes
This commit is contained in:
parent
0ecde298a1
commit
c38c054d7b
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
||||
|
||||
# Ignore Idea IDE directory
|
||||
.idea/
|
||||
4
NOTICE.txt
Normal file
4
NOTICE.txt
Normal file
@ -0,0 +1,4 @@
|
||||
OpenSearch (https://opensearch.org/)
|
||||
Copyright OpenSearch Contributors
|
||||
Wazuh (https://wazuh.com/)
|
||||
Copyright Wazuh Contributors
|
||||
25
build.gradle
Normal file
25
build.gradle
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
* this file be licensed under the Apache-2.0 license or a
|
||||
* compatible open source license.
|
||||
*/
|
||||
plugins { id "com.diffplug.spotless" version "6.25.0" }
|
||||
repositories { mavenCentral() }
|
||||
|
||||
apply plugin: 'java'
|
||||
apply from: 'gradle/formatting.gradle'
|
||||
|
||||
task installLocalGitHook(type: Copy){
|
||||
from new File(rootProject.rootDir, 'scripts/pre-commit')
|
||||
into { new File(rootProject.rootDir, '.git/hooks')}
|
||||
fileMode 0775
|
||||
}
|
||||
|
||||
// Install git pre-commit hook on the project.
|
||||
build.dependsOn installLocalGitHook
|
||||
|
||||
// Add the spotlessCheck to gradle check
|
||||
check.dependsOn spotlessCheck
|
||||
8
formatter/license-header.txt
Normal file
8
formatter/license-header.txt
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
* this file be licensed under the Apache-2.0 license or a
|
||||
* compatible open source license.
|
||||
*/
|
||||
39
gradle/formatting.gradle
Normal file
39
gradle/formatting.gradle
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
* this file be licensed under the Apache-2.0 license or a
|
||||
* compatible open source license.
|
||||
*/
|
||||
|
||||
allprojects {
|
||||
project.apply plugin: "com.diffplug.spotless"
|
||||
spotless {
|
||||
java {
|
||||
licenseHeaderFile("${rootProject.file("formatter/license-header.txt")}")
|
||||
googleJavaFormat().aosp()
|
||||
removeUnusedImports()
|
||||
importOrder(
|
||||
'de.thetaphi',
|
||||
'com.carrotsearch',
|
||||
'com.fasterxml',
|
||||
'com.avast',
|
||||
'com.sun',
|
||||
'com.maxmind|com.github|com.networknt|groovy|nebula',
|
||||
'org.antlr',
|
||||
'software.amazon',
|
||||
'com.azure|com.microsoft|com.ibm|com.google|joptsimple|org.apache|org.bouncycastle|org.codehaus|org.opensearch|org.objectweb|org.joda|org.hamcrest|org.openjdk|org.gradle|org.junit',
|
||||
'javax',
|
||||
'java',
|
||||
'',
|
||||
'\\#java|\\#org.opensearch|\\#org.hamcrest|\\#'
|
||||
)
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
|
||||
// add support for spotless:off and spotless:on tags to exclude sections of code
|
||||
toggleOffOn()
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
252
gradlew
vendored
Executable file
252
gradlew
vendored
Executable file
@ -0,0 +1,252 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed 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
|
||||
#
|
||||
# https://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.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
94
gradlew.bat
vendored
Normal file
94
gradlew.bat
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@ -1,5 +1,24 @@
|
||||
import org.opensearch.gradle.test.RestIntegTestTask
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
opensearch_version = System.getProperty("opensearch.version", "2.16.0")
|
||||
wazuh_version = System.getProperty("version", "5.0.0")
|
||||
revision = System.getProperty("revision", "0")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
|
||||
mavenCentral()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.opensearch.gradle:build-tools:${opensearch_version}"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'eclipse'
|
||||
@ -80,25 +99,6 @@ thirdPartyAudit.enabled = false
|
||||
//Skip checking for third party licenses
|
||||
dependencyLicenses.enabled = false
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
opensearch_version = System.getProperty("opensearch.version", "2.16.0")
|
||||
wazuh_version = System.getProperty("version", "5.0.0")
|
||||
revision = System.getProperty("revision", "0")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
|
||||
mavenCentral()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.opensearch.gradle:build-tools:${opensearch_version}"
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,10 +8,6 @@
|
||||
*/
|
||||
package com.wazuh.commandmanager;
|
||||
|
||||
import com.wazuh.commandmanager.index.CommandIndex;
|
||||
import com.wazuh.commandmanager.rest.RestPostCommandAction;
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClient;
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClientDemo;
|
||||
import org.opensearch.client.Client;
|
||||
import org.opensearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.opensearch.cluster.node.DiscoveryNodes;
|
||||
@ -38,11 +35,15 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.wazuh.commandmanager.index.CommandIndex;
|
||||
import com.wazuh.commandmanager.rest.RestPostCommandAction;
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClient;
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClientDemo;
|
||||
|
||||
/**
|
||||
* The Command Manager plugin exposes an HTTP API with a single endpoint to
|
||||
* receive raw commands from the Wazuh Server. These commands are processed,
|
||||
* indexed and sent back to the Server for its delivery to, in most cases, the
|
||||
* Agents.
|
||||
* The Command Manager plugin exposes an HTTP API with a single endpoint to receive raw commands
|
||||
* from the Wazuh Server. These commands are processed, indexed and sent back to the Server for its
|
||||
* delivery to, in most cases, the Agents.
|
||||
*/
|
||||
public class CommandManagerPlugin extends Plugin implements ActionPlugin {
|
||||
public static final String COMMAND_MANAGER_BASE_URI = "/_plugins/_command_manager";
|
||||
@ -64,8 +65,7 @@ public class CommandManagerPlugin extends Plugin implements ActionPlugin {
|
||||
NodeEnvironment nodeEnvironment,
|
||||
NamedWriteableRegistry namedWriteableRegistry,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
Supplier<RepositoriesService> repositoriesServiceSupplier
|
||||
) {
|
||||
Supplier<RepositoriesService> repositoriesServiceSupplier) {
|
||||
this.commandIndex = new CommandIndex(client, clusterService, threadPool);
|
||||
|
||||
// HttpRestClient stuff
|
||||
@ -82,8 +82,7 @@ public class CommandManagerPlugin extends Plugin implements ActionPlugin {
|
||||
IndexScopedSettings indexScopedSettings,
|
||||
SettingsFilter settingsFilter,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
Supplier<DiscoveryNodes> nodesInCluster
|
||||
) {
|
||||
Supplier<DiscoveryNodes> nodesInCluster) {
|
||||
return Collections.singletonList(new RestPostCommandAction(this.commandIndex));
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,9 +8,6 @@
|
||||
*/
|
||||
package com.wazuh.commandmanager.index;
|
||||
|
||||
import com.wazuh.commandmanager.CommandManagerPlugin;
|
||||
import com.wazuh.commandmanager.model.Document;
|
||||
import com.wazuh.commandmanager.utils.IndexTemplateUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.opensearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
@ -31,9 +29,11 @@ import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* Class to manage the Command Manager index and index template.
|
||||
*/
|
||||
import com.wazuh.commandmanager.CommandManagerPlugin;
|
||||
import com.wazuh.commandmanager.model.Document;
|
||||
import com.wazuh.commandmanager.utils.IndexTemplateUtils;
|
||||
|
||||
/** Class to manage the Command Manager index and index template. */
|
||||
public class CommandIndex implements IndexingOperationListener {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(CommandIndex.class);
|
||||
@ -45,9 +45,9 @@ public class CommandIndex implements IndexingOperationListener {
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param client OpenSearch client.
|
||||
* @param client OpenSearch client.
|
||||
* @param clusterService OpenSearch cluster service.
|
||||
* @param threadPool An OpenSearch ThreadPool.
|
||||
* @param threadPool An OpenSearch ThreadPool.
|
||||
*/
|
||||
public CommandIndex(Client client, ClusterService clusterService, ThreadPool threadPool) {
|
||||
this.client = client;
|
||||
@ -69,30 +69,31 @@ public class CommandIndex implements IndexingOperationListener {
|
||||
} else {
|
||||
log.info(
|
||||
"Index template {} already exists. Skipping creation.",
|
||||
CommandManagerPlugin.COMMAND_MANAGER_INDEX_TEMPLATE_NAME
|
||||
);
|
||||
CommandManagerPlugin.COMMAND_MANAGER_INDEX_TEMPLATE_NAME);
|
||||
}
|
||||
|
||||
log.info("Indexing command with id [{}]", document.getId());
|
||||
try {
|
||||
IndexRequest request = new IndexRequest()
|
||||
.index(CommandManagerPlugin.COMMAND_MANAGER_INDEX_NAME)
|
||||
.source(document.toXContent(XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS))
|
||||
.id(document.getId())
|
||||
.create(true);
|
||||
IndexRequest request =
|
||||
new IndexRequest()
|
||||
.index(CommandManagerPlugin.COMMAND_MANAGER_INDEX_NAME)
|
||||
.source(
|
||||
document.toXContent(
|
||||
XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS))
|
||||
.id(document.getId())
|
||||
.create(true);
|
||||
executor.submit(
|
||||
() -> {
|
||||
try (ThreadContext.StoredContext ignored = this.threadPool.getThreadContext().stashContext()) {
|
||||
try (ThreadContext.StoredContext ignored =
|
||||
this.threadPool.getThreadContext().stashContext()) {
|
||||
RestStatus restStatus = client.index(request).actionGet().status();
|
||||
future.complete(restStatus);
|
||||
} catch (Exception e) {
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} catch (IOException e) {
|
||||
log.error(
|
||||
"Error indexing command with id [{}] due to {}", document.getId(), e);
|
||||
log.error("Error indexing command with id [{}] due to {}", document.getId(), e);
|
||||
}
|
||||
return future;
|
||||
}
|
||||
@ -104,10 +105,8 @@ public class CommandIndex implements IndexingOperationListener {
|
||||
* @return whether the index template exists.
|
||||
*/
|
||||
public boolean indexTemplateExists(String template_name) {
|
||||
Map<String, IndexTemplateMetadata> templates = this.clusterService
|
||||
.state()
|
||||
.metadata()
|
||||
.templates();
|
||||
Map<String, IndexTemplateMetadata> templates =
|
||||
this.clusterService.state().metadata().templates();
|
||||
log.debug("Existing index templates: {} ", templates);
|
||||
|
||||
return templates.containsKey(template_name);
|
||||
@ -124,25 +123,25 @@ public class CommandIndex implements IndexingOperationListener {
|
||||
// @throws IOException
|
||||
Map<String, Object> template = IndexTemplateUtils.fromFile(templateName + ".json");
|
||||
|
||||
PutIndexTemplateRequest putIndexTemplateRequest = new PutIndexTemplateRequest()
|
||||
.mapping(IndexTemplateUtils.get(template, "mappings"))
|
||||
.settings(IndexTemplateUtils.get(template, "settings"))
|
||||
.name(templateName)
|
||||
.patterns((List<String>) template.get("index_patterns"));
|
||||
PutIndexTemplateRequest putIndexTemplateRequest =
|
||||
new PutIndexTemplateRequest()
|
||||
.mapping(IndexTemplateUtils.get(template, "mappings"))
|
||||
.settings(IndexTemplateUtils.get(template, "settings"))
|
||||
.name(templateName)
|
||||
.patterns((List<String>) template.get("index_patterns"));
|
||||
|
||||
executor.submit(() -> {
|
||||
AcknowledgedResponse acknowledgedResponse = this.client
|
||||
.admin()
|
||||
.indices()
|
||||
.putTemplate(putIndexTemplateRequest)
|
||||
.actionGet();
|
||||
if (acknowledgedResponse.isAcknowledged()) {
|
||||
log.info(
|
||||
"Index template [{}] created successfully",
|
||||
templateName
|
||||
);
|
||||
}
|
||||
});
|
||||
executor.submit(
|
||||
() -> {
|
||||
AcknowledgedResponse acknowledgedResponse =
|
||||
this.client
|
||||
.admin()
|
||||
.indices()
|
||||
.putTemplate(putIndexTemplateRequest)
|
||||
.actionGet();
|
||||
if (acknowledgedResponse.isAcknowledged()) {
|
||||
log.info("Index template [{}] created successfully", templateName);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading index template [{}] from filesystem", templateName);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -14,9 +15,7 @@ import org.opensearch.core.xcontent.XContentParser;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command's action fields.
|
||||
*/
|
||||
/** Command's action fields. */
|
||||
public class Action implements ToXContentObject {
|
||||
public static final String ACTION = "action";
|
||||
public static final String NAME = "name";
|
||||
@ -29,8 +28,8 @@ public class Action implements ToXContentObject {
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @param name action to be executed on the target,
|
||||
* @param args actual command.
|
||||
* @param name action to be executed on the target,
|
||||
* @param args actual command.
|
||||
* @param version version of the action.
|
||||
*/
|
||||
public Action(String name, List<String> args, String version) {
|
||||
@ -84,10 +83,15 @@ public class Action implements ToXContentObject {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Action{" +
|
||||
"name='" + name + '\'' +
|
||||
", args=" + args +
|
||||
", version='" + version + '\'' +
|
||||
'}';
|
||||
return "Action{"
|
||||
+ "name='"
|
||||
+ name
|
||||
+ '\''
|
||||
+ ", args="
|
||||
+ args
|
||||
+ ", version='"
|
||||
+ version
|
||||
+ '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -14,9 +15,7 @@ import org.opensearch.core.xcontent.XContentParser;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command's agent fields.
|
||||
*/
|
||||
/** Command's agent fields. */
|
||||
public class Agent implements ToXContentObject {
|
||||
public static final String AGENT = "agent";
|
||||
public static final String GROUPS = "groups";
|
||||
@ -63,8 +62,6 @@ public class Agent implements ToXContentObject {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Agent{" +
|
||||
"groups=" + groups +
|
||||
'}';
|
||||
return "Agent{" + "groups=" + groups + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -12,11 +13,12 @@ import org.opensearch.core.xcontent.ToXContent;
|
||||
import org.opensearch.core.xcontent.ToXContentObject;
|
||||
import org.opensearch.core.xcontent.XContentBuilder;
|
||||
import org.opensearch.core.xcontent.XContentParser;
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
public class Command implements ToXContentObject {
|
||||
public static final String COMMAND = "command";
|
||||
public static final String ORDER_ID = "order_id";
|
||||
@ -37,19 +39,18 @@ public class Command implements ToXContentObject {
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @param source origin of the request.
|
||||
* @param target {@link Target}
|
||||
* @param source origin of the request.
|
||||
* @param target {@link Target}
|
||||
* @param timeout time window in which the command has to be sent to its target.
|
||||
* @param user the user that originated the request
|
||||
* @param action {@link Action}
|
||||
* @param user the user that originated the request
|
||||
* @param action {@link Action}
|
||||
*/
|
||||
public Command(
|
||||
@NonNull String source,
|
||||
@NonNull Target target,
|
||||
@NonNull Integer timeout,
|
||||
@NonNull String user,
|
||||
@NonNull Action action
|
||||
) {
|
||||
@NonNull Action action) {
|
||||
this.requestId = UUIDs.base64UUID();
|
||||
this.orderId = UUIDs.base64UUID();
|
||||
this.source = source;
|
||||
@ -65,10 +66,11 @@ public class Command implements ToXContentObject {
|
||||
*
|
||||
* @param parser XContentParser from the Rest Request
|
||||
* @return instance of Command
|
||||
* @throws IOException error parsing request content
|
||||
* @throws IOException error parsing request content
|
||||
* @throws IllegalArgumentException missing arguments
|
||||
*/
|
||||
public static Command parse(XContentParser parser) throws IOException, IllegalArgumentException {
|
||||
public static Command parse(XContentParser parser)
|
||||
throws IOException, IllegalArgumentException {
|
||||
String source = null;
|
||||
Target target = null;
|
||||
Integer timeout = null;
|
||||
@ -121,13 +123,7 @@ public class Command implements ToXContentObject {
|
||||
if (!nullArguments.isEmpty()) {
|
||||
throw new IllegalArgumentException("Missing arguments: " + nullArguments);
|
||||
} else {
|
||||
return new Command(
|
||||
source,
|
||||
target,
|
||||
timeout,
|
||||
user,
|
||||
action
|
||||
);
|
||||
return new Command(source, target, timeout, user, action);
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,15 +144,27 @@ public class Command implements ToXContentObject {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Command{" +
|
||||
"orderId='" + orderId + '\'' +
|
||||
", requestId='" + requestId + '\'' +
|
||||
", source='" + source + '\'' +
|
||||
", target=" + target +
|
||||
", timeout=" + timeout +
|
||||
", user='" + user + '\'' +
|
||||
", status=" + status +
|
||||
", action=" + action +
|
||||
'}';
|
||||
return "Command{"
|
||||
+ "orderId='"
|
||||
+ orderId
|
||||
+ '\''
|
||||
+ ", requestId='"
|
||||
+ requestId
|
||||
+ '\''
|
||||
+ ", source='"
|
||||
+ source
|
||||
+ '\''
|
||||
+ ", target="
|
||||
+ target
|
||||
+ ", timeout="
|
||||
+ timeout
|
||||
+ ", user='"
|
||||
+ user
|
||||
+ '\''
|
||||
+ ", status="
|
||||
+ status
|
||||
+ ", action="
|
||||
+ action
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -15,9 +16,7 @@ import org.opensearch.core.xcontent.XContentParser;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command's target fields.
|
||||
*/
|
||||
/** Command's target fields. */
|
||||
public class Document implements ToXContentObject {
|
||||
private final Agent agent;
|
||||
private final Command command;
|
||||
@ -74,9 +73,6 @@ public class Document implements ToXContentObject {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Document{" +
|
||||
"agent=" + agent +
|
||||
", command=" + command +
|
||||
'}';
|
||||
return "Document{" + "agent=" + agent + ", command=" + command + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -13,9 +14,7 @@ import org.opensearch.core.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Command's target fields.
|
||||
*/
|
||||
/** Command's target fields. */
|
||||
public class Target implements ToXContentObject {
|
||||
public static final String TARGET = "target";
|
||||
public static final String TYPE = "type";
|
||||
@ -27,7 +26,7 @@ public class Target implements ToXContentObject {
|
||||
* Default constructor.
|
||||
*
|
||||
* @param type The destination type. One of [`group`, `agent`, `server`]
|
||||
* @param id Unique identifier of the destination to send the command to.
|
||||
* @param id Unique identifier of the destination to send the command to.
|
||||
*/
|
||||
public Target(String type, String id) {
|
||||
this.type = type;
|
||||
@ -72,9 +71,6 @@ public class Target implements ToXContentObject {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Target{" +
|
||||
"type='" + type + '\'' +
|
||||
", id='" + id + '\'' +
|
||||
'}';
|
||||
return "Target{" + "type='" + type + '\'' + ", id='" + id + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,12 +8,6 @@
|
||||
*/
|
||||
package com.wazuh.commandmanager.rest;
|
||||
|
||||
import com.wazuh.commandmanager.CommandManagerPlugin;
|
||||
import com.wazuh.commandmanager.index.CommandIndex;
|
||||
import com.wazuh.commandmanager.model.Agent;
|
||||
import com.wazuh.commandmanager.model.Command;
|
||||
import com.wazuh.commandmanager.model.Document;
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClient;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.core5.net.URIBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -34,17 +29,24 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.wazuh.commandmanager.CommandManagerPlugin;
|
||||
import com.wazuh.commandmanager.index.CommandIndex;
|
||||
import com.wazuh.commandmanager.model.Agent;
|
||||
import com.wazuh.commandmanager.model.Command;
|
||||
import com.wazuh.commandmanager.model.Document;
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClient;
|
||||
|
||||
import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
import static org.opensearch.rest.RestRequest.Method.POST;
|
||||
|
||||
/**
|
||||
* Handles HTTP requests to the POST
|
||||
* {@value com.wazuh.commandmanager.CommandManagerPlugin#COMMANDS_URI}
|
||||
* endpoint.
|
||||
* Handles HTTP requests to the POST {@value
|
||||
* com.wazuh.commandmanager.CommandManagerPlugin#COMMANDS_URI} endpoint.
|
||||
*/
|
||||
public class RestPostCommandAction extends BaseRestHandler {
|
||||
|
||||
public static final String POST_COMMAND_ACTION_REQUEST_DETAILS = "post_command_action_request_details";
|
||||
public static final String POST_COMMAND_ACTION_REQUEST_DETAILS =
|
||||
"post_command_action_request_details";
|
||||
private static final Logger log = LogManager.getLogger(RestPostCommandAction.class);
|
||||
private final CommandIndex commandIndex;
|
||||
|
||||
@ -55,7 +57,6 @@ public class RestPostCommandAction extends BaseRestHandler {
|
||||
*/
|
||||
public RestPostCommandAction(CommandIndex commandIndex) {
|
||||
this.commandIndex = commandIndex;
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -66,21 +67,12 @@ public class RestPostCommandAction extends BaseRestHandler {
|
||||
public List<Route> routes() {
|
||||
return Collections.singletonList(
|
||||
new Route(
|
||||
POST,
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"%s",
|
||||
CommandManagerPlugin.COMMANDS_URI
|
||||
)
|
||||
)
|
||||
);
|
||||
POST, String.format(Locale.ROOT, "%s", CommandManagerPlugin.COMMANDS_URI)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RestChannelConsumer prepareRequest(
|
||||
final RestRequest request,
|
||||
final NodeClient client
|
||||
) throws IOException {
|
||||
protected RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client)
|
||||
throws IOException {
|
||||
switch (request.method()) {
|
||||
case POST:
|
||||
return handlePost(request);
|
||||
@ -103,27 +95,27 @@ public class RestPostCommandAction extends BaseRestHandler {
|
||||
request.method().name(),
|
||||
request.uri(),
|
||||
request.getRequestId(),
|
||||
request.header("Host")
|
||||
);
|
||||
request.header("Host"));
|
||||
// Get request details
|
||||
XContentParser parser = request.contentParser();
|
||||
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
|
||||
|
||||
Command command = Command.parse(parser);
|
||||
Document document = new Document(
|
||||
new Agent(List.of("groups000")), // TODO read agent from .agents index
|
||||
command
|
||||
);
|
||||
Document document =
|
||||
new Document(
|
||||
new Agent(List.of("groups000")), // TODO read agent from .agents index
|
||||
command);
|
||||
|
||||
// Commands delivery to the Management API.
|
||||
// Note: needs to be decoupled from the Rest handler (job scheduler task).
|
||||
HttpRestClient httpClient = HttpRestClient.getInstance();
|
||||
try {
|
||||
String uri = "https://httpbin.org/post";
|
||||
// String uri = "https://127.0.0.1:5000";
|
||||
URI receiverURI = new URIBuilder(uri)
|
||||
.build();
|
||||
String payload = document.toXContent(XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS).toString();
|
||||
// String uri = "https://127.0.0.1:5000";
|
||||
URI receiverURI = new URIBuilder(uri).build();
|
||||
String payload =
|
||||
document.toXContent(XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS)
|
||||
.toString();
|
||||
SimpleHttpResponse response = httpClient.post(receiverURI, payload, document.getId());
|
||||
log.info("Received response to POST request with code [{}]", response.getCode());
|
||||
log.info("Raw response:\n{}", response.getBodyText());
|
||||
@ -135,27 +127,35 @@ public class RestPostCommandAction extends BaseRestHandler {
|
||||
|
||||
// Send response
|
||||
return channel -> {
|
||||
this.commandIndex.asyncCreate(document)
|
||||
.thenAccept(restStatus -> {
|
||||
try (XContentBuilder builder = channel.newBuilder()) {
|
||||
builder.startObject();
|
||||
builder.field("_index", CommandManagerPlugin.COMMAND_MANAGER_INDEX_NAME);
|
||||
builder.field("_id", document.getId());
|
||||
builder.field("result", restStatus.name());
|
||||
builder.endObject();
|
||||
channel.sendResponse(new BytesRestResponse(restStatus, builder));
|
||||
} catch (IOException e) {
|
||||
log.error("Error preparing response to [{}] request with id [{}] due to {}",
|
||||
request.method().name(),
|
||||
request.getRequestId(),
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
}).exceptionally(e -> {
|
||||
channel.sendResponse(new BytesRestResponse(RestStatus.INTERNAL_SERVER_ERROR, e.getMessage()));
|
||||
return null;
|
||||
});
|
||||
|
||||
this.commandIndex
|
||||
.asyncCreate(document)
|
||||
.thenAccept(
|
||||
restStatus -> {
|
||||
try (XContentBuilder builder = channel.newBuilder()) {
|
||||
builder.startObject();
|
||||
builder.field(
|
||||
"_index",
|
||||
CommandManagerPlugin.COMMAND_MANAGER_INDEX_NAME);
|
||||
builder.field("_id", document.getId());
|
||||
builder.field("result", restStatus.name());
|
||||
builder.endObject();
|
||||
channel.sendResponse(
|
||||
new BytesRestResponse(restStatus, builder));
|
||||
} catch (IOException e) {
|
||||
log.error(
|
||||
"Error preparing response to [{}] request with id [{}] due to {}",
|
||||
request.method().name(),
|
||||
request.getRequestId(),
|
||||
e.getMessage());
|
||||
}
|
||||
})
|
||||
.exceptionally(
|
||||
e -> {
|
||||
channel.sendResponse(
|
||||
new BytesRestResponse(
|
||||
RestStatus.INTERNAL_SERVER_ERROR, e.getMessage()));
|
||||
return null;
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,43 +1,37 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
* this file be licensed under the Apache-2.0 license or a
|
||||
* compatible open source license.
|
||||
*/
|
||||
|
||||
package com.wazuh.commandmanager.utils;
|
||||
|
||||
import org.opensearch.common.xcontent.json.JsonXContent;
|
||||
import org.opensearch.core.xcontent.DeprecationHandler;
|
||||
import org.opensearch.core.xcontent.NamedXContentRegistry;
|
||||
import org.opensearch.core.xcontent.XContentParser;
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Util functions to parse and manage index templates files.
|
||||
*/
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
/** Util functions to parse and manage index templates files. */
|
||||
public class IndexTemplateUtils {
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public IndexTemplateUtils() {
|
||||
}
|
||||
/** Default constructor */
|
||||
public IndexTemplateUtils() {}
|
||||
|
||||
/**
|
||||
* Read index template file from the resources folder and returns its JSON
|
||||
* content as a map.
|
||||
* Read index template file from the resources folder and returns its JSON content as a map.
|
||||
*
|
||||
* @param filename name of the index template to read from the resources folder
|
||||
* @return the JSON index template as a map
|
||||
* @throws IOException file not found or could not be read
|
||||
*/
|
||||
|
||||
public static Map<String, Object> fromFile(@NonNull String filename) throws IOException {
|
||||
InputStream is = IndexTemplateUtils.class.getClassLoader().getResourceAsStream(filename);
|
||||
return IndexTemplateUtils.toMap(is);
|
||||
@ -45,29 +39,29 @@ public class IndexTemplateUtils {
|
||||
|
||||
/**
|
||||
* Convert from a JSON InputStream into a String, Object map.
|
||||
* <p>
|
||||
* Used to convert the JSON index templates to the required format.
|
||||
* </p>
|
||||
*
|
||||
* <p>Used to convert the JSON index templates to the required format.
|
||||
*
|
||||
* @param is: the JSON formatted InputStream
|
||||
* @return a map with the json string contents.
|
||||
* @throws IOException thrown by {@link JsonXContent#createParser(NamedXContentRegistry, DeprecationHandler, InputStream)}
|
||||
* @throws IOException thrown by {@link JsonXContent#createParser(NamedXContentRegistry,
|
||||
* DeprecationHandler, InputStream)}
|
||||
*/
|
||||
public static Map<String, Object> toMap(InputStream is) throws IOException {
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(
|
||||
NamedXContentRegistry.EMPTY,
|
||||
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
|
||||
is);
|
||||
XContentParser parser =
|
||||
JsonXContent.jsonXContent.createParser(
|
||||
NamedXContentRegistry.EMPTY,
|
||||
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
|
||||
is);
|
||||
parser.nextToken();
|
||||
return parser.map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast map's element to a String, Object map.
|
||||
* <p>
|
||||
* Used to retrieve the settings and mappings from the index templates,
|
||||
* which are a JSON object themselves.
|
||||
* </p>
|
||||
*
|
||||
* <p>Used to retrieve the settings and mappings from the index templates, which are a JSON
|
||||
* object themselves.
|
||||
*
|
||||
* @param map the index template as a map.
|
||||
* @param key the element's key to retrieve and cast.
|
||||
@ -76,6 +70,4 @@ public class IndexTemplateUtils {
|
||||
public static Map<String, Object> get(Map<String, Object> map, String key) {
|
||||
return (Map<String, Object>) map.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -18,18 +19,13 @@ public class HttpResponseCallback implements FutureCallback<SimpleHttpResponse>
|
||||
|
||||
private static final Logger log = LogManager.getLogger(HttpResponseCallback.class);
|
||||
|
||||
/**
|
||||
* The Http get request.
|
||||
*/
|
||||
/** The Http get request. */
|
||||
SimpleHttpRequest httpRequest;
|
||||
|
||||
/**
|
||||
* The Error message.
|
||||
*/
|
||||
/** The Error message. */
|
||||
String errorMessage;
|
||||
|
||||
public HttpResponseCallback(SimpleHttpRequest httpRequest,
|
||||
String errorMessage) {
|
||||
public HttpResponseCallback(SimpleHttpRequest httpRequest, String errorMessage) {
|
||||
this.httpRequest = httpRequest;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
@ -43,7 +39,7 @@ public class HttpResponseCallback implements FutureCallback<SimpleHttpResponse>
|
||||
@Override
|
||||
public void failed(Exception ex) {
|
||||
log.error("{}->{}", httpRequest, ex);
|
||||
// throw new HttpException(errorMessage, ex);
|
||||
// throw new HttpException(errorMessage, ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -26,10 +27,7 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* HTTP Rest client. Currently used to perform
|
||||
* POST requests against the Wazuh Server.
|
||||
*/
|
||||
/** HTTP Rest client. Currently used to perform POST requests against the Wazuh Server. */
|
||||
public class HttpRestClient {
|
||||
|
||||
public static final long TIMEOUT = 4;
|
||||
@ -38,9 +36,7 @@ public class HttpRestClient {
|
||||
private static HttpRestClient instance;
|
||||
private CloseableHttpAsyncClient httpClient;
|
||||
|
||||
/**
|
||||
* Private default constructor
|
||||
*/
|
||||
/** Private default constructor */
|
||||
private HttpRestClient() {
|
||||
startHttpAsyncClient();
|
||||
}
|
||||
@ -57,23 +53,21 @@ public class HttpRestClient {
|
||||
return HttpRestClient.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts http async client.
|
||||
*/
|
||||
/** Starts http async client. */
|
||||
private void startHttpAsyncClient() {
|
||||
if (this.httpClient == null) {
|
||||
try {
|
||||
PoolingAsyncClientConnectionManager cm =
|
||||
PoolingAsyncClientConnectionManagerBuilder.create().build();
|
||||
|
||||
IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
|
||||
.setSoTimeout(Timeout.ofSeconds(5))
|
||||
.build();
|
||||
IOReactorConfig ioReactorConfig =
|
||||
IOReactorConfig.custom().setSoTimeout(Timeout.ofSeconds(5)).build();
|
||||
|
||||
httpClient = HttpAsyncClients.custom()
|
||||
.setIOReactorConfig(ioReactorConfig)
|
||||
.setConnectionManager(cm)
|
||||
.build();
|
||||
httpClient =
|
||||
HttpAsyncClients.custom()
|
||||
.setIOReactorConfig(ioReactorConfig)
|
||||
.setConnectionManager(cm)
|
||||
.build();
|
||||
|
||||
httpClient.start();
|
||||
} catch (Exception e) {
|
||||
@ -83,9 +77,7 @@ public class HttpRestClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop http async client.
|
||||
*/
|
||||
/** Stop http async client. */
|
||||
public void stopHttpAsyncClient() {
|
||||
if (this.httpClient != null) {
|
||||
log.info("Shutting down.");
|
||||
@ -98,26 +90,22 @@ public class HttpRestClient {
|
||||
* Sends a POST request.
|
||||
*
|
||||
* @param receiverURI Well-formed URI
|
||||
* @param payload data to send
|
||||
* @param payloadId payload ID
|
||||
* @param payload data to send
|
||||
* @param payloadId payload ID
|
||||
* @return SimpleHttpResponse response
|
||||
*/
|
||||
public SimpleHttpResponse post(URI receiverURI, String payload, String payloadId) {
|
||||
try {
|
||||
HttpHost httpHost = HttpHost.create(receiverURI);
|
||||
|
||||
log.info(
|
||||
"Sending payload with id [{}] to [{}]",
|
||||
payloadId,
|
||||
receiverURI
|
||||
);
|
||||
log.info("Sending payload with id [{}] to [{}]", payloadId, receiverURI);
|
||||
|
||||
SimpleHttpRequest httpPostRequest = SimpleRequestBuilder
|
||||
.post()
|
||||
.setHttpHost(httpHost)
|
||||
.setPath(receiverURI.getPath())
|
||||
.setBody(payload, ContentType.APPLICATION_JSON)
|
||||
.build();
|
||||
SimpleHttpRequest httpPostRequest =
|
||||
SimpleRequestBuilder.post()
|
||||
.setHttpHost(httpHost)
|
||||
.setPath(receiverURI.getPath())
|
||||
.setBody(payload, ContentType.APPLICATION_JSON)
|
||||
.build();
|
||||
|
||||
Future<SimpleHttpResponse> future =
|
||||
this.httpClient.execute(
|
||||
@ -125,9 +113,9 @@ public class HttpRestClient {
|
||||
SimpleResponseConsumer.create(),
|
||||
new HttpResponseCallback(
|
||||
httpPostRequest,
|
||||
"Failed to execute outgoing POST request with payload id [" + payloadId + "]"
|
||||
)
|
||||
);
|
||||
"Failed to execute outgoing POST request with payload id ["
|
||||
+ payloadId
|
||||
+ "]"));
|
||||
|
||||
return future.get(TIMEOUT, TIME_UNIT);
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -17,9 +18,7 @@ import java.net.URISyntaxException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* Demo class to test the {@link HttpRestClient} class.
|
||||
*/
|
||||
/** Demo class to test the {@link HttpRestClient} class. */
|
||||
public class HttpRestClientDemo {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(HttpRestClientDemo.class);
|
||||
@ -28,25 +27,28 @@ public class HttpRestClientDemo {
|
||||
* Demo method to test the {@link HttpRestClient} class.
|
||||
*
|
||||
* @param endpoint POST's requests endpoint as a well-formed URI
|
||||
* @param body POST's request body as a JSON string.
|
||||
* @param body POST's request body as a JSON string.
|
||||
*/
|
||||
public static void run(String endpoint, String body) {
|
||||
log.info("Executing POST request");
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<SimpleHttpResponse>) () -> {
|
||||
HttpRestClient httpClient = HttpRestClient.getInstance();
|
||||
try {
|
||||
URI host = new URIBuilder(endpoint).build();
|
||||
SimpleHttpResponse response = httpClient.post(host, body, "randomId");
|
||||
log.info("Received response to POST request with code {}", response.getCode());
|
||||
log.info("Raw response:\n{}", response.getBodyText());
|
||||
} catch (URISyntaxException e) {
|
||||
log.error("Bad URI:{}", e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("Error reading response: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
(PrivilegedAction<SimpleHttpResponse>)
|
||||
() -> {
|
||||
HttpRestClient httpClient = HttpRestClient.getInstance();
|
||||
try {
|
||||
URI host = new URIBuilder(endpoint).build();
|
||||
SimpleHttpResponse response =
|
||||
httpClient.post(host, body, "randomId");
|
||||
log.info(
|
||||
"Received response to POST request with code {}",
|
||||
response.getCode());
|
||||
log.info("Raw response:\n{}", response.getBodyText());
|
||||
} catch (URISyntaxException e) {
|
||||
log.error("Bad URI:{}", e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("Error reading response: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -8,6 +9,7 @@
|
||||
package com.wazuh.commandmanager;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
|
||||
|
||||
import org.apache.http.ParseException;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,16 +8,17 @@
|
||||
*/
|
||||
package com.wazuh.commandmanager;
|
||||
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClient;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.junit.Assert;
|
||||
import org.opensearch.test.OpenSearchTestCase;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import com.wazuh.commandmanager.utils.httpclient.HttpRestClient;
|
||||
|
||||
public class CommandManagerTests extends OpenSearchTestCase {
|
||||
// Add unit tests for your plugin
|
||||
|
||||
@ -25,26 +27,27 @@ public class CommandManagerTests extends OpenSearchTestCase {
|
||||
public void testPost_success() {
|
||||
try {
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<SimpleHttpResponse>) () -> {
|
||||
this.httpClient = HttpRestClient.getInstance();
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI("https://httpbin.org/post");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String payload = "{\"message\": \"Hello world!\"}";
|
||||
SimpleHttpResponse postResponse = this.httpClient.post(uri, payload, "randomId");
|
||||
(PrivilegedAction<SimpleHttpResponse>)
|
||||
() -> {
|
||||
this.httpClient = HttpRestClient.getInstance();
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI("https://httpbin.org/post");
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String payload = "{\"message\": \"Hello world!\"}";
|
||||
SimpleHttpResponse postResponse =
|
||||
this.httpClient.post(uri, payload, "randomId");
|
||||
|
||||
String responseText = postResponse.getBodyText();
|
||||
assertNotEquals(null, postResponse);
|
||||
assertNotEquals(null, responseText);
|
||||
assertEquals(200, postResponse.getCode());
|
||||
assertNotEquals(0, responseText.length());
|
||||
assertTrue(responseText.contains("Hello world!"));
|
||||
return postResponse;
|
||||
}
|
||||
);
|
||||
String responseText = postResponse.getBodyText();
|
||||
assertNotEquals(null, postResponse);
|
||||
assertNotEquals(null, responseText);
|
||||
assertEquals(200, postResponse.getCode());
|
||||
assertNotEquals(0, responseText.length());
|
||||
assertTrue(responseText.contains("Hello world!"));
|
||||
return postResponse;
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Assert.fail("Failed to execute HTTP request: " + e);
|
||||
} finally {
|
||||
@ -52,9 +55,7 @@ public class CommandManagerTests extends OpenSearchTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testPost_badUri() {
|
||||
}
|
||||
public void testPost_badUri() {}
|
||||
|
||||
public void testPost_badPayload() {
|
||||
}
|
||||
public void testPost_badPayload() {}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -9,13 +10,14 @@ package com.wazuh.commandmanager;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.opensearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.opensearch.test.rest.yaml.OpenSearchClientYamlSuiteTestCase;
|
||||
|
||||
|
||||
public class CommandManagerClientYamlTestSuiteIT extends OpenSearchClientYamlSuiteTestCase {
|
||||
|
||||
public CommandManagerClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
public CommandManagerClientYamlTestSuiteIT(
|
||||
@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,24 @@
|
||||
import org.opensearch.gradle.test.RestIntegTestTask
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
opensearch_version = System.getProperty("opensearch.version", "2.16.0")
|
||||
wazuh_version = System.getProperty("version", "5.0.0")
|
||||
revision = System.getProperty("revision", "0")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
|
||||
mavenCentral()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.opensearch.gradle:build-tools:${opensearch_version}"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'eclipse'
|
||||
@ -13,7 +32,6 @@ def projectPath = 'com.wazuh'
|
||||
def pathToPlugin = 'setup'
|
||||
def pluginClassName = 'SetupPlugin'
|
||||
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
pluginZip(MavenPublication) { publication ->
|
||||
@ -58,25 +76,6 @@ loggerUsageCheck.enabled = false
|
||||
// No need to validate pom, as we do not upload to maven/sonatype
|
||||
validateNebulaPom.enabled = false
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
opensearch_version = System.getProperty("opensearch.version", "2.16.0")
|
||||
wazuh_version = System.getProperty("version", "5.0.0")
|
||||
revision = System.getProperty("revision", "0")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
|
||||
mavenCentral()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.opensearch.gradle:build-tools:${opensearch_version}"
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,7 +8,6 @@
|
||||
*/
|
||||
package com.wazuh.setup;
|
||||
|
||||
import com.wazuh.setup.index.WazuhIndices;
|
||||
import org.opensearch.client.Client;
|
||||
import org.opensearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.opensearch.cluster.node.DiscoveryNode;
|
||||
@ -27,20 +27,18 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.wazuh.setup.index.WazuhIndices;
|
||||
|
||||
/**
|
||||
* Main class of the Indexer Setup plugin. This plugin is responsible for
|
||||
* the creation of the index templates and indices required by Wazuh to
|
||||
* work properly.
|
||||
* Main class of the Indexer Setup plugin. This plugin is responsible for the creation of the index
|
||||
* templates and indices required by Wazuh to work properly.
|
||||
*/
|
||||
public class SetupPlugin extends Plugin implements ClusterPlugin {
|
||||
|
||||
private WazuhIndices indices;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public SetupPlugin() {
|
||||
}
|
||||
/** Default constructor */
|
||||
public SetupPlugin() {}
|
||||
|
||||
@Override
|
||||
public Collection<Object> createComponents(
|
||||
@ -54,8 +52,7 @@ public class SetupPlugin extends Plugin implements ClusterPlugin {
|
||||
NodeEnvironment nodeEnvironment,
|
||||
NamedWriteableRegistry namedWriteableRegistry,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
Supplier<RepositoriesService> repositoriesServiceSupplier
|
||||
) {
|
||||
Supplier<RepositoriesService> repositoriesServiceSupplier) {
|
||||
this.indices = new WazuhIndices(client, clusterService);
|
||||
return List.of(this.indices);
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,7 +8,6 @@
|
||||
*/
|
||||
package com.wazuh.setup.index;
|
||||
|
||||
import com.wazuh.setup.utils.IndexTemplateUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.opensearch.action.admin.indices.create.CreateIndexRequest;
|
||||
@ -22,25 +22,24 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.wazuh.setup.utils.IndexTemplateUtils;
|
||||
|
||||
/**
|
||||
* This class contains the logic to create the index templates and the indices
|
||||
* required by Wazuh.
|
||||
* This class contains the logic to create the index templates and the indices required by Wazuh.
|
||||
*/
|
||||
public class WazuhIndices {
|
||||
private static final Logger log = LogManager.getLogger(WazuhIndices.class);
|
||||
/**
|
||||
* | Key | value |
|
||||
* | ------------------- | ---------- |
|
||||
* | Index template name | index name |
|
||||
*/
|
||||
|
||||
/** | Key | value | | ------------------- | ---------- | | Index template name | index name | */
|
||||
public final Map<String, String> indexTemplates = new HashMap<>();
|
||||
|
||||
private final Client client;
|
||||
private final ClusterService clusterService;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param client Client
|
||||
* @param client Client
|
||||
* @param clusterService ClusterService
|
||||
*/
|
||||
public WazuhIndices(Client client, ClusterService clusterService) {
|
||||
@ -67,23 +66,20 @@ public class WazuhIndices {
|
||||
// @throws IOException
|
||||
Map<String, Object> template = IndexTemplateUtils.fromFile(templateName + ".json");
|
||||
|
||||
PutIndexTemplateRequest putIndexTemplateRequest = new PutIndexTemplateRequest()
|
||||
.mapping(IndexTemplateUtils.get(template, "mappings"))
|
||||
.settings(IndexTemplateUtils.get(template, "settings"))
|
||||
.name(templateName)
|
||||
.patterns((List<String>) template.get("index_patterns"));
|
||||
PutIndexTemplateRequest putIndexTemplateRequest =
|
||||
new PutIndexTemplateRequest()
|
||||
.mapping(IndexTemplateUtils.get(template, "mappings"))
|
||||
.settings(IndexTemplateUtils.get(template, "settings"))
|
||||
.name(templateName)
|
||||
.patterns((List<String>) template.get("index_patterns"));
|
||||
|
||||
AcknowledgedResponse createIndexTemplateResponse = this.client
|
||||
.admin()
|
||||
.indices()
|
||||
.putTemplate(putIndexTemplateRequest)
|
||||
.actionGet();
|
||||
AcknowledgedResponse createIndexTemplateResponse =
|
||||
this.client.admin().indices().putTemplate(putIndexTemplateRequest).actionGet();
|
||||
|
||||
log.info(
|
||||
"Index template created successfully: {} {}",
|
||||
templateName,
|
||||
createIndexTemplateResponse.isAcknowledged()
|
||||
);
|
||||
createIndexTemplateResponse.isAcknowledged());
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading index template from filesystem {}", templateName);
|
||||
@ -98,16 +94,12 @@ public class WazuhIndices {
|
||||
public void putIndex(String indexName) {
|
||||
if (!indexExists(indexName)) {
|
||||
CreateIndexRequest request = new CreateIndexRequest(indexName);
|
||||
CreateIndexResponse createIndexResponse = this.client
|
||||
.admin()
|
||||
.indices()
|
||||
.create(request)
|
||||
.actionGet();
|
||||
CreateIndexResponse createIndexResponse =
|
||||
this.client.admin().indices().create(request).actionGet();
|
||||
log.info(
|
||||
"Index created successfully: {} {}",
|
||||
createIndexResponse.index(),
|
||||
createIndexResponse.isAcknowledged()
|
||||
);
|
||||
createIndexResponse.isAcknowledged());
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,16 +113,15 @@ public class WazuhIndices {
|
||||
return this.clusterService.state().getRoutingTable().hasIndex(indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates each index template and index in {@link #indexTemplates}.
|
||||
*/
|
||||
/** Creates each index template and index in {@link #indexTemplates}. */
|
||||
public void initialize() {
|
||||
// 1. Read index templates from files
|
||||
// 2. Upsert index template
|
||||
// 3. Create index
|
||||
this.indexTemplates.forEach((k, v) -> {
|
||||
this.putTemplate(k);
|
||||
this.putIndex(v);
|
||||
});
|
||||
this.indexTemplates.forEach(
|
||||
(k, v) -> {
|
||||
this.putTemplate(k);
|
||||
this.putIndex(v);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,43 +1,37 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
* this file be licensed under the Apache-2.0 license or a
|
||||
* compatible open source license.
|
||||
*/
|
||||
|
||||
package com.wazuh.setup.utils;
|
||||
|
||||
import org.opensearch.common.xcontent.json.JsonXContent;
|
||||
import org.opensearch.core.xcontent.DeprecationHandler;
|
||||
import org.opensearch.core.xcontent.NamedXContentRegistry;
|
||||
import org.opensearch.core.xcontent.XContentParser;
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Util functions to parse and manage index templates files.
|
||||
*/
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
/** Util functions to parse and manage index templates files. */
|
||||
public class IndexTemplateUtils {
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public IndexTemplateUtils() {
|
||||
}
|
||||
/** Default constructor */
|
||||
public IndexTemplateUtils() {}
|
||||
|
||||
/**
|
||||
* Read index template file from the resources folder and returns its JSON
|
||||
* content as a map.
|
||||
* Read index template file from the resources folder and returns its JSON content as a map.
|
||||
*
|
||||
* @param filename name of the index template to read from the resources folder
|
||||
* @return the JSON index template as a map
|
||||
* @throws IOException file not found or could not be read
|
||||
*/
|
||||
|
||||
public static Map<String, Object> fromFile(@NonNull String filename) throws IOException {
|
||||
InputStream is = IndexTemplateUtils.class.getClassLoader().getResourceAsStream(filename);
|
||||
return IndexTemplateUtils.toMap(is);
|
||||
@ -45,29 +39,29 @@ public class IndexTemplateUtils {
|
||||
|
||||
/**
|
||||
* Convert from a JSON InputStream into a String, Object map.
|
||||
* <p>
|
||||
* Used to convert the JSON index templates to the required format.
|
||||
* </p>
|
||||
*
|
||||
* <p>Used to convert the JSON index templates to the required format.
|
||||
*
|
||||
* @param is: the JSON formatted InputStream
|
||||
* @return a map with the json string contents.
|
||||
* @throws IOException thrown by {@link JsonXContent#createParser(NamedXContentRegistry, DeprecationHandler, InputStream)}
|
||||
* @throws IOException thrown by {@link JsonXContent#createParser(NamedXContentRegistry,
|
||||
* DeprecationHandler, InputStream)}
|
||||
*/
|
||||
public static Map<String, Object> toMap(InputStream is) throws IOException {
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(
|
||||
NamedXContentRegistry.EMPTY,
|
||||
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
|
||||
is);
|
||||
XContentParser parser =
|
||||
JsonXContent.jsonXContent.createParser(
|
||||
NamedXContentRegistry.EMPTY,
|
||||
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
|
||||
is);
|
||||
parser.nextToken();
|
||||
return parser.map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast map's element to a String, Object map.
|
||||
* <p>
|
||||
* Used to retrieve the settings and mappings from the index templates,
|
||||
* which are a JSON object themselves.
|
||||
* </p>
|
||||
*
|
||||
* <p>Used to retrieve the settings and mappings from the index templates, which are a JSON
|
||||
* object themselves.
|
||||
*
|
||||
* @param map the index template as a map.
|
||||
* @param key the element's key to retrieve and cast.
|
||||
@ -76,5 +70,4 @@ public class IndexTemplateUtils {
|
||||
public static Map<String, Object> get(Map<String, Object> map, String key) {
|
||||
return (Map<String, Object>) map.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -8,28 +9,27 @@
|
||||
package com.wazuh.setup;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
|
||||
|
||||
import org.apache.http.ParseException;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.opensearch.client.Request;
|
||||
import org.opensearch.client.Response;
|
||||
import org.opensearch.plugins.Plugin;
|
||||
import org.opensearch.test.OpenSearchIntegTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.opensearch.action.admin.cluster.health.ClusterHealthRequest;
|
||||
import org.opensearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.opensearch.action.admin.cluster.node.info.NodeInfo;
|
||||
import org.opensearch.action.admin.cluster.node.info.NodesInfoRequest;
|
||||
import org.opensearch.action.admin.cluster.node.info.NodesInfoResponse;
|
||||
import org.opensearch.action.admin.cluster.node.info.PluginsAndModules;
|
||||
import org.opensearch.client.Request;
|
||||
import org.opensearch.client.Response;
|
||||
import org.opensearch.cluster.health.ClusterHealthStatus;
|
||||
import org.opensearch.plugins.Plugin;
|
||||
import org.opensearch.plugins.PluginInfo;
|
||||
import org.opensearch.test.OpenSearchIntegTestCase;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
@ -54,36 +54,33 @@ public class SetupPluginIT extends OpenSearchIntegTestCase {
|
||||
assertThat(body, containsString("wazuh-indexer-setup"));
|
||||
}
|
||||
|
||||
|
||||
public void testPluginsAreInstalled() {
|
||||
ClusterHealthRequest request = new ClusterHealthRequest();
|
||||
ClusterHealthResponse response = OpenSearchIntegTestCase
|
||||
.client()
|
||||
.admin().
|
||||
cluster()
|
||||
.health(request)
|
||||
.actionGet();
|
||||
ClusterHealthResponse response =
|
||||
OpenSearchIntegTestCase.client().admin().cluster().health(request).actionGet();
|
||||
Assert.assertEquals(ClusterHealthStatus.GREEN, response.getStatus());
|
||||
|
||||
NodesInfoRequest nodesInfoRequest = new NodesInfoRequest();
|
||||
nodesInfoRequest.addMetric(NodesInfoRequest.Metric.PLUGINS.metricName());
|
||||
NodesInfoResponse nodesInfoResponse = OpenSearchIntegTestCase
|
||||
.client()
|
||||
.admin()
|
||||
.cluster().
|
||||
nodesInfo(nodesInfoRequest)
|
||||
.actionGet();
|
||||
List<PluginInfo> pluginInfos = nodesInfoResponse.getNodes()
|
||||
.stream()
|
||||
.flatMap((Function<NodeInfo, Stream<PluginInfo>>) nodeInfo ->
|
||||
nodeInfo
|
||||
.getInfo(PluginsAndModules.class)
|
||||
.getPluginInfos()
|
||||
.stream()
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
Assert.assertTrue(pluginInfos.stream().anyMatch(
|
||||
pluginInfo -> pluginInfo.getName().equals("wazuh-indexer-setup"))
|
||||
);
|
||||
NodesInfoResponse nodesInfoResponse =
|
||||
OpenSearchIntegTestCase.client()
|
||||
.admin()
|
||||
.cluster()
|
||||
.nodesInfo(nodesInfoRequest)
|
||||
.actionGet();
|
||||
List<PluginInfo> pluginInfos =
|
||||
nodesInfoResponse.getNodes().stream()
|
||||
.flatMap(
|
||||
(Function<NodeInfo, Stream<PluginInfo>>)
|
||||
nodeInfo ->
|
||||
nodeInfo
|
||||
.getInfo(PluginsAndModules.class)
|
||||
.getPluginInfos()
|
||||
.stream())
|
||||
.collect(Collectors.toList());
|
||||
Assert.assertTrue(
|
||||
pluginInfos.stream()
|
||||
.anyMatch(
|
||||
pluginInfo -> pluginInfo.getName().equals("wazuh-indexer-setup")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,9 +8,6 @@
|
||||
*/
|
||||
package com.wazuh.setup;
|
||||
|
||||
import com.wazuh.setup.index.WazuhIndices;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.opensearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.opensearch.action.admin.indices.create.CreateIndexResponse;
|
||||
import org.opensearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
@ -24,9 +22,13 @@ import org.opensearch.core.action.ActionListener;
|
||||
import org.opensearch.test.OpenSearchTestCase;
|
||||
import org.opensearch.threadpool.TestThreadPool;
|
||||
import org.opensearch.threadpool.ThreadPool;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import com.wazuh.setup.index.WazuhIndices;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.opensearch.test.ClusterServiceUtils.createClusterService;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class SetupPluginTests extends OpenSearchTestCase {
|
||||
|
||||
@ -36,9 +38,7 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
private ThreadPool threadPool;
|
||||
private Client mockClient;
|
||||
|
||||
/**
|
||||
* Creates the necessary mocks and spies
|
||||
*/
|
||||
/** Creates the necessary mocks and spies */
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
try {
|
||||
@ -53,18 +53,14 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts the test cluster down properly after tests are done
|
||||
*/
|
||||
/** Shuts the test cluster down properly after tests are done */
|
||||
@After
|
||||
public void testTearDown() {
|
||||
this.threadPool.shutdownNow();
|
||||
this.clusterService.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the putTemplate method
|
||||
*/
|
||||
/** Tests the putTemplate method */
|
||||
@AwaitsFix(bugUrl = "")
|
||||
public void testPutTemplate() {
|
||||
String mockTemplateName = "anIndexTemplateName";
|
||||
@ -74,11 +70,15 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
when(this.mockClient.admin()).thenReturn(mockAdminClient);
|
||||
when(mockAdminClient.indices()).thenReturn(mockIndicesAdminClient);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
ActionListener<AcknowledgedResponse> listener = invocation.getArgument(1);
|
||||
listener.onResponse(new AcknowledgedResponse(true));
|
||||
return null;
|
||||
}).when(mockIndicesAdminClient).putTemplate(any(PutIndexTemplateRequest.class), any(ActionListener.class));
|
||||
doAnswer(
|
||||
invocation -> {
|
||||
ActionListener<AcknowledgedResponse> listener =
|
||||
invocation.getArgument(1);
|
||||
listener.onResponse(new AcknowledgedResponse(true));
|
||||
return null;
|
||||
})
|
||||
.when(mockIndicesAdminClient)
|
||||
.putTemplate(any(PutIndexTemplateRequest.class), any(ActionListener.class));
|
||||
|
||||
try {
|
||||
this.wazuhIndices.putTemplate(mockTemplateName);
|
||||
@ -86,11 +86,15 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
fail(e.toString());
|
||||
}
|
||||
|
||||
doAnswer(invocation -> {
|
||||
ActionListener<AcknowledgedResponse> listener = invocation.getArgument(1);
|
||||
listener.onFailure(new Exception("Mock exception on putTemplate"));
|
||||
return null;
|
||||
}).when(mockIndicesAdminClient).putTemplate(any(PutIndexTemplateRequest.class), any(ActionListener.class));
|
||||
doAnswer(
|
||||
invocation -> {
|
||||
ActionListener<AcknowledgedResponse> listener =
|
||||
invocation.getArgument(1);
|
||||
listener.onFailure(new Exception("Mock exception on putTemplate"));
|
||||
return null;
|
||||
})
|
||||
.when(mockIndicesAdminClient)
|
||||
.putTemplate(any(PutIndexTemplateRequest.class), any(ActionListener.class));
|
||||
|
||||
try {
|
||||
this.wazuhIndices.putTemplate(mockTemplateName);
|
||||
@ -99,9 +103,7 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating an index
|
||||
*/
|
||||
/** Tests creating an index */
|
||||
@AwaitsFix(bugUrl = "")
|
||||
public void testCreate() {
|
||||
AdminClient mockAdminClient = mock(AdminClient.class);
|
||||
@ -109,24 +111,29 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
when(this.mockClient.admin()).thenReturn(mockAdminClient);
|
||||
when(mockAdminClient.indices()).thenReturn(mockIndicesAdminClient);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
ActionListener<CreateIndexResponse> listener = invocation.getArgument(1);
|
||||
listener.onResponse(new CreateIndexResponse(true, true, INDEX_NAME));
|
||||
return null;
|
||||
}).when(mockIndicesAdminClient).create(any(CreateIndexRequest.class), any(ActionListener.class));
|
||||
doAnswer(
|
||||
invocation -> {
|
||||
ActionListener<CreateIndexResponse> listener =
|
||||
invocation.getArgument(1);
|
||||
listener.onResponse(new CreateIndexResponse(true, true, INDEX_NAME));
|
||||
return null;
|
||||
})
|
||||
.when(mockIndicesAdminClient)
|
||||
.create(any(CreateIndexRequest.class), any(ActionListener.class));
|
||||
|
||||
ActionListener<CreateIndexResponse> actionListener = new ActionListener<>() {
|
||||
@Override
|
||||
public void onResponse(CreateIndexResponse createIndexResponse) {
|
||||
logger.info("Mock successful index creation");
|
||||
assertTrue(createIndexResponse.isAcknowledged());
|
||||
}
|
||||
ActionListener<CreateIndexResponse> actionListener =
|
||||
new ActionListener<>() {
|
||||
@Override
|
||||
public void onResponse(CreateIndexResponse createIndexResponse) {
|
||||
logger.info("Mock successful index creation");
|
||||
assertTrue(createIndexResponse.isAcknowledged());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
logger.error("Mock error creating index: {}", e.toString());
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
logger.error("Mock error creating index: {}", e.toString());
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
this.wazuhIndices.putIndex(INDEX_NAME);
|
||||
@ -134,11 +141,15 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
fail(e.toString());
|
||||
}
|
||||
|
||||
doAnswer(invocation -> {
|
||||
ActionListener<CreateIndexResponse> listener = invocation.getArgument(1);
|
||||
listener.onFailure(new Exception("Mock Exception"));
|
||||
return null;
|
||||
}).when(mockIndicesAdminClient).create(any(CreateIndexRequest.class), any(ActionListener.class));
|
||||
doAnswer(
|
||||
invocation -> {
|
||||
ActionListener<CreateIndexResponse> listener =
|
||||
invocation.getArgument(1);
|
||||
listener.onFailure(new Exception("Mock Exception"));
|
||||
return null;
|
||||
})
|
||||
.when(mockIndicesAdminClient)
|
||||
.create(any(CreateIndexRequest.class), any(ActionListener.class));
|
||||
|
||||
try {
|
||||
this.wazuhIndices.putIndex(INDEX_NAME);
|
||||
@ -147,9 +158,7 @@ public class SetupPluginTests extends OpenSearchTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the indexExists() method
|
||||
*/
|
||||
/** Tests the indexExists() method */
|
||||
public void testIndexExists() {
|
||||
ClusterState mockClusterState = mock(ClusterState.class);
|
||||
RoutingTable mockRoutingTable = mock(RoutingTable.class);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -7,9 +8,6 @@
|
||||
*/
|
||||
package com.wazuh.setup.index;
|
||||
|
||||
import com.wazuh.setup.utils.IndexTemplateUtils;
|
||||
import org.junit.Before;
|
||||
import org.mockito.*;
|
||||
import org.opensearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.opensearch.action.admin.indices.create.CreateIndexResponse;
|
||||
import org.opensearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
@ -21,43 +19,38 @@ import org.opensearch.cluster.ClusterState;
|
||||
import org.opensearch.cluster.routing.RoutingTable;
|
||||
import org.opensearch.cluster.service.ClusterService;
|
||||
import org.opensearch.test.OpenSearchTestCase;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.wazuh.setup.utils.IndexTemplateUtils;
|
||||
import org.mockito.*;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
|
||||
@Mock
|
||||
private Client client;
|
||||
@Mock private Client client;
|
||||
|
||||
@Mock
|
||||
private ClusterService clusterService;
|
||||
@Mock private ClusterService clusterService;
|
||||
|
||||
@Mock
|
||||
private AdminClient adminClient;
|
||||
@Mock private AdminClient adminClient;
|
||||
|
||||
@Mock
|
||||
private IndicesAdminClient indicesAdminClient;
|
||||
@Mock private IndicesAdminClient indicesAdminClient;
|
||||
|
||||
@Mock
|
||||
private ClusterState clusterState;
|
||||
@Mock private ClusterState clusterState;
|
||||
|
||||
@Mock
|
||||
private RoutingTable routingTable;
|
||||
@Mock private RoutingTable routingTable;
|
||||
|
||||
@InjectMocks
|
||||
private WazuhIndices wazuhIndices;
|
||||
@InjectMocks private WazuhIndices wazuhIndices;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<PutIndexTemplateRequest> putIndexTemplateRequestCaptor;
|
||||
@Captor private ArgumentCaptor<PutIndexTemplateRequest> putIndexTemplateRequestCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<CreateIndexRequest> createIndexRequestCaptor;
|
||||
@Captor private ArgumentCaptor<CreateIndexRequest> createIndexRequestCaptor;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@ -76,7 +69,8 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
this.wazuhIndices = new WazuhIndices(this.client, this.clusterService);
|
||||
}
|
||||
|
||||
// FIXME The used MockMaker SubclassByteBuddyMockMaker does not support the creation of static mocks
|
||||
// FIXME The used MockMaker SubclassByteBuddyMockMaker does not support the creation of static
|
||||
// mocks
|
||||
// adding mockito-inline seems to have no effect
|
||||
@AwaitsFix(bugUrl = "")
|
||||
public void testPutTemplate_Successful() {
|
||||
@ -88,8 +82,11 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
template.put("index_patterns", new HashMap<>());
|
||||
|
||||
// Mock the static method call
|
||||
try (MockedStatic<IndexTemplateUtils> mockedStatic = Mockito.mockStatic(IndexTemplateUtils.class)) {
|
||||
mockedStatic.when(() -> IndexTemplateUtils.fromFile(eq(templateName + ".json"))).thenReturn(template);
|
||||
try (MockedStatic<IndexTemplateUtils> mockedStatic =
|
||||
Mockito.mockStatic(IndexTemplateUtils.class)) {
|
||||
mockedStatic
|
||||
.when(() -> IndexTemplateUtils.fromFile(eq(templateName + ".json")))
|
||||
.thenReturn(template);
|
||||
|
||||
when(indicesAdminClient.putTemplate(any(PutIndexTemplateRequest.class)).actionGet())
|
||||
.thenReturn(mock(AcknowledgedResponse.class));
|
||||
@ -107,7 +104,8 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME The used MockMaker SubclassByteBuddyMockMaker does not support the creation of static mocks
|
||||
// FIXME The used MockMaker SubclassByteBuddyMockMaker does not support the creation of static
|
||||
// mocks
|
||||
// adding mockito-inline seems to have no effect
|
||||
@AwaitsFix(bugUrl = "")
|
||||
public void testPutTemplate_IOException() {
|
||||
@ -115,8 +113,11 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
String templateName = "index-template-agent";
|
||||
|
||||
// Mock the static method to throw IOException
|
||||
try (MockedStatic<IndexTemplateUtils> mockedStatic = Mockito.mockStatic(IndexTemplateUtils.class)) {
|
||||
mockedStatic.when(() -> IndexTemplateUtils.fromFile(eq(templateName + ".json"))).thenThrow(IOException.class);
|
||||
try (MockedStatic<IndexTemplateUtils> mockedStatic =
|
||||
Mockito.mockStatic(IndexTemplateUtils.class)) {
|
||||
mockedStatic
|
||||
.when(() -> IndexTemplateUtils.fromFile(eq(templateName + ".json")))
|
||||
.thenThrow(IOException.class);
|
||||
|
||||
// Act
|
||||
wazuhIndices.putTemplate(templateName);
|
||||
@ -126,16 +127,13 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME the return value of "org.opensearch.client.IndicesAdminClient.create(org.opensearch.action.admin.indices.create.CreateIndexRequest)" is null
|
||||
// FIXME the return value of
|
||||
// "org.opensearch.client.IndicesAdminClient.create(org.opensearch.action.admin.indices.create.CreateIndexRequest)" is null
|
||||
@AwaitsFix(bugUrl = "")
|
||||
public void testPutIndex_IndexDoesNotExist() {
|
||||
// Arrange
|
||||
String indexName = ".agents";
|
||||
CreateIndexResponse createIndexResponse = new CreateIndexResponse(
|
||||
true,
|
||||
true,
|
||||
indexName
|
||||
);
|
||||
CreateIndexResponse createIndexResponse = new CreateIndexResponse(true, true, indexName);
|
||||
|
||||
when(routingTable.hasIndex(indexName)).thenReturn(false);
|
||||
when(indicesAdminClient.create(any(CreateIndexRequest.class)).actionGet())
|
||||
@ -151,7 +149,6 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
assertEquals(indexName, capturedRequest.index());
|
||||
}
|
||||
|
||||
|
||||
public void testPutIndex_IndexExists() {
|
||||
// Arrange
|
||||
String indexName = ".agents";
|
||||
@ -164,7 +161,6 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
verify(indicesAdminClient, never()).create(any(CreateIndexRequest.class));
|
||||
}
|
||||
|
||||
|
||||
public void testIndexExists() {
|
||||
// Arrange
|
||||
String indexName = ".agents";
|
||||
@ -177,7 +173,6 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
assertTrue(exists);
|
||||
}
|
||||
|
||||
|
||||
@AwaitsFix(bugUrl = "")
|
||||
public void testInitialize() throws IOException {
|
||||
// Arrange
|
||||
@ -204,4 +199,3 @@ public class WazuhIndicesTests extends OpenSearchTestCase {
|
||||
verify(indicesAdminClient).create(any(CreateIndexRequest.class));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright OpenSearch Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* The OpenSearch Contributors require contributions made to
|
||||
@ -9,10 +10,10 @@ package com.wazuh.setup;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.opensearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.opensearch.test.rest.yaml.OpenSearchClientYamlSuiteTestCase;
|
||||
|
||||
|
||||
public class SetupPluginClientYamlTestSuiteIT extends OpenSearchClientYamlSuiteTestCase {
|
||||
|
||||
public SetupPluginClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
|
||||
21
scripts/pre-commit
Normal file
21
scripts/pre-commit
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Navigate to the root of the repository
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
# Run spotlessCheck
|
||||
./gradlew spotlessCheck
|
||||
|
||||
# Capture the exit code
|
||||
EXIT_CODE=$?
|
||||
|
||||
if [ $EXIT_CODE -ne 0 ]; then
|
||||
echo "======================================================================================"
|
||||
echo "Spotless found some formatting issues. Please run ./gradlew spotlessApply to fix them."
|
||||
echo "======================================================================================"
|
||||
exit 1
|
||||
else
|
||||
echo "==================================="
|
||||
echo "Spotless check passed successfully!"
|
||||
echo "==================================="
|
||||
fi
|
||||
14
settings.gradle
Normal file
14
settings.gradle
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.10.2/userguide/multi_project_builds.html in the Gradle documentation.
|
||||
*/
|
||||
|
||||
rootProject.name = "wazuh-indexer-plugins"
|
||||
|
||||
include(":setup")
|
||||
project(":setup").projectDir = "plugins/setup/" as File
|
||||
|
||||
include(":command-manager")
|
||||
project(":command-manager").projectDir = "plugins/command-manager/" as File
|
||||
Loading…
x
Reference in New Issue
Block a user