diff --git a/build.gradle b/build.gradle index 863a4ae234..15eaad0803 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ spotless { // non-standard places target '**/com/amazon/dlic/**/*.java' target '**/com/amazon/security/**/*.java' - target '**/test/java/org/opensearch/security/**/*.java' + target '**/test/**/*.java' removeUnusedImports() eclipse().configFile rootProject.file('formatter/formatterConfig.xml') @@ -112,17 +112,11 @@ spotless { target '**/*.java' targetExclude '**/com/amazon/dlic/**/*.java' targetExclude '**/com/amazon/security/**/*.java' - targetExclude '**/test/java/org/opensearch/security/**/*.java' - targetExclude 'src/integrationTest/**' + targetExclude '**/test/**/*.java' trimTrailingWhitespace() endWithNewline(); } - format("integrationTest", JavaExtension) { - target('src/integrationTest/java/**/*.java') - importOrder('java', 'javax', '', 'com.amazon', 'org.opensearch', '\\#') - indentWithTabs(4) - } } licenseFile = rootProject.file('LICENSE.txt') diff --git a/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java b/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java index d3c3658245..59c2a26c03 100644 --- a/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java +++ b/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java @@ -12,15 +12,11 @@ import java.util.Set; import java.util.stream.Collectors; -import com.google.common.collect.ImmutableMap; -import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.opensearch.Version; -import org.opensearch.client.Response; import org.opensearch.common.settings.Settings; -import org.opensearch.rest.RestStatus; import org.opensearch.test.rest.OpenSearchRestTestCase; import static org.hamcrest.MatcherAssert.assertThat; @@ -56,14 +52,13 @@ protected boolean preserveTemplatesUponCompletion() { @Override protected final Settings restClientSettings() { - return Settings - .builder() - .put(super.restClientSettings()) - // increase the timeout here to 90 seconds to handle long waits for a green - // cluster health. the waits for green need to be longer than a minute to - // account for delayed shards - .put(OpenSearchRestTestCase.CLIENT_SOCKET_TIMEOUT, "90s") - .build(); + return Settings.builder() + .put(super.restClientSettings()) + // increase the timeout here to 90 seconds to handle long waits for a green + // cluster health. the waits for green need to be longer than a minute to + // account for delayed shards + .put(OpenSearchRestTestCase.CLIENT_SOCKET_TIMEOUT, "90s") + .build(); } public void testBasicBackwardsCompatibility() throws Exception { diff --git a/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java b/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java index 1599cd2a37..62b0199824 100644 --- a/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java +++ b/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java @@ -33,7 +33,7 @@ import org.opensearch.plugins.Plugin; public class PluginAwareNode extends Node { - + private final boolean clusterManagerEligible; @SafeVarargs @@ -41,7 +41,7 @@ public PluginAwareNode(boolean clusterManagerEligible, final Settings preparedSe super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, Collections.emptyMap(), null, () -> System.getenv("HOSTNAME")), Arrays.asList(plugins), true); this.clusterManagerEligible = clusterManagerEligible; } - + public boolean isClusterManagerEligible() { return clusterManagerEligible; diff --git a/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java b/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java index d93a168341..c25d28ef12 100644 --- a/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java +++ b/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java @@ -47,9 +47,9 @@ public void testSecurityRoles() throws Exception { HttpResponse response = client.getAuthInfo(); response.assertStatusCode(HttpStatus.SC_OK); - // Check username + // Check username assertThat(response.getTextFromJsonBody("/user_name"), equalTo("sr_user")); - + // Check security roles assertThat(response.getTextFromJsonBody("/roles/0"), equalTo("user_sr_user__abc_ber")); assertThat(response.getTextFromJsonBody("/roles/1"), equalTo("user_sr_user__def_efg")); diff --git a/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java b/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java index 244bd6b80e..c17ccb8ea3 100644 --- a/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java +++ b/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java @@ -36,7 +36,7 @@ abstract class CommonProxyAuthenticationTests { protected static final String ATTRIBUTE_DEPARTMENT = "department"; protected static final String ATTRIBUTE_SKILLS = "skills"; - + protected static final String USER_ATTRIBUTE_DEPARTMENT_NAME = "attr.proxy." + ATTRIBUTE_DEPARTMENT; protected static final String USER_ATTRIBUTE_SKILLS_NAME = "attr.proxy." + ATTRIBUTE_SKILLS; protected static final String USER_ATTRIBUTE_USERNAME_NAME = "attr.proxy.username"; @@ -82,7 +82,7 @@ abstract class CommonProxyAuthenticationTests { protected static final RolesMapping ROLES_MAPPING_FIRST_MATE = new RolesMapping(ROLE_ALL_INDEX_SEARCH) .backendRoles(BACKEND_ROLE_FIRST_MATE); - + protected abstract LocalCluster getCluster(); protected void shouldAuthenticateWithBasicAuthWhenProxyAuthenticationIsConfigured() { diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java b/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java index c9d5f8b40a..d75fc0e4e5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java @@ -18,89 +18,90 @@ public class AuditCompliance implements ToXContentObject { - private boolean enabled = false; - - private Boolean writeLogDiffs; - - private List readIgnoreUsers; - - private List writeWatchedIndices; - - private List writeIgnoreUsers; - - private Boolean readMetadataOnly; - - private Boolean writeMetadataOnly; - - private Boolean externalConfig; - - private Boolean internalConfig; - - public AuditCompliance enabled(boolean enabled) { - this.enabled = enabled; - this.writeLogDiffs = false; - this.readIgnoreUsers = Collections.emptyList(); - this.writeWatchedIndices = Collections.emptyList(); - this.writeIgnoreUsers = Collections.emptyList(); - this.readMetadataOnly = false; - this.writeMetadataOnly = false; - this.externalConfig = false; - this.internalConfig = false; - return this; - } - - public AuditCompliance writeLogDiffs(boolean writeLogDiffs) { - this.writeLogDiffs = writeLogDiffs; - return this; - } - - public AuditCompliance readIgnoreUsers(List list) { - this.readIgnoreUsers = list; - return this; - } - - public AuditCompliance writeWatchedIndices(List list) { - this.writeWatchedIndices = list; - return this; - } - - public AuditCompliance writeIgnoreUsers(List list) { - this.writeIgnoreUsers = list; - return this; - } - - public AuditCompliance readMetadataOnly(boolean readMetadataOnly) { - this.readMetadataOnly = readMetadataOnly; - return this; - } - - public AuditCompliance writeMetadataOnly(boolean writeMetadataOnly) { - this.writeMetadataOnly = writeMetadataOnly; - return this; - } - - public AuditCompliance externalConfig(boolean externalConfig) { - this.externalConfig = externalConfig; - return this; - } - - public AuditCompliance internalConfig(boolean internalConfig) { - this.internalConfig = internalConfig; - return this; - } - - @Override public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("enabled", enabled); - xContentBuilder.field("write_log_diffs", writeLogDiffs); - xContentBuilder.field("read_ignore_users", readIgnoreUsers); - xContentBuilder.field("write_watched_indices", writeWatchedIndices); - xContentBuilder.field("write_ignore_users", writeIgnoreUsers); - xContentBuilder.field("read_metadata_only", readMetadataOnly); - xContentBuilder.field("write_metadata_only", writeMetadataOnly); - xContentBuilder.field("external_config", externalConfig); - xContentBuilder.field("internal_config", internalConfig); - xContentBuilder.endObject(); - return xContentBuilder; - } + private boolean enabled = false; + + private Boolean writeLogDiffs; + + private List readIgnoreUsers; + + private List writeWatchedIndices; + + private List writeIgnoreUsers; + + private Boolean readMetadataOnly; + + private Boolean writeMetadataOnly; + + private Boolean externalConfig; + + private Boolean internalConfig; + + public AuditCompliance enabled(boolean enabled) { + this.enabled = enabled; + this.writeLogDiffs = false; + this.readIgnoreUsers = Collections.emptyList(); + this.writeWatchedIndices = Collections.emptyList(); + this.writeIgnoreUsers = Collections.emptyList(); + this.readMetadataOnly = false; + this.writeMetadataOnly = false; + this.externalConfig = false; + this.internalConfig = false; + return this; + } + + public AuditCompliance writeLogDiffs(boolean writeLogDiffs) { + this.writeLogDiffs = writeLogDiffs; + return this; + } + + public AuditCompliance readIgnoreUsers(List list) { + this.readIgnoreUsers = list; + return this; + } + + public AuditCompliance writeWatchedIndices(List list) { + this.writeWatchedIndices = list; + return this; + } + + public AuditCompliance writeIgnoreUsers(List list) { + this.writeIgnoreUsers = list; + return this; + } + + public AuditCompliance readMetadataOnly(boolean readMetadataOnly) { + this.readMetadataOnly = readMetadataOnly; + return this; + } + + public AuditCompliance writeMetadataOnly(boolean writeMetadataOnly) { + this.writeMetadataOnly = writeMetadataOnly; + return this; + } + + public AuditCompliance externalConfig(boolean externalConfig) { + this.externalConfig = externalConfig; + return this; + } + + public AuditCompliance internalConfig(boolean internalConfig) { + this.internalConfig = internalConfig; + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("enabled", enabled); + xContentBuilder.field("write_log_diffs", writeLogDiffs); + xContentBuilder.field("read_ignore_users", readIgnoreUsers); + xContentBuilder.field("write_watched_indices", writeWatchedIndices); + xContentBuilder.field("write_ignore_users", writeIgnoreUsers); + xContentBuilder.field("read_metadata_only", readMetadataOnly); + xContentBuilder.field("write_metadata_only", writeMetadataOnly); + xContentBuilder.field("external_config", externalConfig); + xContentBuilder.field("internal_config", internalConfig); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java b/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java index 783fa19af0..1b3f11cc83 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java @@ -15,41 +15,42 @@ import org.opensearch.core.xcontent.XContentBuilder; public class AuditConfiguration implements ToXContentObject { - private final boolean enabled; + private final boolean enabled; - private AuditFilters filters; + private AuditFilters filters; - private AuditCompliance compliance; + private AuditCompliance compliance; - public AuditConfiguration(boolean enabled) { - this.filters = new AuditFilters(); - this.compliance = new AuditCompliance(); - this.enabled = enabled; - } + public AuditConfiguration(boolean enabled) { + this.filters = new AuditFilters(); + this.compliance = new AuditCompliance(); + this.enabled = enabled; + } - public boolean isEnabled() { - return enabled; - } + public boolean isEnabled() { + return enabled; + } - public AuditConfiguration filters(AuditFilters filters) { - this.filters = filters; - return this; - } + public AuditConfiguration filters(AuditFilters filters) { + this.filters = filters; + return this; + } - public AuditConfiguration compliance(AuditCompliance auditCompliance) { - this.compliance = auditCompliance; - return this; - } + public AuditConfiguration compliance(AuditCompliance auditCompliance) { + this.compliance = auditCompliance; + return this; + } - @Override public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - // json built here must be deserialized to org.opensearch.security.auditlog.config.AuditConfig - xContentBuilder.startObject(); - xContentBuilder.field("enabled", enabled); + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + // json built here must be deserialized to org.opensearch.security.auditlog.config.AuditConfig + xContentBuilder.startObject(); + xContentBuilder.field("enabled", enabled); - xContentBuilder.field("audit", filters); - xContentBuilder.field("compliance", compliance); + xContentBuilder.field("audit", filters); + xContentBuilder.field("compliance", compliance); - xContentBuilder.endObject(); - return xContentBuilder; - } + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java b/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java index bc9f972906..f984becefa 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java @@ -18,104 +18,105 @@ public class AuditFilters implements ToXContentObject { - private Boolean enabledRest; - - private Boolean enabledTransport; - - private Boolean logRequestBody; - - private Boolean resolveIndices; - - private Boolean resolveBulkRequests; - - private Boolean excludeSensitiveHeaders; - - private List ignoreUsers; - - private List ignoreRequests; - - private List disabledRestCategories; - - private List disabledTransportCategories; - - public AuditFilters() { - this.enabledRest = false; - this.enabledTransport = false; - - this.logRequestBody = true; - this.resolveIndices = true; - this.resolveBulkRequests = false; - this.excludeSensitiveHeaders = true; - - this.ignoreUsers = Collections.emptyList(); - this.ignoreRequests = Collections.emptyList(); - this.disabledRestCategories = Collections.emptyList(); - this.disabledTransportCategories = Collections.emptyList(); - } - - public AuditFilters enabledRest(boolean enabled) { - this.enabledRest = enabled; - return this; - } - - public AuditFilters enabledTransport(boolean enabled) { - this.enabledTransport = enabled; - return this; - } - - public AuditFilters logRequestBody(boolean logRequestBody) { - this.logRequestBody = logRequestBody; - return this; - } - - public AuditFilters resolveIndices(boolean resolveIndices) { - this.resolveIndices = resolveIndices; - return this; - } - - public AuditFilters resolveBulkRequests(boolean resolveBulkRequests) { - this.resolveBulkRequests = resolveBulkRequests; - return this; - } - - public AuditFilters excludeSensitiveHeaders(boolean excludeSensitiveHeaders) { - this.excludeSensitiveHeaders = excludeSensitiveHeaders; - return this; - } - - public AuditFilters ignoreUsers(List ignoreUsers) { - this.ignoreUsers = ignoreUsers; - return this; - } - - public AuditFilters ignoreRequests(List ignoreRequests) { - this.ignoreRequests = ignoreRequests; - return this; - } - - public AuditFilters disabledRestCategories(List disabledRestCategories) { - this.disabledRestCategories = disabledRestCategories; - return this; - } - - public AuditFilters disabledTransportCategories(List disabledTransportCategories) { - this.disabledTransportCategories = disabledTransportCategories; - return this; - } - - @Override public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("enable_rest", enabledRest); - xContentBuilder.field("enable_transport", enabledTransport); - xContentBuilder.field("resolve_indices", resolveIndices); - xContentBuilder.field("log_request_body", logRequestBody); - xContentBuilder.field("resolve_bulk_requests", resolveBulkRequests); - xContentBuilder.field("exclude_sensitive_headers", excludeSensitiveHeaders); - xContentBuilder.field("ignore_users", ignoreUsers); - xContentBuilder.field("ignore_requests", ignoreRequests); - xContentBuilder.field("disabled_rest_categories", disabledRestCategories); - xContentBuilder.field("disabled_transport_categories", disabledTransportCategories); - xContentBuilder.endObject(); - return xContentBuilder; - } + private Boolean enabledRest; + + private Boolean enabledTransport; + + private Boolean logRequestBody; + + private Boolean resolveIndices; + + private Boolean resolveBulkRequests; + + private Boolean excludeSensitiveHeaders; + + private List ignoreUsers; + + private List ignoreRequests; + + private List disabledRestCategories; + + private List disabledTransportCategories; + + public AuditFilters() { + this.enabledRest = false; + this.enabledTransport = false; + + this.logRequestBody = true; + this.resolveIndices = true; + this.resolveBulkRequests = false; + this.excludeSensitiveHeaders = true; + + this.ignoreUsers = Collections.emptyList(); + this.ignoreRequests = Collections.emptyList(); + this.disabledRestCategories = Collections.emptyList(); + this.disabledTransportCategories = Collections.emptyList(); + } + + public AuditFilters enabledRest(boolean enabled) { + this.enabledRest = enabled; + return this; + } + + public AuditFilters enabledTransport(boolean enabled) { + this.enabledTransport = enabled; + return this; + } + + public AuditFilters logRequestBody(boolean logRequestBody) { + this.logRequestBody = logRequestBody; + return this; + } + + public AuditFilters resolveIndices(boolean resolveIndices) { + this.resolveIndices = resolveIndices; + return this; + } + + public AuditFilters resolveBulkRequests(boolean resolveBulkRequests) { + this.resolveBulkRequests = resolveBulkRequests; + return this; + } + + public AuditFilters excludeSensitiveHeaders(boolean excludeSensitiveHeaders) { + this.excludeSensitiveHeaders = excludeSensitiveHeaders; + return this; + } + + public AuditFilters ignoreUsers(List ignoreUsers) { + this.ignoreUsers = ignoreUsers; + return this; + } + + public AuditFilters ignoreRequests(List ignoreRequests) { + this.ignoreRequests = ignoreRequests; + return this; + } + + public AuditFilters disabledRestCategories(List disabledRestCategories) { + this.disabledRestCategories = disabledRestCategories; + return this; + } + + public AuditFilters disabledTransportCategories(List disabledTransportCategories) { + this.disabledTransportCategories = disabledTransportCategories; + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("enable_rest", enabledRest); + xContentBuilder.field("enable_transport", enabledTransport); + xContentBuilder.field("resolve_indices", resolveIndices); + xContentBuilder.field("log_request_body", logRequestBody); + xContentBuilder.field("resolve_bulk_requests", resolveBulkRequests); + xContentBuilder.field("exclude_sensitive_headers", excludeSensitiveHeaders); + xContentBuilder.field("ignore_users", ignoreUsers); + xContentBuilder.field("ignore_requests", ignoreRequests); + xContentBuilder.field("disabled_rest_categories", disabledRestCategories); + xContentBuilder.field("disabled_transport_categories", disabledTransportCategories); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java b/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java index 5d467bd754..472d3d8d08 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java @@ -19,21 +19,21 @@ public class AuthFailureListeners implements ToXContentObject { - private Map limits = new LinkedHashMap<>(); + private Map limits = new LinkedHashMap<>(); - public AuthFailureListeners addRateLimit(RateLimiting rateLimiting) { - Objects.requireNonNull(rateLimiting, "Rate limiting is required"); - limits.put(rateLimiting.getName(), rateLimiting); - return this; - } + public AuthFailureListeners addRateLimit(RateLimiting rateLimiting) { + Objects.requireNonNull(rateLimiting, "Rate limiting is required"); + limits.put(rateLimiting.getName(), rateLimiting); + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - for(Map.Entry entry : limits.entrySet()) { - xContentBuilder.field(entry.getKey(), entry.getValue()); - } - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + for (Map.Entry entry : limits.entrySet()) { + xContentBuilder.field(entry.getKey(), entry.getValue()); + } + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java b/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java index 2d9d1c1b66..521d35ed46 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java @@ -18,28 +18,28 @@ import org.opensearch.core.xcontent.XContentBuilder; public class AuthorizationBackend implements ToXContentObject { - private final String type; - private Supplier> config; + private final String type; + private Supplier> config; - public AuthorizationBackend(String type) { - this.type = type; - } + public AuthorizationBackend(String type) { + this.type = type; + } - public AuthorizationBackend config(Map ldapConfig) { - return config(() -> ldapConfig); - } + public AuthorizationBackend config(Map ldapConfig) { + return config(() -> ldapConfig); + } - public AuthorizationBackend config(Supplier> ldapConfigSupplier) { - this.config = Objects.requireNonNull(ldapConfigSupplier, "Configuration supplier is required"); - return this; - } + public AuthorizationBackend config(Supplier> ldapConfigSupplier) { + this.config = Objects.requireNonNull(ldapConfigSupplier, "Configuration supplier is required"); + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("type", type); - xContentBuilder.field("config", config.get()); - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("type", type); + xContentBuilder.field("config", config.get()); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java b/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java index 7d611881e0..5ccf1f9ee0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java @@ -19,52 +19,52 @@ */ public class AuthzDomain implements ToXContentObject { - private final String id; + private final String id; - private String description; + private String description; - private boolean httpEnabled; + private boolean httpEnabled; - private boolean transportEnabled; + private boolean transportEnabled; - private AuthorizationBackend authorizationBackend; + private AuthorizationBackend authorizationBackend; - public AuthzDomain(String id) { - this.id = id; - } + public AuthzDomain(String id) { + this.id = id; + } - public String getId() { - return id; - } + public String getId() { + return id; + } - public AuthzDomain description(String description) { - this.description = description; - return this; - } + public AuthzDomain description(String description) { + this.description = description; + return this; + } - public AuthzDomain httpEnabled(boolean httpEnabled) { - this.httpEnabled = httpEnabled; - return this; - } + public AuthzDomain httpEnabled(boolean httpEnabled) { + this.httpEnabled = httpEnabled; + return this; + } - public AuthzDomain authorizationBackend(AuthorizationBackend authorizationBackend) { - this.authorizationBackend = authorizationBackend; - return this; - } + public AuthzDomain authorizationBackend(AuthorizationBackend authorizationBackend) { + this.authorizationBackend = authorizationBackend; + return this; + } - public AuthzDomain transportEnabled(boolean transportEnabled) { - this.transportEnabled = transportEnabled; - return this; - } + public AuthzDomain transportEnabled(boolean transportEnabled) { + this.transportEnabled = transportEnabled; + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("description", description); - xContentBuilder.field("http_enabled", httpEnabled); - xContentBuilder.field("transport_enabled", transportEnabled); - xContentBuilder.field("authorization_backend", authorizationBackend); - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("description", description); + xContentBuilder.field("http_enabled", httpEnabled); + xContentBuilder.field("transport_enabled", transportEnabled); + xContentBuilder.field("authorization_backend", authorizationBackend); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java index 5b1ea2c678..48dfa128e0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java @@ -17,46 +17,46 @@ import static org.apache.commons.lang3.StringUtils.isNoneBlank; public class JwtConfigBuilder { - private String jwtHeader; - private String signingKey; - private String subjectKey; - private String rolesKey; - - public JwtConfigBuilder jwtHeader(String jwtHeader) { - this.jwtHeader = jwtHeader; - return this; - } - - public JwtConfigBuilder signingKey(String signingKey) { - this.signingKey = signingKey; - return this; - } - - public JwtConfigBuilder subjectKey(String subjectKey) { - this.subjectKey = subjectKey; - return this; - } - - public JwtConfigBuilder rolesKey(String rolesKey) { - this.rolesKey = rolesKey; - return this; - } - - public Map build() { - Builder builder = new Builder<>(); - if(Objects.isNull(signingKey)) { - throw new IllegalStateException("Signing key is required."); - } - builder.put("signing_key", signingKey); - if(isNoneBlank(jwtHeader)) { - builder.put("jwt_header", jwtHeader); - } - if(isNoneBlank(subjectKey)) { - builder.put("subject_key", subjectKey); - } - if(isNoneBlank(rolesKey)) { - builder.put("roles_key", rolesKey); - } - return builder.build(); - } + private String jwtHeader; + private String signingKey; + private String subjectKey; + private String rolesKey; + + public JwtConfigBuilder jwtHeader(String jwtHeader) { + this.jwtHeader = jwtHeader; + return this; + } + + public JwtConfigBuilder signingKey(String signingKey) { + this.signingKey = signingKey; + return this; + } + + public JwtConfigBuilder subjectKey(String subjectKey) { + this.subjectKey = subjectKey; + return this; + } + + public JwtConfigBuilder rolesKey(String rolesKey) { + this.rolesKey = rolesKey; + return this; + } + + public Map build() { + Builder builder = new Builder<>(); + if (Objects.isNull(signingKey)) { + throw new IllegalStateException("Signing key is required."); + } + builder.put("signing_key", signingKey); + if (isNoneBlank(jwtHeader)) { + builder.put("jwt_header", jwtHeader); + } + if (isNoneBlank(subjectKey)) { + builder.put("subject_key", subjectKey); + } + if (isNoneBlank(rolesKey)) { + builder.put("roles_key", rolesKey); + } + return builder.build(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java index b6519f7b87..07f1836b59 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java @@ -20,100 +20,100 @@ * {@link LdapAuthorizationConfigBuilder} */ public class LdapAuthenticationConfigBuilder { - private boolean enableSsl = false; - private boolean enableStartTls = false; - private boolean enableSslClientAuth = false; - private boolean verifyHostnames = false; - private List hosts; - private String bindDn; - private String password; - private String userBase; - private String userSearch; - private String usernameAttribute; - - private String penTrustedCasFilePath; - - /** - * Subclass of this - */ - private final T builderSubclass; - - protected LdapAuthenticationConfigBuilder(Function thisCastFunction) { - this.builderSubclass = thisCastFunction.apply(this); - } - - public static LdapAuthenticationConfigBuilder config() { - return new LdapAuthenticationConfigBuilder<>(Function.identity()); - } - - public T enableSsl(boolean enableSsl) { - this.enableSsl = enableSsl; - return builderSubclass; - } - - public T enableStartTls(boolean enableStartTls) { - this.enableStartTls = enableStartTls; - return builderSubclass; - } - - public T enableSslClientAuth(boolean enableSslClientAuth) { - this.enableSslClientAuth = enableSslClientAuth; - return builderSubclass; - } - - public T verifyHostnames(boolean verifyHostnames) { - this.verifyHostnames = verifyHostnames; - return builderSubclass; - } - - public T hosts(List hosts) { - this.hosts = hosts; - return builderSubclass; - } - - public T bindDn(String bindDn) { - this.bindDn = bindDn; - return builderSubclass; - } - - public T password(String password) { - this.password = password; - return builderSubclass; - } - - public T userBase(String userBase) { - this.userBase = userBase; - return builderSubclass; - } - - public T userSearch(String userSearch) { - this.userSearch = userSearch; - return builderSubclass; - } - - public T usernameAttribute(String usernameAttribute) { - this.usernameAttribute = usernameAttribute; - return builderSubclass; - } - - public T penTrustedCasFilePath(String penTrustedCasFilePath) { - this.penTrustedCasFilePath = penTrustedCasFilePath; - return builderSubclass; - } - - public Map build() { - HashMap config = new HashMap<>(); - config.put("enable_ssl", enableSsl); - config.put("enable_start_tls", enableStartTls); - config.put("enable_ssl_client_auth", enableSslClientAuth); - config.put("verify_hostnames", verifyHostnames); - config.put("hosts", hosts); - config.put("bind_dn", bindDn); - config.put("password", password); - config.put("userbase", userBase); - config.put("usersearch", userSearch); - config.put("username_attribute", usernameAttribute); - config.put("pemtrustedcas_filepath", penTrustedCasFilePath); - return config; - } + private boolean enableSsl = false; + private boolean enableStartTls = false; + private boolean enableSslClientAuth = false; + private boolean verifyHostnames = false; + private List hosts; + private String bindDn; + private String password; + private String userBase; + private String userSearch; + private String usernameAttribute; + + private String penTrustedCasFilePath; + + /** + * Subclass of this + */ + private final T builderSubclass; + + protected LdapAuthenticationConfigBuilder(Function thisCastFunction) { + this.builderSubclass = thisCastFunction.apply(this); + } + + public static LdapAuthenticationConfigBuilder config() { + return new LdapAuthenticationConfigBuilder<>(Function.identity()); + } + + public T enableSsl(boolean enableSsl) { + this.enableSsl = enableSsl; + return builderSubclass; + } + + public T enableStartTls(boolean enableStartTls) { + this.enableStartTls = enableStartTls; + return builderSubclass; + } + + public T enableSslClientAuth(boolean enableSslClientAuth) { + this.enableSslClientAuth = enableSslClientAuth; + return builderSubclass; + } + + public T verifyHostnames(boolean verifyHostnames) { + this.verifyHostnames = verifyHostnames; + return builderSubclass; + } + + public T hosts(List hosts) { + this.hosts = hosts; + return builderSubclass; + } + + public T bindDn(String bindDn) { + this.bindDn = bindDn; + return builderSubclass; + } + + public T password(String password) { + this.password = password; + return builderSubclass; + } + + public T userBase(String userBase) { + this.userBase = userBase; + return builderSubclass; + } + + public T userSearch(String userSearch) { + this.userSearch = userSearch; + return builderSubclass; + } + + public T usernameAttribute(String usernameAttribute) { + this.usernameAttribute = usernameAttribute; + return builderSubclass; + } + + public T penTrustedCasFilePath(String penTrustedCasFilePath) { + this.penTrustedCasFilePath = penTrustedCasFilePath; + return builderSubclass; + } + + public Map build() { + HashMap config = new HashMap<>(); + config.put("enable_ssl", enableSsl); + config.put("enable_start_tls", enableStartTls); + config.put("enable_ssl_client_auth", enableSslClientAuth); + config.put("verify_hostnames", verifyHostnames); + config.put("hosts", hosts); + config.put("bind_dn", bindDn); + config.put("password", password); + config.put("userbase", userBase); + config.put("usersearch", userSearch); + config.put("username_attribute", usernameAttribute); + config.put("pemtrustedcas_filepath", penTrustedCasFilePath); + return config; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java index 43611d8d08..9f2a0abd83 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java @@ -13,63 +13,63 @@ import java.util.Map; public class LdapAuthorizationConfigBuilder extends LdapAuthenticationConfigBuilder { - private List skipUsers; - private String roleBase; - private String roleSearch; - private String userRoleAttribute; - private String userRoleName; - private String roleName; - private boolean resolveNestedRoles; + private List skipUsers; + private String roleBase; + private String roleSearch; + private String userRoleAttribute; + private String userRoleName; + private String roleName; + private boolean resolveNestedRoles; - public LdapAuthorizationConfigBuilder() { - super(LdapAuthorizationConfigBuilder.class::cast); - } + public LdapAuthorizationConfigBuilder() { + super(LdapAuthorizationConfigBuilder.class::cast); + } - public LdapAuthorizationConfigBuilder skipUsers(List skipUsers) { - this.skipUsers = skipUsers; - return this; - } + public LdapAuthorizationConfigBuilder skipUsers(List skipUsers) { + this.skipUsers = skipUsers; + return this; + } - public LdapAuthorizationConfigBuilder roleBase(String roleBase) { - this.roleBase = roleBase; - return this; - } + public LdapAuthorizationConfigBuilder roleBase(String roleBase) { + this.roleBase = roleBase; + return this; + } - public LdapAuthorizationConfigBuilder roleSearch(String roleSearch) { - this.roleSearch = roleSearch; - return this; - } + public LdapAuthorizationConfigBuilder roleSearch(String roleSearch) { + this.roleSearch = roleSearch; + return this; + } - public LdapAuthorizationConfigBuilder userRoleAttribute(String userRoleAttribute) { - this.userRoleAttribute = userRoleAttribute; - return this; - } + public LdapAuthorizationConfigBuilder userRoleAttribute(String userRoleAttribute) { + this.userRoleAttribute = userRoleAttribute; + return this; + } - public LdapAuthorizationConfigBuilder userRoleName(String userRoleName) { - this.userRoleName = userRoleName; - return this; - } + public LdapAuthorizationConfigBuilder userRoleName(String userRoleName) { + this.userRoleName = userRoleName; + return this; + } - public LdapAuthorizationConfigBuilder roleName(String roleName) { - this.roleName = roleName; - return this; - } + public LdapAuthorizationConfigBuilder roleName(String roleName) { + this.roleName = roleName; + return this; + } - public LdapAuthorizationConfigBuilder resolveNestedRoles(boolean resolveNestedRoles) { - this.resolveNestedRoles = resolveNestedRoles; - return this; - } + public LdapAuthorizationConfigBuilder resolveNestedRoles(boolean resolveNestedRoles) { + this.resolveNestedRoles = resolveNestedRoles; + return this; + } - @Override - public Map build() { - Map map = super.build(); - map.put("skip_users", skipUsers); - map.put("rolebase", roleBase); - map.put("rolesearch", roleSearch); - map.put("userroleattribute", userRoleAttribute); - map.put("userrolename", userRoleName); - map.put("rolename", roleName); - map.put("resolve_nested_roles", resolveNestedRoles); - return map; - } + @Override + public Map build() { + Map map = super.build(); + map.put("skip_users", skipUsers); + map.put("rolebase", roleBase); + map.put("rolesearch", roleSearch); + map.put("userroleattribute", userRoleAttribute); + map.put("userrolename", userRoleName); + map.put("rolename", roleName); + map.put("resolve_nested_roles", resolveNestedRoles); + return map; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java b/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java index b41c6f8f1d..bd38aac1e5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java +++ b/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java @@ -17,69 +17,69 @@ public class RateLimiting implements ToXContentObject { - private final String name; - private String type; - private String authenticationBackend; - private Integer allowedTries; - private Integer timeWindowSeconds; - private Integer blockExpirySeconds; - private Integer maxBlockedClients; - private Integer maxTrackedClients; + private final String name; + private String type; + private String authenticationBackend; + private Integer allowedTries; + private Integer timeWindowSeconds; + private Integer blockExpirySeconds; + private Integer maxBlockedClients; + private Integer maxTrackedClients; - public String getName() { - return name; - } + public String getName() { + return name; + } - public RateLimiting(String name) { - this.name = Objects.requireNonNull(name, "Rate limit name is required."); - } + public RateLimiting(String name) { + this.name = Objects.requireNonNull(name, "Rate limit name is required."); + } - public RateLimiting type(String type) { - this.type = type; - return this; - } + public RateLimiting type(String type) { + this.type = type; + return this; + } - public RateLimiting authenticationBackend(String authenticationBackend) { - this.authenticationBackend = authenticationBackend; - return this; - } + public RateLimiting authenticationBackend(String authenticationBackend) { + this.authenticationBackend = authenticationBackend; + return this; + } - public RateLimiting allowedTries(Integer allowedTries) { - this.allowedTries = allowedTries; - return this; - } + public RateLimiting allowedTries(Integer allowedTries) { + this.allowedTries = allowedTries; + return this; + } - public RateLimiting timeWindowSeconds(Integer timeWindowSeconds) { - this.timeWindowSeconds = timeWindowSeconds; - return this; - } + public RateLimiting timeWindowSeconds(Integer timeWindowSeconds) { + this.timeWindowSeconds = timeWindowSeconds; + return this; + } - public RateLimiting blockExpirySeconds(Integer blockExpirySeconds) { - this.blockExpirySeconds = blockExpirySeconds; - return this; - } + public RateLimiting blockExpirySeconds(Integer blockExpirySeconds) { + this.blockExpirySeconds = blockExpirySeconds; + return this; + } - public RateLimiting maxBlockedClients(Integer maxBlockedClients) { - this.maxBlockedClients = maxBlockedClients; - return this; - } + public RateLimiting maxBlockedClients(Integer maxBlockedClients) { + this.maxBlockedClients = maxBlockedClients; + return this; + } - public RateLimiting maxTrackedClients(Integer maxTrackedClients) { - this.maxTrackedClients = maxTrackedClients; - return this; - } + public RateLimiting maxTrackedClients(Integer maxTrackedClients) { + this.maxTrackedClients = maxTrackedClients; + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("type", type); - xContentBuilder.field("authentication_backend", authenticationBackend); - xContentBuilder.field("allowed_tries", allowedTries); - xContentBuilder.field("time_window_seconds", timeWindowSeconds); - xContentBuilder.field("block_expiry_seconds", blockExpirySeconds); - xContentBuilder.field("max_blocked_clients", maxBlockedClients); - xContentBuilder.field("max_tracked_clients", maxTrackedClients); - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("type", type); + xContentBuilder.field("authentication_backend", authenticationBackend); + xContentBuilder.field("allowed_tries", allowedTries); + xContentBuilder.field("time_window_seconds", timeWindowSeconds); + xContentBuilder.field("block_expiry_seconds", blockExpirySeconds); + xContentBuilder.field("max_blocked_clients", maxBlockedClients); + xContentBuilder.field("max_tracked_clients", maxTrackedClients); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java b/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java index a0f048f953..75c0325474 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java +++ b/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java @@ -27,71 +27,69 @@ */ public class RolesMapping implements ToXContentObject { - /** - * OpenSearch role name - */ - private String roleName; + /** + * OpenSearch role name + */ + private String roleName; - /** - * Backend role names - */ - private List backendRoles; + /** + * Backend role names + */ + private List backendRoles; - private boolean reserved = false; + private boolean reserved = false; - /** - * Creates roles mapping to OpenSearch role defined by parameter role - * @param role OpenSearch role, must not be null. - */ - public RolesMapping(Role role) { - requireNonNull(role); - this.roleName = requireNonNull(role.getName()); - this.backendRoles = new ArrayList<>(); - } + /** + * Creates roles mapping to OpenSearch role defined by parameter role + * @param role OpenSearch role, must not be null. + */ + public RolesMapping(Role role) { + requireNonNull(role); + this.roleName = requireNonNull(role.getName()); + this.backendRoles = new ArrayList<>(); + } + /** + * Defines backend role names + * @param backendRoles backend roles names + * @return current {@link RolesMapping} instance + */ + public RolesMapping backendRoles(String... backendRoles) { + this.backendRoles.addAll(Arrays.asList(backendRoles)); + return this; + } - /** - * Defines backend role names - * @param backendRoles backend roles names - * @return current {@link RolesMapping} instance - */ - public RolesMapping backendRoles(String...backendRoles) { - this.backendRoles.addAll(Arrays.asList(backendRoles)); - return this; - } + /** + * Determines if role is reserved + * @param reserved true for reserved roles + * @return current {@link RolesMapping} instance + */ + public RolesMapping reserved(boolean reserved) { + this.reserved = reserved; + return this; + } - /** - * Determines if role is reserved - * @param reserved true for reserved roles - * @return current {@link RolesMapping} instance - */ - public RolesMapping reserved(boolean reserved) { - this.reserved = reserved; - return this; - } + /** + * Returns OpenSearch role name + * @return role name + */ + public String getRoleName() { + return roleName; + } - - /** - * Returns OpenSearch role name - * @return role name - */ - public String getRoleName() { - return roleName; - } - - /** - * Controls serialization to JSON - * @param xContentBuilder must not be null - * @param params not used parameter, but required by the interface {@link ToXContentObject} - * @return builder form parameter xContentBuilder - * @throws IOException denotes error during serialization to JSON - */ - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("reserved", reserved); - xContentBuilder.field("backend_roles", backendRoles); - xContentBuilder.endObject(); - return xContentBuilder; - } + /** + * Controls serialization to JSON + * @param xContentBuilder must not be null + * @param params not used parameter, but required by the interface {@link ToXContentObject} + * @return builder form parameter xContentBuilder + * @throws IOException denotes error during serialization to JSON + */ + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("reserved", reserved); + xContentBuilder.field("backend_roles", backendRoles); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java b/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java index 9d5feb9eee..6f6bd935a5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java +++ b/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java @@ -34,51 +34,50 @@ public class TestIndex { - private final String name; - private final Settings settings; - - public TestIndex(String name, Settings settings) { - this.name = name; - this.settings = settings; - - } - - public void create(Client client) { - client.admin().indices().create(new CreateIndexRequest(name).settings(settings)).actionGet(); - } - - public String getName() { - return name; - } - - - public static Builder name(String name) { - return new Builder().name(name); - } - - public static class Builder { - private String name; - private Settings.Builder settings = Settings.builder(); - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder setting(String name, int value) { - settings.put(name, value); - return this; - } - - public Builder shards(int value) { - settings.put("index.number_of_shards", 5); - return this; - } - - public TestIndex build() { - return new TestIndex(name, settings.build()); - } - - } + private final String name; + private final Settings settings; + + public TestIndex(String name, Settings settings) { + this.name = name; + this.settings = settings; + + } + + public void create(Client client) { + client.admin().indices().create(new CreateIndexRequest(name).settings(settings)).actionGet(); + } + + public String getName() { + return name; + } + + public static Builder name(String name) { + return new Builder().name(name); + } + + public static class Builder { + private String name; + private Settings.Builder settings = Settings.builder(); + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder setting(String name, int value) { + settings.put(name, value); + return this; + } + + public Builder shards(int value) { + settings.put("index.number_of_shards", 5); + return this; + } + + public TestIndex build() { + return new TestIndex(name, settings.build()); + } + + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java b/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java index 43b98b02ce..a702102e6b 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java +++ b/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java @@ -76,630 +76,642 @@ */ public class TestSecurityConfig { - private static final Logger log = LogManager.getLogger(TestSecurityConfig.class); - - private Config config = new Config(); - private Map internalUsers = new LinkedHashMap<>(); - private Map roles = new LinkedHashMap<>(); - private AuditConfiguration auditConfiguration; - private Map rolesMapping = new LinkedHashMap<>(); - - private String indexName = ".opendistro_security"; - - public TestSecurityConfig() { - - } - - public TestSecurityConfig configIndexName(String configIndexName) { - this.indexName = configIndexName; - return this; - } - - public TestSecurityConfig authFailureListeners(AuthFailureListeners listener) { - config.authFailureListeners(listener); - return this; - } - - public TestSecurityConfig anonymousAuth(boolean anonymousAuthEnabled) { - config.anonymousAuth(anonymousAuthEnabled); - return this; - } - - public TestSecurityConfig doNotFailOnForbidden(boolean doNotFailOnForbidden) { - config.doNotFailOnForbidden(doNotFailOnForbidden); - return this; - } - - public TestSecurityConfig xff(XffConfig xffConfig) { - config.xffConfig(xffConfig); - return this; - } - - public TestSecurityConfig authc(AuthcDomain authcDomain) { - config.authc(authcDomain); - return this; - } - - public TestSecurityConfig authz(AuthzDomain authzDomain) { - config.authz(authzDomain); - return this; - } - public TestSecurityConfig user(User user) { - this.internalUsers.put(user.name, user); - - for (Role role : user.roles) { - this.roles.put(role.name, role); - } - - return this; - } - - public List getUsers() { - return new ArrayList<>(internalUsers.values()); - } - - public TestSecurityConfig roles(Role... roles) { - for (Role role : roles) { - if(this.roles.containsKey(role.name)) { - throw new IllegalStateException("Role with name " + role.name + " is already defined"); - } - this.roles.put(role.name, role); - } - - return this; - } - - public TestSecurityConfig audit(AuditConfiguration auditConfiguration) { - this.auditConfiguration = auditConfiguration; - return this; - } - - public TestSecurityConfig rolesMapping(RolesMapping...mappings) { - for (RolesMapping mapping : mappings) { - String roleName = mapping.getRoleName(); - if(rolesMapping.containsKey(roleName)) { - throw new IllegalArgumentException("Role mapping " + roleName + " already exists"); - } - this.rolesMapping.put(roleName, mapping); - } - return this; - } - - public static class Config implements ToXContentObject { - private boolean anonymousAuth; - - private Boolean doNotFailOnForbidden; - private XffConfig xffConfig; - private Map authcDomainMap = new LinkedHashMap<>(); - - private AuthFailureListeners authFailureListeners; - private Map authzDomainMap = new LinkedHashMap<>(); - - public Config anonymousAuth(boolean anonymousAuth) { - this.anonymousAuth = anonymousAuth; - return this; - } - - public Config doNotFailOnForbidden(Boolean doNotFailOnForbidden) { - this.doNotFailOnForbidden = doNotFailOnForbidden; - return this; - } - - public Config xffConfig(XffConfig xffConfig) { - this.xffConfig = xffConfig; - return this; - } - - public Config authc(AuthcDomain authcDomain) { - authcDomainMap.put(authcDomain.id, authcDomain); - return this; - } - - public Config authFailureListeners(AuthFailureListeners authFailureListeners) { - this.authFailureListeners = authFailureListeners; - return this; - } - - public Config authz(AuthzDomain authzDomain) { - authzDomainMap.put(authzDomain.getId(), authzDomain); - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.startObject("dynamic"); - - if (anonymousAuth || (xffConfig != null)) { - xContentBuilder.startObject("http"); - xContentBuilder.field("anonymous_auth_enabled", anonymousAuth); - if(xffConfig != null) { - xContentBuilder.field("xff", xffConfig); - } - xContentBuilder.endObject(); - } - if(doNotFailOnForbidden != null) { - xContentBuilder.field("do_not_fail_on_forbidden", doNotFailOnForbidden); - } - - xContentBuilder.field("authc", authcDomainMap); - if(authzDomainMap.isEmpty() == false) { - xContentBuilder.field("authz", authzDomainMap); - } - - if(authFailureListeners != null) { - xContentBuilder.field("auth_failure_listeners", authFailureListeners); - } - - xContentBuilder.endObject(); - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class User implements UserCredentialsHolder, ToXContentObject { - - public final static TestSecurityConfig.User USER_ADMIN = new TestSecurityConfig.User("admin") - .roles(new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*")); - - String name; - private String password; - List roles = new ArrayList<>(); - private Map attributes = new HashMap<>(); - - public User(String name) { - this.name = name; - this.password = "secret"; - } - - public User password(String password) { - this.password = password; - return this; - } - - public User roles(Role... roles) { - // We scope the role names by user to keep tests free of potential side effects - String roleNamePrefix = "user_" + this.getName() + "__"; - this.roles.addAll(Arrays.asList(roles).stream().map((r) -> r.clone().name(roleNamePrefix + r.getName())).collect(Collectors.toSet())); - return this; - } - - public User attr(String key, Object value) { - this.attributes.put(key, value); - return this; - } - - public String getName() { - return name; - } - - public String getPassword() { - return password; - } - - public Set getRoleNames() { - return roles.stream().map(Role::getName).collect(Collectors.toSet()); - } - - public Object getAttribute(String attributeName) { - return attributes.get(attributeName); - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("hash", hash(password.toCharArray())); - - Set roleNames = getRoleNames(); - - if (!roleNames.isEmpty()) { - xContentBuilder.field("opendistro_security_roles", roleNames); - } - - if (attributes != null && attributes.size() != 0) { - xContentBuilder.field("attributes", attributes); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class Role implements ToXContentObject { - public static Role ALL_ACCESS = new Role("all_access").clusterPermissions("*").indexPermissions("*").on("*"); - - private String name; - private List clusterPermissions = new ArrayList<>(); - - private List indexPermissions = new ArrayList<>(); - - public Role(String name) { - this.name = name; - } - - public Role clusterPermissions(String... clusterPermissions) { - this.clusterPermissions.addAll(Arrays.asList(clusterPermissions)); - return this; - } - - public IndexPermission indexPermissions(String... indexPermissions) { - return new IndexPermission(this, indexPermissions); - } - - public Role name(String name) { - this.name = name; - return this; - } - - public String getName() { - return name; - } - - public Role clone() { - Role role = new Role(this.name); - role.clusterPermissions.addAll(this.clusterPermissions); - role.indexPermissions.addAll(this.indexPermissions); - return role; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - if (!clusterPermissions.isEmpty()) { - xContentBuilder.field("cluster_permissions", clusterPermissions); - } - - if (!indexPermissions.isEmpty()) { - xContentBuilder.field("index_permissions", indexPermissions); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class IndexPermission implements ToXContentObject { - private List allowedActions; - private List indexPatterns; - private Role role; - private String dlsQuery; - private List fls; - private List maskedFields; - - IndexPermission(Role role, String... allowedActions) { - this.allowedActions = Arrays.asList(allowedActions); - this.role = role; - } - - public IndexPermission dls(String dlsQuery) { - this.dlsQuery = dlsQuery; - return this; - } - - public IndexPermission fls(String... fls) { - this.fls = Arrays.asList(fls); - return this; - } - - public IndexPermission maskedFields(String... maskedFields) { - this.maskedFields = Arrays.asList(maskedFields); - return this; - } - - public Role on(String... indexPatterns) { - this.indexPatterns = Arrays.asList(indexPatterns); - this.role.indexPermissions.add(this); - return this.role; - } - - public Role on(TestIndex... testindices) { - this.indexPatterns = Arrays.asList(testindices).stream().map(TestIndex::getName).collect(Collectors.toList()); - this.role.indexPermissions.add(this); - return this.role; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("index_patterns", indexPatterns); - xContentBuilder.field("allowed_actions", allowedActions); - - if (dlsQuery != null) { - xContentBuilder.field("dls", dlsQuery); - } - - if (fls != null) { - xContentBuilder.field("fls", fls); - } - - if (maskedFields != null) { - xContentBuilder.field("masked_fields", maskedFields); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class AuthcDomain implements ToXContentObject { - - private static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoqZbjLUAWc+DZTkinQAdvy1GFjPHPnxheU89hSiWoDD3NOW76H3u3T7cCDdOah2msdxSlBmCBH6wik8qLYkcV8owWukQg3PQmbEhrdPaKo0QCgomWs4nLgtmEYqcZ+QQldd82MdTlQ1QmoQmI9Uxqs1SuaKZASp3Gy19y8su5CV+FZ6BruUw9HELK055sAwl3X7j5ouabXGbcib2goBF3P52LkvbJLuWr5HDZEOeSkwIeqSeMojASM96K5SdotD+HwEyjaTjzRPL2Aa1BEQFWOQ6CFJLyLH7ZStDuPM1mJU1VxIVfMbZrhsUBjAnIhRynmWxML7YlNqkP9j6jyOIYQIDAQAB"; - - public static final int BASIC_AUTH_DOMAIN_ORDER = 0; - public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig.AuthcDomain("basic", BASIC_AUTH_DOMAIN_ORDER) - .httpAuthenticatorWithChallenge("basic").backend("internal"); - - public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL_WITHOUT_CHALLENGE = new TestSecurityConfig.AuthcDomain("basic", - BASIC_AUTH_DOMAIN_ORDER) - .httpAuthenticator("basic").backend("internal"); - - public final static AuthcDomain DISABLED_AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig - .AuthcDomain("basic", BASIC_AUTH_DOMAIN_ORDER, false).httpAuthenticator("basic").backend("internal"); - - public final static AuthcDomain JWT_AUTH_DOMAIN = new TestSecurityConfig - .AuthcDomain("jwt", 1) - .jwtHttpAuthenticator(new JwtConfigBuilder().jwtHeader(AUTHORIZATION).signingKey(PUBLIC_KEY)).backend("noop"); - - private final String id; - private boolean enabled = true; - private int order; - private List skipUsers = new ArrayList<>(); - private HttpAuthenticator httpAuthenticator; - private AuthenticationBackend authenticationBackend; - - public AuthcDomain(String id, int order, boolean enabled) { - this.id = id; - this.order = order; - this.enabled = enabled; - } - - public AuthcDomain(String id, int order) { - this(id, order, true); - } - - public AuthcDomain httpAuthenticator(String type) { - this.httpAuthenticator = new HttpAuthenticator(type); - return this; - } - - public AuthcDomain jwtHttpAuthenticator(JwtConfigBuilder builder) { - this.httpAuthenticator = new HttpAuthenticator("jwt") - .challenge(false).config(builder.build()); - return this; - } - - public AuthcDomain httpAuthenticatorWithChallenge(String type) { - this.httpAuthenticator = new HttpAuthenticator(type).challenge(true); - return this; - } - - public AuthcDomain httpAuthenticator(HttpAuthenticator httpAuthenticator) { - this.httpAuthenticator = httpAuthenticator; - return this; - } - - public AuthcDomain backend(String type) { - this.authenticationBackend = new AuthenticationBackend(type); - return this; - } - - public AuthcDomain backend(AuthenticationBackend authenticationBackend) { - this.authenticationBackend = authenticationBackend; - return this; - } - - public AuthcDomain skipUsers(String... users) { - this.skipUsers.addAll(Arrays.asList(users)); - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("http_enabled", enabled); - xContentBuilder.field("order", order); - - if (httpAuthenticator != null) { - xContentBuilder.field("http_authenticator", httpAuthenticator); - } - - if (authenticationBackend != null) { - xContentBuilder.field("authentication_backend", authenticationBackend); - } - - if (skipUsers != null && skipUsers.size() > 0) { - xContentBuilder.field("skip_users", skipUsers); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - - public static class HttpAuthenticator implements ToXContentObject { - private final String type; - private boolean challenge; - private Map config = new HashMap(); - - public HttpAuthenticator(String type) { - this.type = type; - } - - public HttpAuthenticator challenge(boolean challenge) { - this.challenge = challenge; - return this; - } - - public HttpAuthenticator config(Map config) { - this.config.putAll(config); - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("type", type); - xContentBuilder.field("challenge", challenge); - xContentBuilder.field("config", config); - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class AuthenticationBackend implements ToXContentObject { - private final String type; - private Supplier> config = () -> new HashMap(); - - public AuthenticationBackend(String type) { - this.type = type; - } - - public AuthenticationBackend config(Map config) { - Map configCopy = new HashMap<>(config); - this.config = () -> configCopy; - return this; - } - - public AuthenticationBackend config(Supplier> configSupplier) { - this.config = configSupplier; - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("type", type); - xContentBuilder.field("config", config.get()); - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - } - - public void initIndex(Client client) { - Map settings = new HashMap<>(); - if (indexName.startsWith(".")) { - settings.put("index.hidden", true); - } - client.admin().indices().create(new CreateIndexRequest(indexName).settings(settings)).actionGet(); - - writeSingleEntryConfigToIndex(client, CType.CONFIG, config); - if(auditConfiguration != null) { - writeSingleEntryConfigToIndex(client, CType.AUDIT, "config", auditConfiguration); - } - writeConfigToIndex(client, CType.ROLES, roles); - writeConfigToIndex(client, CType.INTERNALUSERS, internalUsers); - writeConfigToIndex(client, CType.ROLESMAPPING, rolesMapping); - writeEmptyConfigToIndex(client, CType.ACTIONGROUPS); - writeEmptyConfigToIndex(client, CType.TENANTS); - } - - public void updateInternalUsersConfiguration(Client client, List users) { - Map userMap = new HashMap<>(); - for(User user : users) { - userMap.put(user.getName(), user); - } - updateConfigInIndex(client, CType.INTERNALUSERS, userMap); - } - - - static String hash(final char[] clearTextPassword) { - final byte[] salt = new byte[16]; - new SecureRandom().nextBytes(salt); - final String hash = OpenBSDBCrypt.generate((Objects.requireNonNull(clearTextPassword)), salt, 12); - Arrays.fill(salt, (byte) 0); - Arrays.fill(clearTextPassword, '\0'); - return hash; - } - - private void writeEmptyConfigToIndex(Client client, CType configType) { - writeConfigToIndex(client, configType, Collections.emptyMap()); - } - - private void writeConfigToIndex(Client client, CType configType, Map config) { - try { - String json = configToJson(configType, config); - - log.info("Writing security configuration into index " + configType + ":\n" + json); - - BytesReference bytesReference = toByteReference(json); - client.index(new IndexRequest(indexName).id(configType.toLCString()) - .setRefreshPolicy(IMMEDIATE).source(configType.toLCString(), bytesReference)) - .actionGet(); - } catch (Exception e) { - throw new RuntimeException("Error while initializing config for " + indexName, e); - } - } - - private static BytesReference toByteReference(String string) throws UnsupportedEncodingException { - return BytesReference.fromByteBuffer(ByteBuffer.wrap(string.getBytes("utf-8"))); - } - - private void updateConfigInIndex(Client client, CType configType, Map config) { - try { - String json = configToJson(configType, config); - BytesReference bytesReference = toByteReference(json); - log.info("Update configuration of type '{}' in index '{}', new value '{}'.", configType, indexName, json); - UpdateRequest upsert = new UpdateRequest(indexName, configType.toLCString()).doc(configType.toLCString(), bytesReference) - .setRefreshPolicy(IMMEDIATE); - client.update(upsert).actionGet(); - } catch (Exception e) { - throw new RuntimeException("Error while updating config for " + indexName, e); - } - } - - private static String configToJson(CType configType, Map config) throws IOException { - XContentBuilder builder = XContentFactory.jsonBuilder(); - - builder.startObject(); - builder.startObject("_meta"); - builder.field("type", configType.toLCString()); - builder.field("config_version", 2); - builder.endObject(); - - for (Map.Entry entry : config.entrySet()) { - builder.field(entry.getKey(), entry.getValue()); - } - - builder.endObject(); - - return Strings.toString(builder); - } - - private void writeSingleEntryConfigToIndex(Client client, CType configType, ToXContentObject config) { - writeSingleEntryConfigToIndex(client, configType, configType.toLCString(), config); - } - - private void writeSingleEntryConfigToIndex(Client client, CType configType, String configurationRoot, ToXContentObject config) { - try { - XContentBuilder builder = XContentFactory.jsonBuilder(); - - builder.startObject(); - builder.startObject("_meta"); - builder.field("type", configType.toLCString()); - builder.field("config_version", 2); - builder.endObject(); - - builder.field(configurationRoot, config); - - builder.endObject(); - - String json = Strings.toString(builder); - - log.info("Writing security plugin configuration into index " + configType + ":\n" + json); - - client.index(new IndexRequest(indexName).id(configType.toLCString()) - .setRefreshPolicy(IMMEDIATE).source(configType.toLCString(), toByteReference(json))) - .actionGet(); - } catch (Exception e) { - throw new RuntimeException("Error while initializing config for " + indexName, e); - } - } + private static final Logger log = LogManager.getLogger(TestSecurityConfig.class); + + private Config config = new Config(); + private Map internalUsers = new LinkedHashMap<>(); + private Map roles = new LinkedHashMap<>(); + private AuditConfiguration auditConfiguration; + private Map rolesMapping = new LinkedHashMap<>(); + + private String indexName = ".opendistro_security"; + + public TestSecurityConfig() { + + } + + public TestSecurityConfig configIndexName(String configIndexName) { + this.indexName = configIndexName; + return this; + } + + public TestSecurityConfig authFailureListeners(AuthFailureListeners listener) { + config.authFailureListeners(listener); + return this; + } + + public TestSecurityConfig anonymousAuth(boolean anonymousAuthEnabled) { + config.anonymousAuth(anonymousAuthEnabled); + return this; + } + + public TestSecurityConfig doNotFailOnForbidden(boolean doNotFailOnForbidden) { + config.doNotFailOnForbidden(doNotFailOnForbidden); + return this; + } + + public TestSecurityConfig xff(XffConfig xffConfig) { + config.xffConfig(xffConfig); + return this; + } + + public TestSecurityConfig authc(AuthcDomain authcDomain) { + config.authc(authcDomain); + return this; + } + + public TestSecurityConfig authz(AuthzDomain authzDomain) { + config.authz(authzDomain); + return this; + } + + public TestSecurityConfig user(User user) { + this.internalUsers.put(user.name, user); + + for (Role role : user.roles) { + this.roles.put(role.name, role); + } + + return this; + } + + public List getUsers() { + return new ArrayList<>(internalUsers.values()); + } + + public TestSecurityConfig roles(Role... roles) { + for (Role role : roles) { + if (this.roles.containsKey(role.name)) { + throw new IllegalStateException("Role with name " + role.name + " is already defined"); + } + this.roles.put(role.name, role); + } + + return this; + } + + public TestSecurityConfig audit(AuditConfiguration auditConfiguration) { + this.auditConfiguration = auditConfiguration; + return this; + } + + public TestSecurityConfig rolesMapping(RolesMapping... mappings) { + for (RolesMapping mapping : mappings) { + String roleName = mapping.getRoleName(); + if (rolesMapping.containsKey(roleName)) { + throw new IllegalArgumentException("Role mapping " + roleName + " already exists"); + } + this.rolesMapping.put(roleName, mapping); + } + return this; + } + + public static class Config implements ToXContentObject { + private boolean anonymousAuth; + + private Boolean doNotFailOnForbidden; + private XffConfig xffConfig; + private Map authcDomainMap = new LinkedHashMap<>(); + + private AuthFailureListeners authFailureListeners; + private Map authzDomainMap = new LinkedHashMap<>(); + + public Config anonymousAuth(boolean anonymousAuth) { + this.anonymousAuth = anonymousAuth; + return this; + } + + public Config doNotFailOnForbidden(Boolean doNotFailOnForbidden) { + this.doNotFailOnForbidden = doNotFailOnForbidden; + return this; + } + + public Config xffConfig(XffConfig xffConfig) { + this.xffConfig = xffConfig; + return this; + } + + public Config authc(AuthcDomain authcDomain) { + authcDomainMap.put(authcDomain.id, authcDomain); + return this; + } + + public Config authFailureListeners(AuthFailureListeners authFailureListeners) { + this.authFailureListeners = authFailureListeners; + return this; + } + + public Config authz(AuthzDomain authzDomain) { + authzDomainMap.put(authzDomain.getId(), authzDomain); + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.startObject("dynamic"); + + if (anonymousAuth || (xffConfig != null)) { + xContentBuilder.startObject("http"); + xContentBuilder.field("anonymous_auth_enabled", anonymousAuth); + if (xffConfig != null) { + xContentBuilder.field("xff", xffConfig); + } + xContentBuilder.endObject(); + } + if (doNotFailOnForbidden != null) { + xContentBuilder.field("do_not_fail_on_forbidden", doNotFailOnForbidden); + } + + xContentBuilder.field("authc", authcDomainMap); + if (authzDomainMap.isEmpty() == false) { + xContentBuilder.field("authz", authzDomainMap); + } + + if (authFailureListeners != null) { + xContentBuilder.field("auth_failure_listeners", authFailureListeners); + } + + xContentBuilder.endObject(); + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class User implements UserCredentialsHolder, ToXContentObject { + + public final static TestSecurityConfig.User USER_ADMIN = new TestSecurityConfig.User("admin").roles( + new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*") + ); + + String name; + private String password; + List roles = new ArrayList<>(); + private Map attributes = new HashMap<>(); + + public User(String name) { + this.name = name; + this.password = "secret"; + } + + public User password(String password) { + this.password = password; + return this; + } + + public User roles(Role... roles) { + // We scope the role names by user to keep tests free of potential side effects + String roleNamePrefix = "user_" + this.getName() + "__"; + this.roles.addAll( + Arrays.asList(roles).stream().map((r) -> r.clone().name(roleNamePrefix + r.getName())).collect(Collectors.toSet()) + ); + return this; + } + + public User attr(String key, Object value) { + this.attributes.put(key, value); + return this; + } + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public Set getRoleNames() { + return roles.stream().map(Role::getName).collect(Collectors.toSet()); + } + + public Object getAttribute(String attributeName) { + return attributes.get(attributeName); + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("hash", hash(password.toCharArray())); + + Set roleNames = getRoleNames(); + + if (!roleNames.isEmpty()) { + xContentBuilder.field("opendistro_security_roles", roleNames); + } + + if (attributes != null && attributes.size() != 0) { + xContentBuilder.field("attributes", attributes); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class Role implements ToXContentObject { + public static Role ALL_ACCESS = new Role("all_access").clusterPermissions("*").indexPermissions("*").on("*"); + + private String name; + private List clusterPermissions = new ArrayList<>(); + + private List indexPermissions = new ArrayList<>(); + + public Role(String name) { + this.name = name; + } + + public Role clusterPermissions(String... clusterPermissions) { + this.clusterPermissions.addAll(Arrays.asList(clusterPermissions)); + return this; + } + + public IndexPermission indexPermissions(String... indexPermissions) { + return new IndexPermission(this, indexPermissions); + } + + public Role name(String name) { + this.name = name; + return this; + } + + public String getName() { + return name; + } + + public Role clone() { + Role role = new Role(this.name); + role.clusterPermissions.addAll(this.clusterPermissions); + role.indexPermissions.addAll(this.indexPermissions); + return role; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + if (!clusterPermissions.isEmpty()) { + xContentBuilder.field("cluster_permissions", clusterPermissions); + } + + if (!indexPermissions.isEmpty()) { + xContentBuilder.field("index_permissions", indexPermissions); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class IndexPermission implements ToXContentObject { + private List allowedActions; + private List indexPatterns; + private Role role; + private String dlsQuery; + private List fls; + private List maskedFields; + + IndexPermission(Role role, String... allowedActions) { + this.allowedActions = Arrays.asList(allowedActions); + this.role = role; + } + + public IndexPermission dls(String dlsQuery) { + this.dlsQuery = dlsQuery; + return this; + } + + public IndexPermission fls(String... fls) { + this.fls = Arrays.asList(fls); + return this; + } + + public IndexPermission maskedFields(String... maskedFields) { + this.maskedFields = Arrays.asList(maskedFields); + return this; + } + + public Role on(String... indexPatterns) { + this.indexPatterns = Arrays.asList(indexPatterns); + this.role.indexPermissions.add(this); + return this.role; + } + + public Role on(TestIndex... testindices) { + this.indexPatterns = Arrays.asList(testindices).stream().map(TestIndex::getName).collect(Collectors.toList()); + this.role.indexPermissions.add(this); + return this.role; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("index_patterns", indexPatterns); + xContentBuilder.field("allowed_actions", allowedActions); + + if (dlsQuery != null) { + xContentBuilder.field("dls", dlsQuery); + } + + if (fls != null) { + xContentBuilder.field("fls", fls); + } + + if (maskedFields != null) { + xContentBuilder.field("masked_fields", maskedFields); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class AuthcDomain implements ToXContentObject { + + private static String PUBLIC_KEY = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoqZbjLUAWc+DZTkinQAdvy1GFjPHPnxheU89hSiWoDD3NOW76H3u3T7cCDdOah2msdxSlBmCBH6wik8qLYkcV8owWukQg3PQmbEhrdPaKo0QCgomWs4nLgtmEYqcZ+QQldd82MdTlQ1QmoQmI9Uxqs1SuaKZASp3Gy19y8su5CV+FZ6BruUw9HELK055sAwl3X7j5ouabXGbcib2goBF3P52LkvbJLuWr5HDZEOeSkwIeqSeMojASM96K5SdotD+HwEyjaTjzRPL2Aa1BEQFWOQ6CFJLyLH7ZStDuPM1mJU1VxIVfMbZrhsUBjAnIhRynmWxML7YlNqkP9j6jyOIYQIDAQAB"; + + public static final int BASIC_AUTH_DOMAIN_ORDER = 0; + public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig.AuthcDomain("basic", BASIC_AUTH_DOMAIN_ORDER) + .httpAuthenticatorWithChallenge("basic") + .backend("internal"); + + public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL_WITHOUT_CHALLENGE = new TestSecurityConfig.AuthcDomain( + "basic", + BASIC_AUTH_DOMAIN_ORDER + ).httpAuthenticator("basic").backend("internal"); + + public final static AuthcDomain DISABLED_AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig.AuthcDomain( + "basic", + BASIC_AUTH_DOMAIN_ORDER, + false + ).httpAuthenticator("basic").backend("internal"); + + public final static AuthcDomain JWT_AUTH_DOMAIN = new TestSecurityConfig.AuthcDomain("jwt", 1).jwtHttpAuthenticator( + new JwtConfigBuilder().jwtHeader(AUTHORIZATION).signingKey(PUBLIC_KEY) + ).backend("noop"); + + private final String id; + private boolean enabled = true; + private int order; + private List skipUsers = new ArrayList<>(); + private HttpAuthenticator httpAuthenticator; + private AuthenticationBackend authenticationBackend; + + public AuthcDomain(String id, int order, boolean enabled) { + this.id = id; + this.order = order; + this.enabled = enabled; + } + + public AuthcDomain(String id, int order) { + this(id, order, true); + } + + public AuthcDomain httpAuthenticator(String type) { + this.httpAuthenticator = new HttpAuthenticator(type); + return this; + } + + public AuthcDomain jwtHttpAuthenticator(JwtConfigBuilder builder) { + this.httpAuthenticator = new HttpAuthenticator("jwt").challenge(false).config(builder.build()); + return this; + } + + public AuthcDomain httpAuthenticatorWithChallenge(String type) { + this.httpAuthenticator = new HttpAuthenticator(type).challenge(true); + return this; + } + + public AuthcDomain httpAuthenticator(HttpAuthenticator httpAuthenticator) { + this.httpAuthenticator = httpAuthenticator; + return this; + } + + public AuthcDomain backend(String type) { + this.authenticationBackend = new AuthenticationBackend(type); + return this; + } + + public AuthcDomain backend(AuthenticationBackend authenticationBackend) { + this.authenticationBackend = authenticationBackend; + return this; + } + + public AuthcDomain skipUsers(String... users) { + this.skipUsers.addAll(Arrays.asList(users)); + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("http_enabled", enabled); + xContentBuilder.field("order", order); + + if (httpAuthenticator != null) { + xContentBuilder.field("http_authenticator", httpAuthenticator); + } + + if (authenticationBackend != null) { + xContentBuilder.field("authentication_backend", authenticationBackend); + } + + if (skipUsers != null && skipUsers.size() > 0) { + xContentBuilder.field("skip_users", skipUsers); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + + public static class HttpAuthenticator implements ToXContentObject { + private final String type; + private boolean challenge; + private Map config = new HashMap(); + + public HttpAuthenticator(String type) { + this.type = type; + } + + public HttpAuthenticator challenge(boolean challenge) { + this.challenge = challenge; + return this; + } + + public HttpAuthenticator config(Map config) { + this.config.putAll(config); + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("type", type); + xContentBuilder.field("challenge", challenge); + xContentBuilder.field("config", config); + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class AuthenticationBackend implements ToXContentObject { + private final String type; + private Supplier> config = () -> new HashMap(); + + public AuthenticationBackend(String type) { + this.type = type; + } + + public AuthenticationBackend config(Map config) { + Map configCopy = new HashMap<>(config); + this.config = () -> configCopy; + return this; + } + + public AuthenticationBackend config(Supplier> configSupplier) { + this.config = configSupplier; + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("type", type); + xContentBuilder.field("config", config.get()); + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + } + + public void initIndex(Client client) { + Map settings = new HashMap<>(); + if (indexName.startsWith(".")) { + settings.put("index.hidden", true); + } + client.admin().indices().create(new CreateIndexRequest(indexName).settings(settings)).actionGet(); + + writeSingleEntryConfigToIndex(client, CType.CONFIG, config); + if (auditConfiguration != null) { + writeSingleEntryConfigToIndex(client, CType.AUDIT, "config", auditConfiguration); + } + writeConfigToIndex(client, CType.ROLES, roles); + writeConfigToIndex(client, CType.INTERNALUSERS, internalUsers); + writeConfigToIndex(client, CType.ROLESMAPPING, rolesMapping); + writeEmptyConfigToIndex(client, CType.ACTIONGROUPS); + writeEmptyConfigToIndex(client, CType.TENANTS); + } + + public void updateInternalUsersConfiguration(Client client, List users) { + Map userMap = new HashMap<>(); + for (User user : users) { + userMap.put(user.getName(), user); + } + updateConfigInIndex(client, CType.INTERNALUSERS, userMap); + } + + static String hash(final char[] clearTextPassword) { + final byte[] salt = new byte[16]; + new SecureRandom().nextBytes(salt); + final String hash = OpenBSDBCrypt.generate((Objects.requireNonNull(clearTextPassword)), salt, 12); + Arrays.fill(salt, (byte) 0); + Arrays.fill(clearTextPassword, '\0'); + return hash; + } + + private void writeEmptyConfigToIndex(Client client, CType configType) { + writeConfigToIndex(client, configType, Collections.emptyMap()); + } + + private void writeConfigToIndex(Client client, CType configType, Map config) { + try { + String json = configToJson(configType, config); + + log.info("Writing security configuration into index " + configType + ":\n" + json); + + BytesReference bytesReference = toByteReference(json); + client.index( + new IndexRequest(indexName).id(configType.toLCString()) + .setRefreshPolicy(IMMEDIATE) + .source(configType.toLCString(), bytesReference) + ).actionGet(); + } catch (Exception e) { + throw new RuntimeException("Error while initializing config for " + indexName, e); + } + } + + private static BytesReference toByteReference(String string) throws UnsupportedEncodingException { + return BytesReference.fromByteBuffer(ByteBuffer.wrap(string.getBytes("utf-8"))); + } + + private void updateConfigInIndex(Client client, CType configType, Map config) { + try { + String json = configToJson(configType, config); + BytesReference bytesReference = toByteReference(json); + log.info("Update configuration of type '{}' in index '{}', new value '{}'.", configType, indexName, json); + UpdateRequest upsert = new UpdateRequest(indexName, configType.toLCString()).doc(configType.toLCString(), bytesReference) + .setRefreshPolicy(IMMEDIATE); + client.update(upsert).actionGet(); + } catch (Exception e) { + throw new RuntimeException("Error while updating config for " + indexName, e); + } + } + + private static String configToJson(CType configType, Map config) throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder(); + + builder.startObject(); + builder.startObject("_meta"); + builder.field("type", configType.toLCString()); + builder.field("config_version", 2); + builder.endObject(); + + for (Map.Entry entry : config.entrySet()) { + builder.field(entry.getKey(), entry.getValue()); + } + + builder.endObject(); + + return Strings.toString(builder); + } + + private void writeSingleEntryConfigToIndex(Client client, CType configType, ToXContentObject config) { + writeSingleEntryConfigToIndex(client, configType, configType.toLCString(), config); + } + + private void writeSingleEntryConfigToIndex(Client client, CType configType, String configurationRoot, ToXContentObject config) { + try { + XContentBuilder builder = XContentFactory.jsonBuilder(); + + builder.startObject(); + builder.startObject("_meta"); + builder.field("type", configType.toLCString()); + builder.field("config_version", 2); + builder.endObject(); + + builder.field(configurationRoot, config); + + builder.endObject(); + + String json = Strings.toString(builder); + + log.info("Writing security plugin configuration into index " + configType + ":\n" + json); + + client.index( + new IndexRequest(indexName).id(configType.toLCString()) + .setRefreshPolicy(IMMEDIATE) + .source(configType.toLCString(), toByteReference(json)) + ).actionGet(); + } catch (Exception e) { + throw new RuntimeException("Error while initializing config for " + indexName, e); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java b/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java index fa4ec5d849..b1c10bfd73 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java +++ b/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java @@ -39,44 +39,44 @@ */ public class XffConfig implements ToXContentObject { - private final boolean enabled; + private final boolean enabled; - /** - * Regular expression used to determine if HTTP proxy is trusted or not. IP address of trusted proxies must match the regular - * expression defined by the below field. - */ - private String internalProxiesRegexp; + /** + * Regular expression used to determine if HTTP proxy is trusted or not. IP address of trusted proxies must match the regular + * expression defined by the below field. + */ + private String internalProxiesRegexp; - private String remoteIpHeader; + private String remoteIpHeader; - public XffConfig(boolean enabled) { - this.enabled = enabled; - } + public XffConfig(boolean enabled) { + this.enabled = enabled; + } - /** - * Builder-like method used to set value of the field {@link #internalProxiesRegexp} - * @param internalProxiesRegexp regular expression which matches IP address of a HTTP proxies if the proxies are trusted. - * @return builder - */ - public XffConfig internalProxiesRegexp(String internalProxiesRegexp) { - this.internalProxiesRegexp = internalProxiesRegexp; - return this; - } + /** + * Builder-like method used to set value of the field {@link #internalProxiesRegexp} + * @param internalProxiesRegexp regular expression which matches IP address of a HTTP proxies if the proxies are trusted. + * @return builder + */ + public XffConfig internalProxiesRegexp(String internalProxiesRegexp) { + this.internalProxiesRegexp = internalProxiesRegexp; + return this; + } - public XffConfig remoteIpHeader(String remoteIpHeader) { - this.remoteIpHeader = remoteIpHeader; - return this; - } + public XffConfig remoteIpHeader(String remoteIpHeader) { + this.remoteIpHeader = remoteIpHeader; + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("enabled", enabled); - xContentBuilder.field("internalProxies", internalProxiesRegexp); - if(StringUtils.isNoneBlank(remoteIpHeader)) { - xContentBuilder.field("remoteIpHeader", remoteIpHeader); - } - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("enabled", enabled); + xContentBuilder.field("internalProxies", internalProxiesRegexp); + if (StringUtils.isNoneBlank(remoteIpHeader)) { + xContentBuilder.field("remoteIpHeader", remoteIpHeader); + } + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java index 9f19b4e5db..911173e14a 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java +++ b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java @@ -36,94 +36,98 @@ public class AuditLogsRule implements TestRule { - private static final Logger log = LogManager.getLogger(AuditLogsRule.class); - - private List currentTestAuditMessages; - - public void waitForAuditLogs() { - try { - TimeUnit.SECONDS.sleep(3); - afterWaitingForAuditLogs(); - } catch (InterruptedException e) { - throw new RuntimeException("Waiting for audit logs interrupted.", e); - } - } - - private void afterWaitingForAuditLogs() { - if(log.isDebugEnabled()) { - log.debug("Audit records captured during test:\n{}", auditMessagesToString(currentTestAuditMessages)); - } - } - - public void assertExactlyOne(Predicate predicate) { - assertExactly(1, predicate); - } - - public void assertAuditLogsCount(int from, int to) { - int actualCount = currentTestAuditMessages.size(); - String message = "Expected audit log count is between " + from + " and " + to + " but was " + actualCount; - assertThat(message, actualCount, allOf(greaterThanOrEqualTo(from), lessThanOrEqualTo(to))); - } - - public void assertExactly(long expectedNumberOfAuditMessages, Predicate predicate) { - assertExactly(exactNumberOfAuditsFulfillPredicate(expectedNumberOfAuditMessages, predicate)); - } - - private void assertExactly(Matcher> matcher) { - //pollDelay - initial delay before first evaluation - Awaitility.await("Await for audit logs") - .atMost(3, TimeUnit.SECONDS).pollDelay(0, TimeUnit.MICROSECONDS) - .until(() -> new ArrayList<>(currentTestAuditMessages), matcher); - } - - public void assertAtLeast(long minCount, Predicate predicate) { - assertExactly(atLeastCertainNumberOfAuditsFulfillPredicate(minCount, predicate)); - } - - private static String auditMessagesToString(List audits) { - return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); - } - - @Override - public Statement apply(Statement statement, Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - String methodName = description.getMethodName(); - beforeTest(methodName); - try { - statement.evaluate(); - } catch (ConditionTimeoutException ex) { - whenTimeoutOccurs(methodName); - throw ex; - } - finally { - afterTest(); - } - } - }; - } - - private void whenTimeoutOccurs(String methodName) { - List copy = new ArrayList<>(currentTestAuditMessages); - String auditMessages = auditMessagesToString(copy); - log.error("Timeout occured due to insufficient number ('{}') of captured audit messages during test '{}'\n{}", - copy.size(), methodName, auditMessages); - } - - private void afterTest() { - TestRuleAuditLogSink.unregisterListener(); - this.currentTestAuditMessages = null; - } - - private void beforeTest(String methodName) { - log.info("Start collecting audit logs before test {}", methodName); - this.currentTestAuditMessages = synchronizedList(new ArrayList<>()); - TestRuleAuditLogSink.registerListener(this); - } - - public void onAuditMessage(AuditMessage auditMessage) { - currentTestAuditMessages.add(auditMessage); - log.debug("New audit message received '{}', total number of audit messages '{}'.", auditMessage, currentTestAuditMessages.size()); - } + private static final Logger log = LogManager.getLogger(AuditLogsRule.class); + + private List currentTestAuditMessages; + + public void waitForAuditLogs() { + try { + TimeUnit.SECONDS.sleep(3); + afterWaitingForAuditLogs(); + } catch (InterruptedException e) { + throw new RuntimeException("Waiting for audit logs interrupted.", e); + } + } + + private void afterWaitingForAuditLogs() { + if (log.isDebugEnabled()) { + log.debug("Audit records captured during test:\n{}", auditMessagesToString(currentTestAuditMessages)); + } + } + + public void assertExactlyOne(Predicate predicate) { + assertExactly(1, predicate); + } + + public void assertAuditLogsCount(int from, int to) { + int actualCount = currentTestAuditMessages.size(); + String message = "Expected audit log count is between " + from + " and " + to + " but was " + actualCount; + assertThat(message, actualCount, allOf(greaterThanOrEqualTo(from), lessThanOrEqualTo(to))); + } + + public void assertExactly(long expectedNumberOfAuditMessages, Predicate predicate) { + assertExactly(exactNumberOfAuditsFulfillPredicate(expectedNumberOfAuditMessages, predicate)); + } + + private void assertExactly(Matcher> matcher) { + // pollDelay - initial delay before first evaluation + Awaitility.await("Await for audit logs") + .atMost(3, TimeUnit.SECONDS) + .pollDelay(0, TimeUnit.MICROSECONDS) + .until(() -> new ArrayList<>(currentTestAuditMessages), matcher); + } + + public void assertAtLeast(long minCount, Predicate predicate) { + assertExactly(atLeastCertainNumberOfAuditsFulfillPredicate(minCount, predicate)); + } + + private static String auditMessagesToString(List audits) { + return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); + } + + @Override + public Statement apply(Statement statement, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + String methodName = description.getMethodName(); + beforeTest(methodName); + try { + statement.evaluate(); + } catch (ConditionTimeoutException ex) { + whenTimeoutOccurs(methodName); + throw ex; + } finally { + afterTest(); + } + } + }; + } + + private void whenTimeoutOccurs(String methodName) { + List copy = new ArrayList<>(currentTestAuditMessages); + String auditMessages = auditMessagesToString(copy); + log.error( + "Timeout occured due to insufficient number ('{}') of captured audit messages during test '{}'\n{}", + copy.size(), + methodName, + auditMessages + ); + } + + private void afterTest() { + TestRuleAuditLogSink.unregisterListener(); + this.currentTestAuditMessages = null; + } + + private void beforeTest(String methodName) { + log.info("Start collecting audit logs before test {}", methodName); + this.currentTestAuditMessages = synchronizedList(new ArrayList<>()); + TestRuleAuditLogSink.registerListener(this); + } + + public void onAuditMessage(AuditMessage auditMessage) { + currentTestAuditMessages.add(auditMessage); + log.debug("New audit message received '{}', total number of audit messages '{}'.", auditMessage, currentTestAuditMessages.size()); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java index 940294b938..922f2d54aa 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java +++ b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java @@ -33,122 +33,201 @@ public class AuditMessagePredicate implements Predicate { - private final AuditCategory category; - private final Origin requestLayer; - private final String restRequestPath; - private final String initiatingUser; - private final Method requestMethod; - private final String transportRequestType; - private final String effectiveUser; - private final String index; - - private AuditMessagePredicate(AuditCategory category, Origin requestLayer, String restRequestPath, - String initiatingUser, Method requestMethod, String transportRequestType, String effectiveUser, String index) { - this.category = category; - this.requestLayer = requestLayer; - this.restRequestPath = restRequestPath; - this.initiatingUser = initiatingUser; - this.requestMethod = requestMethod; - this.transportRequestType = transportRequestType; - this.effectiveUser = effectiveUser; - this.index = index; - } - - private AuditMessagePredicate(AuditCategory category) { - this(category, null, null, null, null, null, null, null); - } - - public static AuditMessagePredicate auditPredicate(AuditCategory category) { - return new AuditMessagePredicate(category); - } - - public static AuditMessagePredicate userAuthenticated(User user) { - return auditPredicate(AUTHENTICATED).withInitiatingUser(user); - } - - public static AuditMessagePredicate grantedPrivilege(User user, String requestType) { - return auditPredicate(GRANTED_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user) - .withTransportRequestType(requestType); - } - - public static AuditMessagePredicate missingPrivilege(User user, String requestType) { - return auditPredicate(MISSING_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user) - .withTransportRequestType(requestType); - } - - public AuditMessagePredicate withLayer(Origin layer) { - return new AuditMessagePredicate(category, layer, restRequestPath, initiatingUser, requestMethod, - transportRequestType, effectiveUser, index); - } - - public AuditMessagePredicate withRequestPath(String path) { - return new AuditMessagePredicate(category, requestLayer, path, initiatingUser, requestMethod, transportRequestType, effectiveUser, - index); - } - - public AuditMessagePredicate withInitiatingUser(String user) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, user, requestMethod, transportRequestType, effectiveUser, - index); - } - - public AuditMessagePredicate withInitiatingUser(User user) { - return withInitiatingUser(user.getName()); - } - - public AuditMessagePredicate withRestMethod(Method method) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, method, - transportRequestType, effectiveUser, index); - } - - public AuditMessagePredicate withTransportRequestType(String type) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, requestMethod, type, effectiveUser, index); - } - - public AuditMessagePredicate withEffectiveUser(String user) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, requestMethod, transportRequestType, user, - index); - } - - public AuditMessagePredicate withEffectiveUser(User user) { - return withEffectiveUser(user.getName()); - } - - public AuditMessagePredicate withRestRequest(Method method, String path) { - return this.withLayer(Origin.REST).withRestMethod(method).withRequestPath(path); - } - - public AuditMessagePredicate withIndex(String indexName) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, requestMethod, transportRequestType, - effectiveUser, indexName); - } - - @Override - public boolean test(AuditMessage auditMessage) { - List> predicates = new ArrayList<>(); - predicates.add(audit -> Objects.isNull(category) || category.equals(audit.getCategory())); - predicates.add(audit -> Objects.isNull(requestLayer) || requestLayer.equals(audit.getAsMap().get(REQUEST_LAYER))); - predicates.add(audit -> Objects.isNull(restRequestPath) || restRequestPath.equals(audit.getAsMap().get(REST_REQUEST_PATH))); - predicates.add(audit -> Objects.isNull(initiatingUser) || initiatingUser.equals(audit.getInitiatingUser())); - predicates.add(audit -> Objects.isNull(requestMethod) || requestMethod.equals(audit.getRequestMethod())); - predicates.add(audit -> Objects.isNull(transportRequestType) || transportRequestType.equals(audit.getRequestType())); - predicates.add(audit -> Objects.isNull(effectiveUser) || effectiveUser.equals(audit.getEffectiveUser())); - predicates.add(audit -> Objects.isNull(index) || containIndex(audit, index)); - return predicates.stream().reduce(Predicate::and).orElseThrow().test(auditMessage); - } - - private boolean containIndex(AuditMessage auditMessage, String indexName) { - Map audit = auditMessage.getAsMap(); - return Optional.ofNullable(audit.get(RESOLVED_INDICES)) - .filter(String[].class::isInstance) - .map(String[].class::cast) - .stream() - .flatMap(Arrays::stream) - .collect(Collectors.toSet()) - .contains(indexName); - } - - @Override - public String toString() { - return "AuditMessagePredicate{" + "category=" + category + ", requestLayer=" + requestLayer + ", restRequestPath='" + restRequestPath + '\'' + ", requestInitiatingUser='" + initiatingUser + '\'' + ", requestMethod=" + requestMethod + ", transportRequestType='" + transportRequestType + '\'' + '}'; - } + private final AuditCategory category; + private final Origin requestLayer; + private final String restRequestPath; + private final String initiatingUser; + private final Method requestMethod; + private final String transportRequestType; + private final String effectiveUser; + private final String index; + + private AuditMessagePredicate( + AuditCategory category, + Origin requestLayer, + String restRequestPath, + String initiatingUser, + Method requestMethod, + String transportRequestType, + String effectiveUser, + String index + ) { + this.category = category; + this.requestLayer = requestLayer; + this.restRequestPath = restRequestPath; + this.initiatingUser = initiatingUser; + this.requestMethod = requestMethod; + this.transportRequestType = transportRequestType; + this.effectiveUser = effectiveUser; + this.index = index; + } + + private AuditMessagePredicate(AuditCategory category) { + this(category, null, null, null, null, null, null, null); + } + + public static AuditMessagePredicate auditPredicate(AuditCategory category) { + return new AuditMessagePredicate(category); + } + + public static AuditMessagePredicate userAuthenticated(User user) { + return auditPredicate(AUTHENTICATED).withInitiatingUser(user); + } + + public static AuditMessagePredicate grantedPrivilege(User user, String requestType) { + return auditPredicate(GRANTED_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user).withTransportRequestType(requestType); + } + + public static AuditMessagePredicate missingPrivilege(User user, String requestType) { + return auditPredicate(MISSING_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user).withTransportRequestType(requestType); + } + + public AuditMessagePredicate withLayer(Origin layer) { + return new AuditMessagePredicate( + category, + layer, + restRequestPath, + initiatingUser, + requestMethod, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withRequestPath(String path) { + return new AuditMessagePredicate( + category, + requestLayer, + path, + initiatingUser, + requestMethod, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withInitiatingUser(String user) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + user, + requestMethod, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withInitiatingUser(User user) { + return withInitiatingUser(user.getName()); + } + + public AuditMessagePredicate withRestMethod(Method method) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + method, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withTransportRequestType(String type) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + requestMethod, + type, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withEffectiveUser(String user) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + requestMethod, + transportRequestType, + user, + index + ); + } + + public AuditMessagePredicate withEffectiveUser(User user) { + return withEffectiveUser(user.getName()); + } + + public AuditMessagePredicate withRestRequest(Method method, String path) { + return this.withLayer(Origin.REST).withRestMethod(method).withRequestPath(path); + } + + public AuditMessagePredicate withIndex(String indexName) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + requestMethod, + transportRequestType, + effectiveUser, + indexName + ); + } + + @Override + public boolean test(AuditMessage auditMessage) { + List> predicates = new ArrayList<>(); + predicates.add(audit -> Objects.isNull(category) || category.equals(audit.getCategory())); + predicates.add(audit -> Objects.isNull(requestLayer) || requestLayer.equals(audit.getAsMap().get(REQUEST_LAYER))); + predicates.add(audit -> Objects.isNull(restRequestPath) || restRequestPath.equals(audit.getAsMap().get(REST_REQUEST_PATH))); + predicates.add(audit -> Objects.isNull(initiatingUser) || initiatingUser.equals(audit.getInitiatingUser())); + predicates.add(audit -> Objects.isNull(requestMethod) || requestMethod.equals(audit.getRequestMethod())); + predicates.add(audit -> Objects.isNull(transportRequestType) || transportRequestType.equals(audit.getRequestType())); + predicates.add(audit -> Objects.isNull(effectiveUser) || effectiveUser.equals(audit.getEffectiveUser())); + predicates.add(audit -> Objects.isNull(index) || containIndex(audit, index)); + return predicates.stream().reduce(Predicate::and).orElseThrow().test(auditMessage); + } + + private boolean containIndex(AuditMessage auditMessage, String indexName) { + Map audit = auditMessage.getAsMap(); + return Optional.ofNullable(audit.get(RESOLVED_INDICES)) + .filter(String[].class::isInstance) + .map(String[].class::cast) + .stream() + .flatMap(Arrays::stream) + .collect(Collectors.toSet()) + .contains(indexName); + } + + @Override + public String toString() { + return "AuditMessagePredicate{" + + "category=" + + category + + ", requestLayer=" + + requestLayer + + ", restRequestPath='" + + restRequestPath + + '\'' + + ", requestInitiatingUser='" + + initiatingUser + + '\'' + + ", requestMethod=" + + requestMethod + + ", transportRequestType='" + + transportRequestType + + '\'' + + '}'; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java b/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java index 0a9abaeb0d..c73d57d23c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java +++ b/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java @@ -17,35 +17,35 @@ import org.opensearch.security.auditlog.sink.AuditLogSink; public class TestRuleAuditLogSink extends AuditLogSink { - private static final Logger log = LogManager.getLogger(TestRuleAuditLogSink.class); - - private static volatile AuditLogsRule listener; - - public TestRuleAuditLogSink(String name, Settings settings, String settingsPrefix, AuditLogSink fallbackSink) { - super(name, settings, settingsPrefix, fallbackSink); - log.info("Test rule audit log sink created"); - } - - @Override - protected boolean doStore(AuditMessage auditMessage) { - log.debug("New audit message received '{}'.", auditMessage); - AuditLogsRule currentListener = listener; - if(currentListener != null) { - currentListener.onAuditMessage(auditMessage); - } - return true; - } - - public static void registerListener(AuditLogsRule auditLogsRule) { - listener = auditLogsRule; - } - - public static void unregisterListener() { - listener = null; - } - - @Override - public boolean isHandlingBackpressure() { - return true; - } + private static final Logger log = LogManager.getLogger(TestRuleAuditLogSink.class); + + private static volatile AuditLogsRule listener; + + public TestRuleAuditLogSink(String name, Settings settings, String settingsPrefix, AuditLogSink fallbackSink) { + super(name, settings, settingsPrefix, fallbackSink); + log.info("Test rule audit log sink created"); + } + + @Override + protected boolean doStore(AuditMessage auditMessage) { + log.debug("New audit message received '{}'.", auditMessage); + AuditLogsRule currentListener = listener; + if (currentListener != null) { + currentListener.onAuditMessage(auditMessage); + } + return true; + } + + public static void registerListener(AuditLogsRule auditLogsRule) { + listener = auditLogsRule; + } + + public static void unregisterListener() { + listener = null; + } + + @Override + public boolean isHandlingBackpressure() { + return true; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java index 270a2bad6f..60ae56410c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java @@ -48,99 +48,100 @@ */ class AlgorithmKit { - private static final Logger log = LogManager.getLogger(AlgorithmKit.class); - public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_RSA = "SHA256withRSA"; - public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA = "SHA256withECDSA"; - - private final String signatureAlgorithmName; - private final Supplier keyPairSupplier; - - private AlgorithmKit(String signatureAlgorithmName, Supplier keyPairSupplier) { - notEmptyAlgorithmName(signatureAlgorithmName); - this.signatureAlgorithmName = signatureAlgorithmName; - this.keyPairSupplier = requireNonNull(keyPairSupplier, "Key pair supplier is required."); - } - - private static void notEmptyAlgorithmName(String signatureAlgorithmName) { - if(Strings.isNullOrEmpty(signatureAlgorithmName)){ - throw new RuntimeException("Algorithm name is required."); - } - } - - /** - * Static factory method. ECDSA algorithm used for key pair creation. Signature algorithm is defined by field - * {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA} - * - * @param securityProvider determines cryptographic algorithm implementation - * @param ellipticCurve - * @return new instance of class {@link AlgorithmKit} - */ - public static AlgorithmKit ecdsaSha256withEcdsa(Provider securityProvider, String ellipticCurve) { - notEmptyAlgorithmName(ellipticCurve); - Supplier supplier = ecdsaKeyPairSupplier(requireNonNull(securityProvider, "Security provider is required"), ellipticCurve); - return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA, supplier); - } - - /** - * Static factory method. It creates object of {@link AlgorithmKit} which enforces usage of RSA algorithm for key pair generation. - * Signature algorithm is defined by {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_RSA} - * - * @param securityProvider determines cryptographic algorithm implementation - * @param keySize defines key size for RSA algorithm - * @return new instance of class {@link AlgorithmKit} - */ - public static AlgorithmKit rsaSha256withRsa(Provider securityProvider, int keySize) { - positiveKeySize(keySize); - Supplier supplier = rsaKeyPairSupplier(securityProvider, keySize); - return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_RSA, supplier); - } - - private static void positiveKeySize(int keySize) { - if(keySize <= 0) { - throw new RuntimeException("Key size must be a positive integer value, provided: " + keySize); - } - } - - /** - * It determines algorithm used for digital signature - * @return algorithm name - */ - public String getSignatureAlgorithmName(){ - return signatureAlgorithmName; - } - - /** - * It creates new private and public key pair - * @return new pair of keys - */ - public KeyPair generateKeyPair(){ - return keyPairSupplier.get(); - } - private static Supplier rsaKeyPairSupplier(Provider securityProvider, int keySize) { - try { - KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", securityProvider); - log.info("Initialize key pair generator with keySize: {}", keySize); - generator.initialize(keySize); - return generator::generateKeyPair; - } catch (NoSuchAlgorithmException e) { - String message = "Error while initializing RSA asymmetric key generator."; - log.error(message, e); - throw new RuntimeException(message, e); - } - } - - private static Supplier ecdsaKeyPairSupplier(Provider securityProvider, String ellipticCurve) { - try { - KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", securityProvider); - log.info("Initialize key pair generator with elliptic curve: {}", ellipticCurve); - ECGenParameterSpec ecsp = new ECGenParameterSpec(ellipticCurve); - generator.initialize(ecsp); - return generator::generateKeyPair; - } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { - String message = "Error while initializing ECDSA asymmetric key generator."; - log.error(message, e); - throw new RuntimeException(message, e); - } - } + private static final Logger log = LogManager.getLogger(AlgorithmKit.class); + public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_RSA = "SHA256withRSA"; + public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA = "SHA256withECDSA"; + + private final String signatureAlgorithmName; + private final Supplier keyPairSupplier; + + private AlgorithmKit(String signatureAlgorithmName, Supplier keyPairSupplier) { + notEmptyAlgorithmName(signatureAlgorithmName); + this.signatureAlgorithmName = signatureAlgorithmName; + this.keyPairSupplier = requireNonNull(keyPairSupplier, "Key pair supplier is required."); + } + + private static void notEmptyAlgorithmName(String signatureAlgorithmName) { + if (Strings.isNullOrEmpty(signatureAlgorithmName)) { + throw new RuntimeException("Algorithm name is required."); + } + } + + /** + * Static factory method. ECDSA algorithm used for key pair creation. Signature algorithm is defined by field + * {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA} + * + * @param securityProvider determines cryptographic algorithm implementation + * @param ellipticCurve + * @return new instance of class {@link AlgorithmKit} + */ + public static AlgorithmKit ecdsaSha256withEcdsa(Provider securityProvider, String ellipticCurve) { + notEmptyAlgorithmName(ellipticCurve); + Supplier supplier = ecdsaKeyPairSupplier(requireNonNull(securityProvider, "Security provider is required"), ellipticCurve); + return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA, supplier); + } + + /** + * Static factory method. It creates object of {@link AlgorithmKit} which enforces usage of RSA algorithm for key pair generation. + * Signature algorithm is defined by {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_RSA} + * + * @param securityProvider determines cryptographic algorithm implementation + * @param keySize defines key size for RSA algorithm + * @return new instance of class {@link AlgorithmKit} + */ + public static AlgorithmKit rsaSha256withRsa(Provider securityProvider, int keySize) { + positiveKeySize(keySize); + Supplier supplier = rsaKeyPairSupplier(securityProvider, keySize); + return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_RSA, supplier); + } + + private static void positiveKeySize(int keySize) { + if (keySize <= 0) { + throw new RuntimeException("Key size must be a positive integer value, provided: " + keySize); + } + } + + /** + * It determines algorithm used for digital signature + * @return algorithm name + */ + public String getSignatureAlgorithmName() { + return signatureAlgorithmName; + } + + /** + * It creates new private and public key pair + * @return new pair of keys + */ + public KeyPair generateKeyPair() { + return keyPairSupplier.get(); + } + + private static Supplier rsaKeyPairSupplier(Provider securityProvider, int keySize) { + try { + KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", securityProvider); + log.info("Initialize key pair generator with keySize: {}", keySize); + generator.initialize(keySize); + return generator::generateKeyPair; + } catch (NoSuchAlgorithmException e) { + String message = "Error while initializing RSA asymmetric key generator."; + log.error(message, e); + throw new RuntimeException(message, e); + } + } + + private static Supplier ecdsaKeyPairSupplier(Provider securityProvider, String ellipticCurve) { + try { + KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", securityProvider); + log.info("Initialize key pair generator with elliptic curve: {}", ellipticCurve); + ECGenParameterSpec ecsp = new ECGenParameterSpec(ellipticCurve); + generator.initialize(ecsp); + return generator::generateKeyPair; + } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { + String message = "Error while initializing ECDSA asymmetric key generator."; + log.error(message, e); + throw new RuntimeException(message, e); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java index 3712bd1763..09d0f931e6 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java @@ -40,50 +40,50 @@ */ public class CertificateData { - private final X509CertificateHolder certificate; - private final KeyPair keyPair; + private final X509CertificateHolder certificate; + private final KeyPair keyPair; - public CertificateData(X509CertificateHolder certificate, KeyPair keyPair) { - this.certificate = certificate; - this.keyPair = keyPair; - } + public CertificateData(X509CertificateHolder certificate, KeyPair keyPair) { + this.certificate = certificate; + this.keyPair = keyPair; + } - /** - * The method returns X.509 certificate encoded in PEM format. PEM format is defined by - * RFC 1421. - * @return Certificate in PEM format - */ - public String certificateInPemFormat() { - return PemConverter.toPem(certificate); - } + /** + * The method returns X.509 certificate encoded in PEM format. PEM format is defined by + * RFC 1421. + * @return Certificate in PEM format + */ + public String certificateInPemFormat() { + return PemConverter.toPem(certificate); + } - public X509Certificate certificate() { - try { - return new JcaX509CertificateConverter().getCertificate(certificate); - } catch (CertificateException e) { - throw new RuntimeException("Cannot retrieve certificate", e); - } - } + public X509Certificate certificate() { + try { + return new JcaX509CertificateConverter().getCertificate(certificate); + } catch (CertificateException e) { + throw new RuntimeException("Cannot retrieve certificate", e); + } + } - /** - * It returns the private key associated with certificate encoded in PEM format. PEM format is defined by - * RFC 1421. - * @param privateKeyPassword password used for private key encryption. null for unencrypted key. - * @return private key encoded in PEM format - */ - public String privateKeyInPemFormat(String privateKeyPassword) { - return PemConverter.toPem(keyPair.getPrivate(), privateKeyPassword); - } + /** + * It returns the private key associated with certificate encoded in PEM format. PEM format is defined by + * RFC 1421. + * @param privateKeyPassword password used for private key encryption. null for unencrypted key. + * @return private key encoded in PEM format + */ + public String privateKeyInPemFormat(String privateKeyPassword) { + return PemConverter.toPem(keyPair.getPrivate(), privateKeyPassword); + } - X500Name getCertificateSubject() { - return certificate.getSubject(); - } + X500Name getCertificateSubject() { + return certificate.getSubject(); + } - KeyPair getKeyPair() { - return keyPair; - } + KeyPair getKeyPair() { + return keyPair; + } - public Key getKey() { - return keyPair.getPrivate(); - } + public Key getKey() { + return keyPair.getPrivate(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java index fbd2c1f8e8..cc94621f72 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java @@ -42,180 +42,179 @@ * */ class CertificateMetadata { - /** - * Certification subject (person, company, web server, IoT device). The subject of certificate is an owner of the certificate - * (simplification). The format of this field must adhere to RFC 4514. - * @see RFC 4514 - */ - private final String subject; - - /** - * It describes certificate expiration date - */ - private final int validityDays; - - /** - * Optionally used by Open Search to indicate that the certificate can be used by Open Search node to confirm the node identity. The - * value becomes a part of - * SAN (Subject Alternative Name) extension - * - * @see #dnsNames - * @see SAN (Subject Alternative Name) extension - */ - private final String nodeOid; - - /** - * The certificate contains only one {@link #subject}. This is a common limitation when a certificate is used by a web server which is - * associated with a few domains. To overcome this limitation SAN (Subject Alternative Name) extension was introduced. - * The field contains additional subject names which enables creation of so called multi-domain certificates. The extension is defined - * in section 4.2.1.6 of RFC 5280 - * - * @see RFC 5280 - */ - private final List dnsNames; - - /** - * Similar to {@link #dnsNames} but contains IP addresses instead of domains. - */ - private final List ipAddresses; - - /** - * If a private key associated with certificate is used to sign other certificate then this field has to be true. - */ - private final boolean basicConstrainIsCa; - - /** - * Allowed usages for public key associated with certificate - */ - private final Set keyUsages; - - - private CertificateMetadata(String subject, - int validityDays, - String nodeOid, - List dnsNames, - List ipAddresses, - boolean basicConstrainIsCa, - Set keyUsages) { - this.subject = subject; - this.validityDays = validityDays; - this.nodeOid = nodeOid; - this.dnsNames = requireNonNull(dnsNames, "List of dns names must not be null."); - this.ipAddresses = requireNonNull(ipAddresses, "List of IP addresses must not be null"); - this.basicConstrainIsCa = basicConstrainIsCa; - this.keyUsages = requireNonNull(keyUsages, "Key usage set must not be null."); - } - - /** - * Static factory method. It creates metadata which contains only basic information. - * @param subjectName please see {@link #subject} - * @param validityDays please see {@link #validityDays} - * @return new instance of {@link CertificateMetadata} - */ - public static CertificateMetadata basicMetadata(String subjectName, int validityDays) { - return new CertificateMetadata(subjectName, validityDays, null, emptyList(), emptyList(), false, emptySet()); - } - - /** - * It is related to private key associated with certificate. It specifies metadata related to allowed private key usage. - * @param basicConstrainIsCa {@link #basicConstrainIsCa} - * @param keyUsages {@link #keyUsages} - * @return returns newly created instance of {@link CertificateData} - */ - public CertificateMetadata withKeyUsage(boolean basicConstrainIsCa, PublicKeyUsage...keyUsages){ - Set usages = arrayToEnumSet(keyUsages); - return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, ipAddresses, basicConstrainIsCa, usages); - } - - private > Set arrayToEnumSet(T[] enumArray) { - if((enumArray == null) || (enumArray.length == 0)){ - return Collections.emptySet(); - } - return EnumSet.copyOf(asList(enumArray)); - } - - /** - * The method defines metadata related to SAN (Subject Alternative Name) extension. - * @param nodeOid {@link #nodeOid} - * @param dnsNames {@link #dnsNames} - * @param ipAddresses {@link #ipAddresses} - * @return new instance of {@link CertificateMetadata} - * @see SAN (Subject Alternative Name) extension - */ - public CertificateMetadata withSubjectAlternativeName(String nodeOid, List dnsNames, String...ipAddresses) { - return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, asList(ipAddresses), basicConstrainIsCa, keyUsages); - } - - /** - * {@link #subject} - * @return Subject name - */ - public String getSubject() { - return subject; - } - - /** - * {@link #validityDays} - * @return determines certificate expiration date - */ - public int getValidityDays() { - return validityDays; - } - - /** - * {@link #basicConstrainIsCa} - * @return Determines if another certificate can be derived from certificate. - */ - public boolean isBasicConstrainIsCa() { - return basicConstrainIsCa; - } - - KeyUsage asKeyUsage() { - Integer keyUsageBitMask = keyUsages - .stream() - .filter(PublicKeyUsage::isNotExtendedUsage) - .map(PublicKeyUsage::asInt) - .reduce(0, (accumulator, currentValue) -> accumulator | currentValue); - return new KeyUsage(keyUsageBitMask); - } - - boolean hasSubjectAlternativeNameExtension() { - return ((ipAddresses.size() + dnsNames.size()) > 0) || (Strings.isNullOrEmpty(nodeOid) == false); - } - - DERSequence createSubjectAlternativeNames() { - List subjectAlternativeNameList = new ArrayList<>(); - if (!Strings.isNullOrEmpty(nodeOid)) { - subjectAlternativeNameList.add(new GeneralName(GeneralName.registeredID, nodeOid)); - } - if (isNotEmpty(dnsNames)) { - for (String dnsName : dnsNames) { - subjectAlternativeNameList.add(new GeneralName(GeneralName.dNSName, dnsName)); - } - } - if (isNotEmpty(ipAddresses)) { - for (String ip : ipAddresses) { - subjectAlternativeNameList.add(new GeneralName(GeneralName.iPAddress, ip)); - } - } - return new DERSequence(subjectAlternativeNameList.toArray(ASN1Encodable[]::new)); - } - - private static boolean isNotEmpty(Collection collection) { - return (collection != null) && (!collection.isEmpty()); - } - - boolean hasExtendedKeyUsage() { - return keyUsages.stream().anyMatch(PublicKeyUsage::isNotExtendedUsage); - } - - ExtendedKeyUsage getExtendedKeyUsage() { - KeyPurposeId[] usages = keyUsages - .stream() - .filter(PublicKeyUsage::isExtendedUsage) - .map(PublicKeyUsage::getKeyPurposeId) - .toArray(KeyPurposeId[]::new); - return new ExtendedKeyUsage(usages); - } + /** + * Certification subject (person, company, web server, IoT device). The subject of certificate is an owner of the certificate + * (simplification). The format of this field must adhere to RFC 4514. + * @see RFC 4514 + */ + private final String subject; + + /** + * It describes certificate expiration date + */ + private final int validityDays; + + /** + * Optionally used by Open Search to indicate that the certificate can be used by Open Search node to confirm the node identity. The + * value becomes a part of + * SAN (Subject Alternative Name) extension + * + * @see #dnsNames + * @see SAN (Subject Alternative Name) extension + */ + private final String nodeOid; + + /** + * The certificate contains only one {@link #subject}. This is a common limitation when a certificate is used by a web server which is + * associated with a few domains. To overcome this limitation SAN (Subject Alternative Name) extension was introduced. + * The field contains additional subject names which enables creation of so called multi-domain certificates. The extension is defined + * in section 4.2.1.6 of RFC 5280 + * + * @see RFC 5280 + */ + private final List dnsNames; + + /** + * Similar to {@link #dnsNames} but contains IP addresses instead of domains. + */ + private final List ipAddresses; + + /** + * If a private key associated with certificate is used to sign other certificate then this field has to be true. + */ + private final boolean basicConstrainIsCa; + + /** + * Allowed usages for public key associated with certificate + */ + private final Set keyUsages; + + private CertificateMetadata( + String subject, + int validityDays, + String nodeOid, + List dnsNames, + List ipAddresses, + boolean basicConstrainIsCa, + Set keyUsages + ) { + this.subject = subject; + this.validityDays = validityDays; + this.nodeOid = nodeOid; + this.dnsNames = requireNonNull(dnsNames, "List of dns names must not be null."); + this.ipAddresses = requireNonNull(ipAddresses, "List of IP addresses must not be null"); + this.basicConstrainIsCa = basicConstrainIsCa; + this.keyUsages = requireNonNull(keyUsages, "Key usage set must not be null."); + } + + /** + * Static factory method. It creates metadata which contains only basic information. + * @param subjectName please see {@link #subject} + * @param validityDays please see {@link #validityDays} + * @return new instance of {@link CertificateMetadata} + */ + public static CertificateMetadata basicMetadata(String subjectName, int validityDays) { + return new CertificateMetadata(subjectName, validityDays, null, emptyList(), emptyList(), false, emptySet()); + } + + /** + * It is related to private key associated with certificate. It specifies metadata related to allowed private key usage. + * @param basicConstrainIsCa {@link #basicConstrainIsCa} + * @param keyUsages {@link #keyUsages} + * @return returns newly created instance of {@link CertificateData} + */ + public CertificateMetadata withKeyUsage(boolean basicConstrainIsCa, PublicKeyUsage... keyUsages) { + Set usages = arrayToEnumSet(keyUsages); + return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, ipAddresses, basicConstrainIsCa, usages); + } + + private > Set arrayToEnumSet(T[] enumArray) { + if ((enumArray == null) || (enumArray.length == 0)) { + return Collections.emptySet(); + } + return EnumSet.copyOf(asList(enumArray)); + } + + /** + * The method defines metadata related to SAN (Subject Alternative Name) extension. + * @param nodeOid {@link #nodeOid} + * @param dnsNames {@link #dnsNames} + * @param ipAddresses {@link #ipAddresses} + * @return new instance of {@link CertificateMetadata} + * @see SAN (Subject Alternative Name) extension + */ + public CertificateMetadata withSubjectAlternativeName(String nodeOid, List dnsNames, String... ipAddresses) { + return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, asList(ipAddresses), basicConstrainIsCa, keyUsages); + } + + /** + * {@link #subject} + * @return Subject name + */ + public String getSubject() { + return subject; + } + + /** + * {@link #validityDays} + * @return determines certificate expiration date + */ + public int getValidityDays() { + return validityDays; + } + + /** + * {@link #basicConstrainIsCa} + * @return Determines if another certificate can be derived from certificate. + */ + public boolean isBasicConstrainIsCa() { + return basicConstrainIsCa; + } + + KeyUsage asKeyUsage() { + Integer keyUsageBitMask = keyUsages.stream() + .filter(PublicKeyUsage::isNotExtendedUsage) + .map(PublicKeyUsage::asInt) + .reduce(0, (accumulator, currentValue) -> accumulator | currentValue); + return new KeyUsage(keyUsageBitMask); + } + + boolean hasSubjectAlternativeNameExtension() { + return ((ipAddresses.size() + dnsNames.size()) > 0) || (Strings.isNullOrEmpty(nodeOid) == false); + } + + DERSequence createSubjectAlternativeNames() { + List subjectAlternativeNameList = new ArrayList<>(); + if (!Strings.isNullOrEmpty(nodeOid)) { + subjectAlternativeNameList.add(new GeneralName(GeneralName.registeredID, nodeOid)); + } + if (isNotEmpty(dnsNames)) { + for (String dnsName : dnsNames) { + subjectAlternativeNameList.add(new GeneralName(GeneralName.dNSName, dnsName)); + } + } + if (isNotEmpty(ipAddresses)) { + for (String ip : ipAddresses) { + subjectAlternativeNameList.add(new GeneralName(GeneralName.iPAddress, ip)); + } + } + return new DERSequence(subjectAlternativeNameList.toArray(ASN1Encodable[]::new)); + } + + private static boolean isNotEmpty(Collection collection) { + return (collection != null) && (!collection.isEmpty()); + } + + boolean hasExtendedKeyUsage() { + return keyUsages.stream().anyMatch(PublicKeyUsage::isNotExtendedUsage); + } + + ExtendedKeyUsage getExtendedKeyUsage() { + KeyPurposeId[] usages = keyUsages.stream() + .filter(PublicKeyUsage::isExtendedUsage) + .map(PublicKeyUsage::getKeyPurposeId) + .toArray(KeyPurposeId[]::new); + return new ExtendedKeyUsage(usages); + } } // CS-ENFORCE-SINGLE diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java index 8d821a4571..6facf5f2ac 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java @@ -83,144 +83,159 @@ */ class CertificatesIssuer { - private static final Logger log = LogManager.getLogger(CertificatesIssuer.class); - - private static final AtomicLong ID_COUNTER = new AtomicLong(System.currentTimeMillis()); - - private final Provider securityProvider; - private final AlgorithmKit algorithmKit; - private final JcaX509ExtensionUtils extUtils; - - CertificatesIssuer(Provider securityProvider, AlgorithmKit algorithmKit) { - this.securityProvider = securityProvider; - this.algorithmKit = algorithmKit; - this.extUtils = getExtUtils(); - } - - /** - * The method creates a certificate with provided metadata and public key obtained from {@link #algorithmKit}. The result of invocation - * contains required data to use a certificate by its owner. - * - * @param certificateMetadata metadata which should be embedded into created certificate - * @return {@link CertificateData} which contain certificate and private key associated with the certificate. - */ - public CertificateData issueSelfSignedCertificate(CertificateMetadata certificateMetadata) { - try { - KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); - X500Name issuerName = stringToX500Name(requireNonNull(certificateMetadata.getSubject(), "Certificate metadata are required.")); - X509CertificateHolder x509CertificateHolder = buildCertificateHolder( - certificateMetadata, - issuerName, - publicAndPrivateKey.getPublic(), - publicAndPrivateKey); - return new CertificateData(x509CertificateHolder, publicAndPrivateKey); - } catch (OperatorCreationException | CertIOException e) { - log.error("Error while generating certificate", e); - throw new RuntimeException("Error while generating self signed certificate", e); - } - } - - /** - * The method is similar to {@link #issueSignedCertificate(CertificateMetadata, CertificateData)} but additionally it signs created - * certificate using data from parentCertificateData. - * - * @param metadata metadata which should be embedded into created certificate - * @param parentCertificateData data required to signe a newly issued certificate (private key among others things). - * @return {@link CertificateData} which contain certificate and private key associated with the certificate. - */ - public CertificateData issueSignedCertificate(CertificateMetadata metadata, CertificateData parentCertificateData) { - try { - KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); - KeyPair parentKeyPair = requireNonNull(parentCertificateData, "Issuer certificate data are required") - .getKeyPair(); - X500Name issuerName = parentCertificateData.getCertificateSubject(); - var x509CertificateHolder = buildCertificateHolder(requireNonNull(metadata, "Certificate metadata are required"), - issuerName, - publicAndPrivateKey.getPublic(), - parentKeyPair); - return new CertificateData(x509CertificateHolder, publicAndPrivateKey); - } catch (OperatorCreationException | CertIOException e) { - log.error("Error while generating signed certificate", e); - throw new RuntimeException("Error while generating signed certificate", e); - } - } - - private X509CertificateHolder buildCertificateHolder(CertificateMetadata certificateMetadata, - X500Name issuerName, - PublicKey certificatePublicKey, - KeyPair parentKeyPair) throws CertIOException, OperatorCreationException { - X509v3CertificateBuilder builder = builderWithBasicExtensions(certificateMetadata, issuerName, certificatePublicKey, parentKeyPair.getPublic()); - addSubjectAlternativeNameExtension(builder, certificateMetadata); - addExtendedKeyUsageExtension(builder, certificateMetadata); - return builder.build(createContentSigner(parentKeyPair.getPrivate())); - } - - private ContentSigner createContentSigner(PrivateKey privateKey) throws OperatorCreationException { - return new JcaContentSignerBuilder(algorithmKit.getSignatureAlgorithmName()) - .setProvider(securityProvider) - .build(privateKey); - } - - private void addExtendedKeyUsageExtension(X509v3CertificateBuilder builder, CertificateMetadata certificateMetadata) throws CertIOException { - if(certificateMetadata.hasExtendedKeyUsage()) { - builder.addExtension(Extension.extendedKeyUsage, true, certificateMetadata.getExtendedKeyUsage()); - } - } - - private X509v3CertificateBuilder builderWithBasicExtensions(CertificateMetadata certificateMetadata, - X500Name issuerName, - PublicKey certificatePublicKey, - PublicKey parentPublicKey) throws CertIOException { - X500Name subjectName = stringToX500Name(certificateMetadata.getSubject()); - Date validityStartDate = new Date(System.currentTimeMillis() - (24 * 3600 * 1000)); - Date validityEndDate = getEndDate(validityStartDate, certificateMetadata.getValidityDays()); - - BigInteger certificateSerialNumber = generateNextCertificateSerialNumber(); - return new X509v3CertificateBuilder(issuerName, certificateSerialNumber, validityStartDate, - validityEndDate, subjectName, SubjectPublicKeyInfo.getInstance(certificatePublicKey.getEncoded())) - .addExtension(Extension.basicConstraints, true, new BasicConstraints(certificateMetadata.isBasicConstrainIsCa())) - .addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(parentPublicKey)) - .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certificatePublicKey)) - .addExtension(Extension.keyUsage, true, certificateMetadata.asKeyUsage()); - } - - private void addSubjectAlternativeNameExtension(X509v3CertificateBuilder builder, CertificateMetadata metadata) throws CertIOException { - if(metadata.hasSubjectAlternativeNameExtension()){ - DERSequence subjectAlternativeNames = metadata.createSubjectAlternativeNames(); - builder.addExtension(Extension.subjectAlternativeName, false, subjectAlternativeNames); - } - } - - private Date getEndDate(Date startDate, int validityDays) { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(startDate); - calendar.add(Calendar.DATE, validityDays); - return calendar.getTime(); - } - - private static JcaX509ExtensionUtils getExtUtils() { - try { - return new JcaX509ExtensionUtils(); - } catch (NoSuchAlgorithmException e) { - log.error("Getting certificate extension utils failed", e); - throw new RuntimeException("Getting certificate extension utils failed", e); - } - } - - private X500Name stringToX500Name(String distinguishedName) { - if (Strings.isNullOrEmpty(distinguishedName)) { - throw new RuntimeException("No DN (distinguished name) must not be null or empty"); - } - try { - return new X500Name(RFC4519Style.INSTANCE, distinguishedName); - } catch (IllegalArgumentException e) { - String message = String.format("Invalid DN (distinguished name) specified for %s certificate.", distinguishedName); - throw new RuntimeException(message, e); - } - } - - private BigInteger generateNextCertificateSerialNumber() { - return BigInteger.valueOf(ID_COUNTER.incrementAndGet()); - } + private static final Logger log = LogManager.getLogger(CertificatesIssuer.class); + + private static final AtomicLong ID_COUNTER = new AtomicLong(System.currentTimeMillis()); + + private final Provider securityProvider; + private final AlgorithmKit algorithmKit; + private final JcaX509ExtensionUtils extUtils; + + CertificatesIssuer(Provider securityProvider, AlgorithmKit algorithmKit) { + this.securityProvider = securityProvider; + this.algorithmKit = algorithmKit; + this.extUtils = getExtUtils(); + } + + /** + * The method creates a certificate with provided metadata and public key obtained from {@link #algorithmKit}. The result of invocation + * contains required data to use a certificate by its owner. + * + * @param certificateMetadata metadata which should be embedded into created certificate + * @return {@link CertificateData} which contain certificate and private key associated with the certificate. + */ + public CertificateData issueSelfSignedCertificate(CertificateMetadata certificateMetadata) { + try { + KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); + X500Name issuerName = stringToX500Name(requireNonNull(certificateMetadata.getSubject(), "Certificate metadata are required.")); + X509CertificateHolder x509CertificateHolder = buildCertificateHolder( + certificateMetadata, + issuerName, + publicAndPrivateKey.getPublic(), + publicAndPrivateKey + ); + return new CertificateData(x509CertificateHolder, publicAndPrivateKey); + } catch (OperatorCreationException | CertIOException e) { + log.error("Error while generating certificate", e); + throw new RuntimeException("Error while generating self signed certificate", e); + } + } + + /** + * The method is similar to {@link #issueSignedCertificate(CertificateMetadata, CertificateData)} but additionally it signs created + * certificate using data from parentCertificateData. + * + * @param metadata metadata which should be embedded into created certificate + * @param parentCertificateData data required to signe a newly issued certificate (private key among others things). + * @return {@link CertificateData} which contain certificate and private key associated with the certificate. + */ + public CertificateData issueSignedCertificate(CertificateMetadata metadata, CertificateData parentCertificateData) { + try { + KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); + KeyPair parentKeyPair = requireNonNull(parentCertificateData, "Issuer certificate data are required").getKeyPair(); + X500Name issuerName = parentCertificateData.getCertificateSubject(); + var x509CertificateHolder = buildCertificateHolder( + requireNonNull(metadata, "Certificate metadata are required"), + issuerName, + publicAndPrivateKey.getPublic(), + parentKeyPair + ); + return new CertificateData(x509CertificateHolder, publicAndPrivateKey); + } catch (OperatorCreationException | CertIOException e) { + log.error("Error while generating signed certificate", e); + throw new RuntimeException("Error while generating signed certificate", e); + } + } + + private X509CertificateHolder buildCertificateHolder( + CertificateMetadata certificateMetadata, + X500Name issuerName, + PublicKey certificatePublicKey, + KeyPair parentKeyPair + ) throws CertIOException, OperatorCreationException { + X509v3CertificateBuilder builder = builderWithBasicExtensions( + certificateMetadata, + issuerName, + certificatePublicKey, + parentKeyPair.getPublic() + ); + addSubjectAlternativeNameExtension(builder, certificateMetadata); + addExtendedKeyUsageExtension(builder, certificateMetadata); + return builder.build(createContentSigner(parentKeyPair.getPrivate())); + } + + private ContentSigner createContentSigner(PrivateKey privateKey) throws OperatorCreationException { + return new JcaContentSignerBuilder(algorithmKit.getSignatureAlgorithmName()).setProvider(securityProvider).build(privateKey); + } + + private void addExtendedKeyUsageExtension(X509v3CertificateBuilder builder, CertificateMetadata certificateMetadata) + throws CertIOException { + if (certificateMetadata.hasExtendedKeyUsage()) { + builder.addExtension(Extension.extendedKeyUsage, true, certificateMetadata.getExtendedKeyUsage()); + } + } + + private X509v3CertificateBuilder builderWithBasicExtensions( + CertificateMetadata certificateMetadata, + X500Name issuerName, + PublicKey certificatePublicKey, + PublicKey parentPublicKey + ) throws CertIOException { + X500Name subjectName = stringToX500Name(certificateMetadata.getSubject()); + Date validityStartDate = new Date(System.currentTimeMillis() - (24 * 3600 * 1000)); + Date validityEndDate = getEndDate(validityStartDate, certificateMetadata.getValidityDays()); + + BigInteger certificateSerialNumber = generateNextCertificateSerialNumber(); + return new X509v3CertificateBuilder( + issuerName, + certificateSerialNumber, + validityStartDate, + validityEndDate, + subjectName, + SubjectPublicKeyInfo.getInstance(certificatePublicKey.getEncoded()) + ).addExtension(Extension.basicConstraints, true, new BasicConstraints(certificateMetadata.isBasicConstrainIsCa())) + .addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(parentPublicKey)) + .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certificatePublicKey)) + .addExtension(Extension.keyUsage, true, certificateMetadata.asKeyUsage()); + } + + private void addSubjectAlternativeNameExtension(X509v3CertificateBuilder builder, CertificateMetadata metadata) throws CertIOException { + if (metadata.hasSubjectAlternativeNameExtension()) { + DERSequence subjectAlternativeNames = metadata.createSubjectAlternativeNames(); + builder.addExtension(Extension.subjectAlternativeName, false, subjectAlternativeNames); + } + } + + private Date getEndDate(Date startDate, int validityDays) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(startDate); + calendar.add(Calendar.DATE, validityDays); + return calendar.getTime(); + } + + private static JcaX509ExtensionUtils getExtUtils() { + try { + return new JcaX509ExtensionUtils(); + } catch (NoSuchAlgorithmException e) { + log.error("Getting certificate extension utils failed", e); + throw new RuntimeException("Getting certificate extension utils failed", e); + } + } + + private X500Name stringToX500Name(String distinguishedName) { + if (Strings.isNullOrEmpty(distinguishedName)) { + throw new RuntimeException("No DN (distinguished name) must not be null or empty"); + } + try { + return new X500Name(RFC4519Style.INSTANCE, distinguishedName); + } catch (IllegalArgumentException e) { + String message = String.format("Invalid DN (distinguished name) specified for %s certificate.", distinguishedName); + throw new RuntimeException(message, e); + } + } + + private BigInteger generateNextCertificateSerialNumber() { + return BigInteger.valueOf(ID_COUNTER.incrementAndGet()); + } } // CS-ENFORCE-SINGLE diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java index 823a0c04ca..f68ccf6022 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java @@ -24,45 +24,45 @@ */ class CertificatesIssuerFactory { - private static final int KEY_SIZE = 2048; + private static final int KEY_SIZE = 2048; - private CertificatesIssuerFactory() { + private CertificatesIssuerFactory() { - } + } - private static final Provider DEFAULT_SECURITY_PROVIDER = new BouncyCastleProvider(); + private static final Provider DEFAULT_SECURITY_PROVIDER = new BouncyCastleProvider(); - /** - * @see {@link #rsaBaseCertificateIssuer(Provider)} - */ - public static CertificatesIssuer rsaBaseCertificateIssuer() { - return rsaBaseCertificateIssuer(null); - } + /** + * @see {@link #rsaBaseCertificateIssuer(Provider)} + */ + public static CertificatesIssuer rsaBaseCertificateIssuer() { + return rsaBaseCertificateIssuer(null); + } - /** - * The method creates {@link CertificatesIssuer} which uses RSA algorithm for certificate creation. - * @param securityProvider determines cryptographic algorithm implementation, can be null. - * @return new instance of {@link CertificatesIssuer} - */ - public static CertificatesIssuer rsaBaseCertificateIssuer(Provider securityProvider) { - Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); - return new CertificatesIssuer(provider, rsaSha256withRsa(provider, KEY_SIZE)); - } + /** + * The method creates {@link CertificatesIssuer} which uses RSA algorithm for certificate creation. + * @param securityProvider determines cryptographic algorithm implementation, can be null. + * @return new instance of {@link CertificatesIssuer} + */ + public static CertificatesIssuer rsaBaseCertificateIssuer(Provider securityProvider) { + Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); + return new CertificatesIssuer(provider, rsaSha256withRsa(provider, KEY_SIZE)); + } - /** - * {@link #rsaBaseCertificateIssuer(Provider)} - */ - public static CertificatesIssuer ecdsaBaseCertificatesIssuer() { - return ecdsaBaseCertificatesIssuer(null); - } + /** + * {@link #rsaBaseCertificateIssuer(Provider)} + */ + public static CertificatesIssuer ecdsaBaseCertificatesIssuer() { + return ecdsaBaseCertificatesIssuer(null); + } - /** - * It creates {@link CertificatesIssuer} which uses asymmetric cryptography algorithm which relays on elliptic curves. - * @param securityProvider determines cryptographic algorithm implementation, can be null. - * @return new instance of {@link CertificatesIssuer} - */ - public static CertificatesIssuer ecdsaBaseCertificatesIssuer(Provider securityProvider) { - Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); - return new CertificatesIssuer(provider, ecdsaSha256withEcdsa(securityProvider, "P-384")); - } + /** + * It creates {@link CertificatesIssuer} which uses asymmetric cryptography algorithm which relays on elliptic curves. + * @param securityProvider determines cryptographic algorithm implementation, can be null. + * @return new instance of {@link CertificatesIssuer} + */ + public static CertificatesIssuer ecdsaBaseCertificatesIssuer(Provider securityProvider) { + Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); + return new CertificatesIssuer(provider, ecdsaSha256withEcdsa(securityProvider, "P-384")); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java index a92e2036d7..749ab232bc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java @@ -53,68 +53,67 @@ */ class PemConverter { - private PemConverter() { - } + private PemConverter() {} - private static final Logger log = LogManager.getLogger(PemConverter.class); - private static final SecureRandom secureRandom = new SecureRandom(); + private static final Logger log = LogManager.getLogger(PemConverter.class); + private static final SecureRandom secureRandom = new SecureRandom(); - /** - * It converts certificate represented by {@link X509CertificateHolder} object to PEM format - * @param certificate is a certificate to convert - * @return {@link String} which contains PEM encoded certificate - */ - public static String toPem(X509CertificateHolder certificate) { - StringWriter stringWriter = new StringWriter(); - try (JcaPEMWriter writer = new JcaPEMWriter(stringWriter)) { - writer.writeObject(requireNonNull(certificate, "Certificate is required.")); - } catch (Exception e) { - throw new RuntimeException("Cannot write certificate in PEM format", e); - } - return stringWriter.toString(); - } + /** + * It converts certificate represented by {@link X509CertificateHolder} object to PEM format + * @param certificate is a certificate to convert + * @return {@link String} which contains PEM encoded certificate + */ + public static String toPem(X509CertificateHolder certificate) { + StringWriter stringWriter = new StringWriter(); + try (JcaPEMWriter writer = new JcaPEMWriter(stringWriter)) { + writer.writeObject(requireNonNull(certificate, "Certificate is required.")); + } catch (Exception e) { + throw new RuntimeException("Cannot write certificate in PEM format", e); + } + return stringWriter.toString(); + } - /** - * It converts private key represented by class {@link PrivateKey} to PEM format. - * @param privateKey is a private key, cannot be null - * @param privateKeyPassword is a password used to encode private key, null for unencrypted private key - * @return {@link String} which contains PEM encoded private key - */ - public static String toPem(PrivateKey privateKey, String privateKeyPassword) { - try(StringWriter stringWriter = new StringWriter()){ - savePrivateKey(stringWriter, requireNonNull(privateKey, "Private key is required."), privateKeyPassword); - return stringWriter.toString(); - } catch (IOException e) { - throw new RuntimeException("Cannot convert private key into PEM format.", e); - } - } + /** + * It converts private key represented by class {@link PrivateKey} to PEM format. + * @param privateKey is a private key, cannot be null + * @param privateKeyPassword is a password used to encode private key, null for unencrypted private key + * @return {@link String} which contains PEM encoded private key + */ + public static String toPem(PrivateKey privateKey, String privateKeyPassword) { + try (StringWriter stringWriter = new StringWriter()) { + savePrivateKey(stringWriter, requireNonNull(privateKey, "Private key is required."), privateKeyPassword); + return stringWriter.toString(); + } catch (IOException e) { + throw new RuntimeException("Cannot convert private key into PEM format.", e); + } + } - private static void savePrivateKey(Writer out, PrivateKey privateKey, String privateKeyPassword) { - try (JcaPEMWriter writer = new JcaPEMWriter(out)) { - writer.writeObject(createPkcs8PrivateKeyPem(privateKey, privateKeyPassword)); - } catch (Exception e) { - log.error("Error while writing private key.", e); - throw new RuntimeException("Error while writing private key ", e); - } - } + private static void savePrivateKey(Writer out, PrivateKey privateKey, String privateKeyPassword) { + try (JcaPEMWriter writer = new JcaPEMWriter(out)) { + writer.writeObject(createPkcs8PrivateKeyPem(privateKey, privateKeyPassword)); + } catch (Exception e) { + log.error("Error while writing private key.", e); + throw new RuntimeException("Error while writing private key ", e); + } + } - private static PemObject createPkcs8PrivateKeyPem(PrivateKey privateKey, String password) { - try { - OutputEncryptor outputEncryptor = password == null ? null : getPasswordEncryptor(password); - return new PKCS8Generator(PrivateKeyInfo.getInstance(privateKey.getEncoded()), outputEncryptor).generate(); - } catch (PemGenerationException | OperatorCreationException e) { - log.error("Creating PKCS8 private key failed", e); - throw new RuntimeException("Creating PKCS8 private key failed", e); - } - } + private static PemObject createPkcs8PrivateKeyPem(PrivateKey privateKey, String password) { + try { + OutputEncryptor outputEncryptor = password == null ? null : getPasswordEncryptor(password); + return new PKCS8Generator(PrivateKeyInfo.getInstance(privateKey.getEncoded()), outputEncryptor).generate(); + } catch (PemGenerationException | OperatorCreationException e) { + log.error("Creating PKCS8 private key failed", e); + throw new RuntimeException("Creating PKCS8 private key failed", e); + } + } - private static OutputEncryptor getPasswordEncryptor(String password) throws OperatorCreationException { - if (!Strings.isNullOrEmpty(password)) { - JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.PBE_SHA1_3DES); - encryptorBuilder.setRandom(secureRandom); - encryptorBuilder.setPassword(password.toCharArray()); - return encryptorBuilder.build(); - } - return null; - } + private static OutputEncryptor getPasswordEncryptor(String password) throws OperatorCreationException { + if (!Strings.isNullOrEmpty(password)) { + JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.PBE_SHA1_3DES); + encryptorBuilder.setRandom(secureRandom); + encryptorBuilder.setPassword(password.toCharArray()); + return encryptorBuilder.build(); + } + return null; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java index 9ee2ec8a02..af37c66001 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java @@ -28,47 +28,48 @@ */ // CS-ENFORCE-SINGLE enum PublicKeyUsage { - DIGITAL_SIGNATURE(KeyUsage.digitalSignature), - KEY_CERT_SIGN(KeyUsage.keyCertSign), - CRL_SIGN(KeyUsage.cRLSign), - NON_REPUDIATION(KeyUsage.nonRepudiation), - KEY_ENCIPHERMENT(KeyUsage.keyEncipherment), + DIGITAL_SIGNATURE(KeyUsage.digitalSignature), + KEY_CERT_SIGN(KeyUsage.keyCertSign), + CRL_SIGN(KeyUsage.cRLSign), + NON_REPUDIATION(KeyUsage.nonRepudiation), + KEY_ENCIPHERMENT(KeyUsage.keyEncipherment), - SERVER_AUTH(KeyPurposeId.id_kp_serverAuth), + SERVER_AUTH(KeyPurposeId.id_kp_serverAuth), - CLIENT_AUTH(KeyPurposeId.id_kp_clientAuth); + CLIENT_AUTH(KeyPurposeId.id_kp_clientAuth); - private final int keyUsage; - private final KeyPurposeId id; + private final int keyUsage; + private final KeyPurposeId id; - PublicKeyUsage(int keyUsage) { - this.keyUsage = keyUsage; - this.id = null; - } + PublicKeyUsage(int keyUsage) { + this.keyUsage = keyUsage; + this.id = null; + } - PublicKeyUsage(KeyPurposeId id) { - this.id = Objects.requireNonNull(id, "Key purpose id is required."); - this.keyUsage = 0; - } + PublicKeyUsage(KeyPurposeId id) { + this.id = Objects.requireNonNull(id, "Key purpose id is required."); + this.keyUsage = 0; + } - boolean isExtendedUsage() { - return this.id != null; - } + boolean isExtendedUsage() { + return this.id != null; + } - boolean isNotExtendedUsage() { - return this.id == null; - } + boolean isNotExtendedUsage() { + return this.id == null; + } - int asInt(){ - if(isExtendedUsage()) { - throw new RuntimeException("Integer value is not available for extended key usage"); - } - return keyUsage; - } - KeyPurposeId getKeyPurposeId() { - if(isExtendedUsage() == false){ - throw new RuntimeException("Key purpose id is not available."); - } - return id; - } + int asInt() { + if (isExtendedUsage()) { + throw new RuntimeException("Integer value is not available for extended key usage"); + } + return keyUsage; + } + + KeyPurposeId getKeyPurposeId() { + if (isExtendedUsage() == false) { + throw new RuntimeException("Key purpose id is not available."); + } + return id; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java index bc5f5f267d..2dd1dd5eea 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java @@ -53,169 +53,162 @@ */ public class TestCertificates { - private static final Logger log = LogManager.getLogger(TestCertificates.class); - - public static final Integer MAX_NUMBER_OF_NODE_CERTIFICATES = 3; - - private static final String CA_SUBJECT = "DC=com,DC=example,O=Example Com Inc.,OU=Example Com Inc. Root CA,CN=Example Com Inc. Root CA"; - private static final String ADMIN_DN = "CN=kirk,OU=client,O=client,L=test,C=de"; - private static final int CERTIFICATE_VALIDITY_DAYS = 365; - private static final String CERTIFICATE_FILE_EXT = ".cert"; - private static final String KEY_FILE_EXT = ".key"; - private final CertificateData caCertificate; - private final CertificateData adminCertificate; - private final List nodeCertificates; - - private final CertificateData ldapCertificate; - - public TestCertificates() { - this.caCertificate = createCaCertificate(); - this.nodeCertificates = IntStream.range(0, MAX_NUMBER_OF_NODE_CERTIFICATES) - .mapToObj(this::createNodeCertificate) - .collect(Collectors.toList()); - this.ldapCertificate = createLdapCertificate(); - this.adminCertificate = createAdminCertificate(ADMIN_DN); - log.info("Test certificates successfully generated"); - } - - private CertificateData createCaCertificate() { - CertificateMetadata metadata = CertificateMetadata.basicMetadata(CA_SUBJECT, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(true, DIGITAL_SIGNATURE, KEY_CERT_SIGN, CRL_SIGN); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSelfSignedCertificate(metadata); - } - - public CertificateData createAdminCertificate(String adminDn) { - CertificateMetadata metadata = CertificateMetadata.basicMetadata(adminDn, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSignedCertificate(metadata, caCertificate); - } - - public CertificateData createSelfSignedCertificate(String distinguishedName) { - CertificateMetadata metadata = CertificateMetadata.basicMetadata(distinguishedName, CERTIFICATE_VALIDITY_DAYS); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSelfSignedCertificate(metadata); - } - - /** - * It returns the most trusted certificate. Certificates for nodes and users are derived from this certificate. - * @return file which contains certificate in PEM format, defined by RFC 1421 - */ - public File getRootCertificate() { - return createTempFile("root", CERTIFICATE_FILE_EXT, caCertificate.certificateInPemFormat()); - } - - public CertificateData getRootCertificateData() { - return caCertificate; - } - - /** - * Certificate for Open Search node. The certificate is derived from root certificate, returned by method {@link #getRootCertificate()} - * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} - * @return file which contains certificate in PEM format, defined by RFC 1421 - */ - public File getNodeCertificate(int node) { - CertificateData certificateData = getNodeCertificateData(node); - return createTempFile("node-" + node, CERTIFICATE_FILE_EXT, certificateData.certificateInPemFormat()); - } - - public CertificateData getNodeCertificateData(int node) { - isCorrectNodeNumber(node); - return nodeCertificates.get(node); - } - - private void isCorrectNodeNumber(int node) { - if (node >= MAX_NUMBER_OF_NODE_CERTIFICATES) { - String message = String.format("Cannot get certificate for node %d, number of created certificates for nodes is %d", node, - MAX_NUMBER_OF_NODE_CERTIFICATES); - throw new RuntimeException(message); - } - } - - private CertificateData createNodeCertificate(Integer node) { - String subject = String.format("DC=de,L=test,O=node,OU=node,CN=node-%d.example.com", node); - String domain = String.format("node-%d.example.com", node); - CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) - .withSubjectAlternativeName("1.2.3.4.5.5", List.of(domain, "localhost"), "127.0.0.1"); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSignedCertificate(metadata, caCertificate); - } - - public CertificateData issueUserCertificate(String organizationUnit, String username) { - String subject = String.format("DC=de,L=test,O=users,OU=%s,CN=%s", organizationUnit, username); - CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS).withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH); - return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); - } - - private CertificateData createLdapCertificate() { - String subject = "DC=de,L=test,O=node,OU=node,CN=ldap.example.com"; - CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) - .withSubjectAlternativeName(null, List.of("localhost"), "127.0.0.1"); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSignedCertificate(metadata, caCertificate); - } - - - public CertificateData getLdapCertificateData() { - return ldapCertificate; - } - - /** - * It returns private key associated with node certificate returned by method {@link #getNodeCertificate(int)} - * - * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} - * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. - * @return file which contains private key encoded in PEM format, defined - * by RFC 1421 - */ - public File getNodeKey(int node, String privateKeyPassword) { - CertificateData certificateData = nodeCertificates.get(node); - return createTempFile("node-" + node, KEY_FILE_EXT, certificateData.privateKeyInPemFormat(privateKeyPassword)); - } - - /** - * Certificate which proofs admin user identity. Certificate is derived from root certificate returned by - * method {@link #getRootCertificate()} - * @return file which contains certificate in PEM format, defined by RFC 1421 - */ - public File getAdminCertificate() { - return createTempFile("admin", CERTIFICATE_FILE_EXT, adminCertificate.certificateInPemFormat()); - } - - public CertificateData getAdminCertificateData() { - return adminCertificate; - } - - /** - * It returns private key associated with admin certificate returned by {@link #getAdminCertificate()}. - * - * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. - * @return file which contains private key encoded in PEM format, defined - * by RFC 1421 - */ - public File getAdminKey(String privateKeyPassword) { - return createTempFile("admin", KEY_FILE_EXT, adminCertificate.privateKeyInPemFormat(privateKeyPassword)); - } - - public String[] getAdminDNs() { - return new String[] {ADMIN_DN}; - } - - private File createTempFile(String name, String suffix, String contents) { - try { - Path path = Files.createTempFile(name, suffix); - Files.writeString(path, contents); - return path.toFile(); - } catch (IOException ex) { - throw new RuntimeException("Cannot create temp file with name " + name + " and suffix " + suffix); - } - } + private static final Logger log = LogManager.getLogger(TestCertificates.class); + + public static final Integer MAX_NUMBER_OF_NODE_CERTIFICATES = 3; + + private static final String CA_SUBJECT = "DC=com,DC=example,O=Example Com Inc.,OU=Example Com Inc. Root CA,CN=Example Com Inc. Root CA"; + private static final String ADMIN_DN = "CN=kirk,OU=client,O=client,L=test,C=de"; + private static final int CERTIFICATE_VALIDITY_DAYS = 365; + private static final String CERTIFICATE_FILE_EXT = ".cert"; + private static final String KEY_FILE_EXT = ".key"; + private final CertificateData caCertificate; + private final CertificateData adminCertificate; + private final List nodeCertificates; + + private final CertificateData ldapCertificate; + + public TestCertificates() { + this.caCertificate = createCaCertificate(); + this.nodeCertificates = IntStream.range(0, MAX_NUMBER_OF_NODE_CERTIFICATES) + .mapToObj(this::createNodeCertificate) + .collect(Collectors.toList()); + this.ldapCertificate = createLdapCertificate(); + this.adminCertificate = createAdminCertificate(ADMIN_DN); + log.info("Test certificates successfully generated"); + } + + private CertificateData createCaCertificate() { + CertificateMetadata metadata = CertificateMetadata.basicMetadata(CA_SUBJECT, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(true, DIGITAL_SIGNATURE, KEY_CERT_SIGN, CRL_SIGN); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSelfSignedCertificate(metadata); + } + + public CertificateData createAdminCertificate(String adminDn) { + CertificateMetadata metadata = CertificateMetadata.basicMetadata(adminDn, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + public CertificateData createSelfSignedCertificate(String distinguishedName) { + CertificateMetadata metadata = CertificateMetadata.basicMetadata(distinguishedName, CERTIFICATE_VALIDITY_DAYS); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSelfSignedCertificate(metadata); + } + + /** + * It returns the most trusted certificate. Certificates for nodes and users are derived from this certificate. + * @return file which contains certificate in PEM format, defined by RFC 1421 + */ + public File getRootCertificate() { + return createTempFile("root", CERTIFICATE_FILE_EXT, caCertificate.certificateInPemFormat()); + } + + public CertificateData getRootCertificateData() { + return caCertificate; + } + + /** + * Certificate for Open Search node. The certificate is derived from root certificate, returned by method {@link #getRootCertificate()} + * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} + * @return file which contains certificate in PEM format, defined by RFC 1421 + */ + public File getNodeCertificate(int node) { + CertificateData certificateData = getNodeCertificateData(node); + return createTempFile("node-" + node, CERTIFICATE_FILE_EXT, certificateData.certificateInPemFormat()); + } + + public CertificateData getNodeCertificateData(int node) { + isCorrectNodeNumber(node); + return nodeCertificates.get(node); + } + + private void isCorrectNodeNumber(int node) { + if (node >= MAX_NUMBER_OF_NODE_CERTIFICATES) { + String message = String.format( + "Cannot get certificate for node %d, number of created certificates for nodes is %d", + node, + MAX_NUMBER_OF_NODE_CERTIFICATES + ); + throw new RuntimeException(message); + } + } + + private CertificateData createNodeCertificate(Integer node) { + String subject = String.format("DC=de,L=test,O=node,OU=node,CN=node-%d.example.com", node); + String domain = String.format("node-%d.example.com", node); + CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) + .withSubjectAlternativeName("1.2.3.4.5.5", List.of(domain, "localhost"), "127.0.0.1"); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + public CertificateData issueUserCertificate(String organizationUnit, String username) { + String subject = String.format("DC=de,L=test,O=users,OU=%s,CN=%s", organizationUnit, username); + CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + private CertificateData createLdapCertificate() { + String subject = "DC=de,L=test,O=node,OU=node,CN=ldap.example.com"; + CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) + .withSubjectAlternativeName(null, List.of("localhost"), "127.0.0.1"); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + public CertificateData getLdapCertificateData() { + return ldapCertificate; + } + + /** + * It returns private key associated with node certificate returned by method {@link #getNodeCertificate(int)} + * + * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} + * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. + * @return file which contains private key encoded in PEM format, defined + * by RFC 1421 + */ + public File getNodeKey(int node, String privateKeyPassword) { + CertificateData certificateData = nodeCertificates.get(node); + return createTempFile("node-" + node, KEY_FILE_EXT, certificateData.privateKeyInPemFormat(privateKeyPassword)); + } + + /** + * Certificate which proofs admin user identity. Certificate is derived from root certificate returned by + * method {@link #getRootCertificate()} + * @return file which contains certificate in PEM format, defined by RFC 1421 + */ + public File getAdminCertificate() { + return createTempFile("admin", CERTIFICATE_FILE_EXT, adminCertificate.certificateInPemFormat()); + } + + public CertificateData getAdminCertificateData() { + return adminCertificate; + } + + /** + * It returns private key associated with admin certificate returned by {@link #getAdminCertificate()}. + * + * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. + * @return file which contains private key encoded in PEM format, defined + * by RFC 1421 + */ + public File getAdminKey(String privateKeyPassword) { + return createTempFile("admin", KEY_FILE_EXT, adminCertificate.privateKeyInPemFormat(privateKeyPassword)); + } + + public String[] getAdminDNs() { + return new String[] { ADMIN_DN }; + } + + private File createTempFile(String name, String suffix, String contents) { + try { + Path path = Files.createTempFile(name, suffix); + Files.writeString(path, contents); + return path.toFile(); + } catch (IOException ex) { + throw new RuntimeException("Cannot create temp file with name " + name + " and suffix " + suffix); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java index e0e57d2ef1..ed236dcd0c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java @@ -27,44 +27,50 @@ class CloseableHttpClientFactory { - private final SSLContext sslContext; + private final SSLContext sslContext; - private final RequestConfig requestConfig; + private final RequestConfig requestConfig; - private final HttpRoutePlanner routePlanner; + private final HttpRoutePlanner routePlanner; - private final String[] supportedCipherSuit; + private final String[] supportedCipherSuit; - public CloseableHttpClientFactory(SSLContext sslContext, - RequestConfig requestConfig, - HttpRoutePlanner routePlanner, - String[] supportedCipherSuit) { - this.sslContext = Objects.requireNonNull(sslContext, "SSL context is required."); - this.requestConfig = requestConfig; - this.routePlanner = routePlanner; - this.supportedCipherSuit = supportedCipherSuit; - } + public CloseableHttpClientFactory( + SSLContext sslContext, + RequestConfig requestConfig, + HttpRoutePlanner routePlanner, + String[] supportedCipherSuit + ) { + this.sslContext = Objects.requireNonNull(sslContext, "SSL context is required."); + this.requestConfig = requestConfig; + this.routePlanner = routePlanner; + this.supportedCipherSuit = supportedCipherSuit; + } - public CloseableHttpClient getHTTPClient() { + public CloseableHttpClient getHTTPClient() { - final HttpClientBuilder hcb = HttpClients.custom(); + final HttpClientBuilder hcb = HttpClients.custom(); - final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(this.sslContext, null, supportedCipherSuit, - NoopHostnameVerifier.INSTANCE); + final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( + this.sslContext, + null, + supportedCipherSuit, + NoopHostnameVerifier.INSTANCE + ); - final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(sslsf) - .setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(60, TimeUnit.SECONDS).build()) - .build(); - hcb.setConnectionManager(cm); - if(routePlanner != null) { - hcb.setRoutePlanner(routePlanner); - } + final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(sslsf) + .setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(60, TimeUnit.SECONDS).build()) + .build(); + hcb.setConnectionManager(cm); + if (routePlanner != null) { + hcb.setRoutePlanner(routePlanner); + } - if (requestConfig != null) { - hcb.setDefaultRequestConfig(requestConfig); - } + if (requestConfig != null) { + hcb.setDefaultRequestConfig(requestConfig); + } - return hcb.build(); - } + return hcb.build(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java index 35c5229bfb..dff40e395c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH -* +* * 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 -* +* * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software @@ -12,7 +12,7 @@ * 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. -* +* */ /* @@ -52,105 +52,121 @@ import static org.opensearch.test.framework.cluster.NodeType.DATA; public enum ClusterManager { - //3 nodes (1m, 2d) - DEFAULT(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA)), - - //1 node (1md) - SINGLENODE(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA)), - - SINGLE_REMOTE_CLIENT(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA, NodeRole.REMOTE_CLUSTER_CLIENT)), - - //4 node (1m, 2d, 1c) - CLIENTNODE(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA), new NodeSettings()), - - THREE_CLUSTER_MANAGERS(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA)); - - private List nodeSettings = new LinkedList<>(); - - private ClusterManager(NodeSettings... settings) { - nodeSettings.addAll(Arrays.asList(settings)); - } - - public List getNodeSettings() { - return unmodifiableList(nodeSettings); - } - - public List getClusterManagerNodeSettings() { - return unmodifiableList(nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); - } - - public List getNonClusterManagerNodeSettings() { - return unmodifiableList(nodeSettings.stream().filter(a -> !a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); - } - - public int getNodes() { - return nodeSettings.size(); - } - - public int getClusterManagerNodes() { - return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).count(); - } - - public int getDataNodes() { - return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.DATA)).count(); - } - - public int getClientNodes() { - return (int) nodeSettings.stream().filter(a -> a.isClientNode()).count(); - } - - - public static class NodeSettings { - - private final static List> DEFAULT_PLUGINS = List.of(Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, - MatrixAggregationModulePlugin.class, ParentJoinModulePlugin.class, PercolatorModulePlugin.class, ReindexModulePlugin.class); - - private final Set roles; - public final List> plugins; - - public NodeSettings(NodeRole...roles) { - this(roles.length == 0 ? Collections.emptySet() : EnumSet.copyOf(Arrays.asList(roles)), Collections.emptyList()); - } - - public NodeSettings(Set roles, List> additionalPlugins) { - super(); - this.roles = Objects.requireNonNull(roles, "Node roles set must not be null"); - this.plugins = mergePlugins(additionalPlugins, DEFAULT_PLUGINS); - } - - public boolean containRole(NodeRole nodeRole) { - return roles.contains(nodeRole); - } - - public boolean isClientNode() { - return (roles.contains(NodeRole.DATA) == false) && (roles.contains(NodeRole.CLUSTER_MANAGER)); - } - - NodeType recognizeNodeType() { - if (roles.contains(NodeRole.CLUSTER_MANAGER)) { - return CLUSTER_MANAGER; - } else if (roles.contains(NodeRole.DATA)) { - return DATA; - } else { - return CLIENT; - } - } - - private List> mergePlugins(Collection>...plugins) { - List> mergedPlugins = Arrays.stream(plugins) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - return unmodifiableList(mergedPlugins); - } - - @SuppressWarnings("unchecked") - public Class[] getPlugins() { - return plugins.toArray(new Class[0]); - } - - public Class[] pluginsWithAddition(List> additionalPlugins) { - return mergePlugins(plugins, additionalPlugins).toArray(Class[]::new); - } - } + // 3 nodes (1m, 2d) + DEFAULT(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA)), + + // 1 node (1md) + SINGLENODE(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA)), + + SINGLE_REMOTE_CLIENT(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA, NodeRole.REMOTE_CLUSTER_CLIENT)), + + // 4 node (1m, 2d, 1c) + CLIENTNODE( + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.DATA), + new NodeSettings(NodeRole.DATA), + new NodeSettings() + ), + + THREE_CLUSTER_MANAGERS( + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.DATA), + new NodeSettings(NodeRole.DATA) + ); + + private List nodeSettings = new LinkedList<>(); + + private ClusterManager(NodeSettings... settings) { + nodeSettings.addAll(Arrays.asList(settings)); + } + + public List getNodeSettings() { + return unmodifiableList(nodeSettings); + } + + public List getClusterManagerNodeSettings() { + return unmodifiableList(nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); + } + + public List getNonClusterManagerNodeSettings() { + return unmodifiableList(nodeSettings.stream().filter(a -> !a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); + } + + public int getNodes() { + return nodeSettings.size(); + } + + public int getClusterManagerNodes() { + return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).count(); + } + + public int getDataNodes() { + return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.DATA)).count(); + } + + public int getClientNodes() { + return (int) nodeSettings.stream().filter(a -> a.isClientNode()).count(); + } + + public static class NodeSettings { + + private final static List> DEFAULT_PLUGINS = List.of( + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + MatrixAggregationModulePlugin.class, + ParentJoinModulePlugin.class, + PercolatorModulePlugin.class, + ReindexModulePlugin.class + ); + + private final Set roles; + public final List> plugins; + + public NodeSettings(NodeRole... roles) { + this(roles.length == 0 ? Collections.emptySet() : EnumSet.copyOf(Arrays.asList(roles)), Collections.emptyList()); + } + + public NodeSettings(Set roles, List> additionalPlugins) { + super(); + this.roles = Objects.requireNonNull(roles, "Node roles set must not be null"); + this.plugins = mergePlugins(additionalPlugins, DEFAULT_PLUGINS); + } + + public boolean containRole(NodeRole nodeRole) { + return roles.contains(nodeRole); + } + + public boolean isClientNode() { + return (roles.contains(NodeRole.DATA) == false) && (roles.contains(NodeRole.CLUSTER_MANAGER)); + } + + NodeType recognizeNodeType() { + if (roles.contains(NodeRole.CLUSTER_MANAGER)) { + return CLUSTER_MANAGER; + } else if (roles.contains(NodeRole.DATA)) { + return DATA; + } else { + return CLIENT; + } + } + + private List> mergePlugins(Collection>... plugins) { + List> mergedPlugins = Arrays.stream(plugins) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + return unmodifiableList(mergedPlugins); + } + + @SuppressWarnings("unchecked") + public Class[] getPlugins() { + return plugins.toArray(new Class[0]); + } + + public Class[] pluginsWithAddition(List> additionalPlugins) { + return mergePlugins(plugins, additionalPlugins).toArray(Class[]::new); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java index 890de49ed7..2b05807fa2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java @@ -27,23 +27,29 @@ */ public class ContextHeaderDecoratorClient extends FilterClient { - private Map headers; - - public ContextHeaderDecoratorClient(Client in, Map headers) { - super(in); - this.headers = headers != null ? headers : Collections.emptyMap(); - } - - @Override - protected void doExecute(ActionType action, Request request, - ActionListener listener) { - - ThreadContext threadContext = threadPool().getThreadContext(); - ContextPreservingActionListener wrappedListener = new ContextPreservingActionListener<>(threadContext.newRestorableContext(true), listener); - - try (StoredContext ctx = threadContext.stashContext()) { - threadContext.putHeader(this.headers); - super.doExecute(action, request, wrappedListener); - } - } + private Map headers; + + public ContextHeaderDecoratorClient(Client in, Map headers) { + super(in); + this.headers = headers != null ? headers : Collections.emptyMap(); + } + + @Override + protected void doExecute( + ActionType action, + Request request, + ActionListener listener + ) { + + ThreadContext threadContext = threadPool().getThreadContext(); + ContextPreservingActionListener wrappedListener = new ContextPreservingActionListener<>( + threadContext.newRestorableContext(true), + listener + ); + + try (StoredContext ctx = threadContext.stashContext()) { + threadContext.putHeader(this.headers); + super.doExecute(action, request, wrappedListener); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java index ab29d3206e..9181186f52 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java @@ -23,26 +23,26 @@ */ class LocalAddressRoutePlanner extends DefaultRoutePlanner { - /** - * IP address of one of the local network interfaces. - */ - private final InetAddress localAddress; + /** + * IP address of one of the local network interfaces. + */ + private final InetAddress localAddress; - /** - * Creates {@link LocalAddressRoutePlanner} - * @param localAddress IP address of one of the local network interfaces. Client socket used by Apache HTTP client will be bind to - * address from this parameter. The parameter must not be null. - */ - public LocalAddressRoutePlanner(InetAddress localAddress) { - super(DefaultSchemePortResolver.INSTANCE); - this.localAddress = Objects.requireNonNull(localAddress); - } + /** + * Creates {@link LocalAddressRoutePlanner} + * @param localAddress IP address of one of the local network interfaces. Client socket used by Apache HTTP client will be bind to + * address from this parameter. The parameter must not be null. + */ + public LocalAddressRoutePlanner(InetAddress localAddress) { + super(DefaultSchemePortResolver.INSTANCE); + this.localAddress = Objects.requireNonNull(localAddress); + } - /** - * Determines IP address used by the client socket of Apache HTTP client - */ - @Override - protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) { - return localAddress; - } + /** + * Determines IP address used by the client socket of Apache HTTP client + */ + @Override + protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) { + return localAddress; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java index e9bb7b5be5..539e15fb57 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java @@ -74,414 +74,455 @@ */ public class LocalCluster extends ExternalResource implements AutoCloseable, OpenSearchClientProvider { - private static final Logger log = LogManager.getLogger(LocalCluster.class); - - public static final String INIT_CONFIGURATION_DIR = "security.default_init.dir"; - - protected static final AtomicLong num = new AtomicLong(); - - private boolean sslOnly; - - private final List> plugins; - private final ClusterManager clusterManager; - private final TestSecurityConfig testSecurityConfig; - private Settings nodeOverride; - private final String clusterName; - private final MinimumSecuritySettingsSupplierFactory minimumOpenSearchSettingsSupplierFactory; - private final TestCertificates testCertificates; - private final List clusterDependencies; - private final Map remotes; - private volatile LocalOpenSearchCluster localOpenSearchCluster; - private final List testIndices; - - private boolean loadConfigurationIntoIndex; - - private LocalCluster(String clusterName, TestSecurityConfig testSgConfig, boolean sslOnly, Settings nodeOverride, - ClusterManager clusterManager, List> plugins, TestCertificates testCertificates, - List clusterDependencies, Map remotes, List testIndices, - boolean loadConfigurationIntoIndex, String defaultConfigurationInitDirectory) { - this.plugins = plugins; - this.testCertificates = testCertificates; - this.clusterManager = clusterManager; - this.testSecurityConfig = testSgConfig; - this.sslOnly = sslOnly; - this.nodeOverride = nodeOverride; - this.clusterName = clusterName; - this.minimumOpenSearchSettingsSupplierFactory = new MinimumSecuritySettingsSupplierFactory(testCertificates); - this.remotes = remotes; - this.clusterDependencies = clusterDependencies; - this.testIndices = testIndices; - this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; - if(StringUtils.isNoneBlank(defaultConfigurationInitDirectory)) { - System.setProperty(INIT_CONFIGURATION_DIR, defaultConfigurationInitDirectory); - } - } - - public String getSnapshotDirPath() { - return localOpenSearchCluster.getSnapshotDirPath(); - } - - @Override - public void before() throws Throwable { - if (localOpenSearchCluster == null) { - for (LocalCluster dependency : clusterDependencies) { - if (!dependency.isStarted()) { - dependency.before(); - } - } - - for (Map.Entry entry : remotes.entrySet()) { - @SuppressWarnings("resource") - InetSocketAddress transportAddress = entry.getValue().localOpenSearchCluster.clusterManagerNode().getTransportAddress(); - String key = "cluster.remote." + entry.getKey() + ".seeds"; - String value = transportAddress.getHostString() + ":" + transportAddress.getPort(); - log.info("Remote cluster '{}' added to configuration with the following seed '{}'", key, value); - nodeOverride = Settings.builder().put(nodeOverride) - .putList(key, value) - .build(); - } - start(); - } - } - - @Override - protected void after() { - System.clearProperty(INIT_CONFIGURATION_DIR); - close(); - } - - @Override - public void close() { - if (localOpenSearchCluster != null && localOpenSearchCluster.isStarted()) { - try { - localOpenSearchCluster.destroy(); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - localOpenSearchCluster = null; - } - } - } - - @Override - public String getClusterName() { - return clusterName; - } - - @Override - public InetSocketAddress getHttpAddress() { - return localOpenSearchCluster.clientNode().getHttpAddress(); - } - - public int getHttpPort() { - return getHttpAddress().getPort(); - } - - @Override - public InetSocketAddress getTransportAddress() { - return localOpenSearchCluster.clientNode().getTransportAddress(); - } - - /** - * Returns a Client object that performs cluster-internal requests. As these requests are regard as cluster-internal, - * no authentication is performed and no user-information is attached to these requests. Thus, this client should - * be only used for preparing test environments, but not as a test subject. - */ - public Client getInternalNodeClient() { - return localOpenSearchCluster.clientNode().getInternalNodeClient(); - } - - /** - * Returns a random node of this cluster. - */ - public PluginAwareNode node() { - return this.localOpenSearchCluster.clusterManagerNode().esNode(); - } - - /** - * Returns all nodes of this cluster. - */ - public List nodes() { - return this.localOpenSearchCluster.getNodes(); - } - - public LocalOpenSearchCluster.Node getNodeByName(String name) { - return this.localOpenSearchCluster.getNodeByName(name); - } - - public boolean isStarted() { - return localOpenSearchCluster != null; - } - - public List getConfiguredUsers() { - return testSecurityConfig.getUsers(); - } - - public Random getRandom() { - return localOpenSearchCluster.getRandom(); - } - - private void start() { - try { - NodeSettingsSupplier nodeSettingsSupplier = minimumOpenSearchSettingsSupplierFactory.minimumOpenSearchSettings(sslOnly, nodeOverride); - localOpenSearchCluster = new LocalOpenSearchCluster(clusterName, clusterManager, nodeSettingsSupplier, plugins, testCertificates); - - localOpenSearchCluster.start(); - - - if (loadConfigurationIntoIndex) { - initSecurityIndex(testSecurityConfig); - } - - try (Client client = getInternalNodeClient()) { - for (TestIndex index : this.testIndices) { - index.create(client); - } - } - - } catch (Exception e) { - log.error("Local ES cluster start failed", e); - throw new RuntimeException(e); - } - } - - private void initSecurityIndex(TestSecurityConfig testSecurityConfig) { - log.info("Initializing OpenSearch Security index"); - try(Client client = new ContextHeaderDecoratorClient(this.getInternalNodeClient(), Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER , "true"))) { - testSecurityConfig.initIndex(client); - triggerConfigurationReload(client); - } - } - - public void updateUserConfiguration(List users) { - try(Client client = new ContextHeaderDecoratorClient(this.getInternalNodeClient(), Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER , "true"))) { - testSecurityConfig.updateInternalUsersConfiguration(client, users); - triggerConfigurationReload(client); - } - } - - private static void triggerConfigurationReload(Client client) { - ConfigUpdateResponse configUpdateResponse = client.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(CType.lcStringValues().toArray(new String[0]))).actionGet(); - if (configUpdateResponse.hasFailures()) { - throw new RuntimeException("ConfigUpdateResponse produced failures: " + configUpdateResponse.failures()); - } - } - - public CertificateData getAdminCertificate() { - return testCertificates.getAdminCertificateData(); - } - - public static class Builder { - - private final Settings.Builder nodeOverrideSettingsBuilder = Settings.builder(); - - private boolean sslOnly = false; - private final List> plugins = new ArrayList<>(); - private Map remoteClusters = new HashMap<>(); - private List clusterDependencies = new ArrayList<>(); - private List testIndices = new ArrayList<>(); - private ClusterManager clusterManager = ClusterManager.DEFAULT; - private TestSecurityConfig testSecurityConfig = new TestSecurityConfig(); - private String clusterName = "local_cluster"; - private TestCertificates testCertificates; - - private boolean loadConfigurationIntoIndex = true; - - private String defaultConfigurationInitDirectory = null; - - public Builder() { - } - - public Builder dependsOn(Object object) { - // We just want to make sure that the object is already done - if (object == null) { - throw new IllegalStateException("Dependency not fulfilled"); - } - return this; - } - - public Builder clusterManager(ClusterManager clusterManager) { - this.clusterManager = clusterManager; - return this; - } - - /** - * Starts a cluster with only one node and thus saves some resources during startup. This shall be only used - * for tests where the node interactions are not relevant to the test. An example for this would be - * authentication tests, as authentication is always done on the directly connected node. - */ - public Builder singleNode() { - this.clusterManager = ClusterManager.SINGLENODE; - return this; - } - - /** - * Specifies the configuration of the security plugin that shall be used by this cluster. - */ - public Builder config(TestSecurityConfig testSecurityConfig) { - this.testSecurityConfig = testSecurityConfig; - return this; - } - - public Builder sslOnly(boolean sslOnly) { - this.sslOnly = sslOnly; - return this; - } - - public Builder nodeSettings(Map settings) { - settings.forEach((key, value) -> { - if (value instanceof List) { - List values = ((List) value).stream().map(String::valueOf).collect(Collectors.toList()); - nodeOverrideSettingsBuilder.putList(key, values); - } else { - nodeOverrideSettingsBuilder.put(key, String.valueOf(value)); - } - }); - - return this; - } - - /** - * Adds additional plugins to the cluster - */ - public Builder plugin(Class plugin) { - this.plugins.add(plugin); - - return this; - } - - public Builder authFailureListeners(AuthFailureListeners listener) { - testSecurityConfig.authFailureListeners(listener); - return this; - } - - /** - * Specifies a remote cluster and its name. The remote cluster can be then used in Cross Cluster Search - * operations with the specified name. - */ - public Builder remote(String name, LocalCluster anotherCluster) { - remoteClusters.put(name, anotherCluster); - - clusterDependencies.add(anotherCluster); - - return this; - } - - /** - * Specifies test indices that shall be created upon startup of the cluster. - */ - public Builder indices(TestIndex... indices) { - this.testIndices.addAll(Arrays.asList(indices)); - return this; - } - - public Builder users(TestSecurityConfig.User... users) { - for (TestSecurityConfig.User user : users) { - testSecurityConfig.user(user); - } - return this; - } - - public Builder audit(AuditConfiguration auditConfiguration) { - if (auditConfiguration != null) { - testSecurityConfig.audit(auditConfiguration); - } - if (auditConfiguration.isEnabled()) { - nodeOverrideSettingsBuilder.put("plugins.security.audit.type", TestRuleAuditLogSink.class.getName()); - } else { - nodeOverrideSettingsBuilder.put("plugins.security.audit.type", "noop"); - } - return this; - } - - public List getUsers() { - return testSecurityConfig.getUsers(); - } - - public Builder roles(Role... roles) { - testSecurityConfig.roles(roles); - return this; - } - - public Builder rolesMapping(RolesMapping...mappings) { - testSecurityConfig.rolesMapping(mappings); - return this; - } - - public Builder authc(TestSecurityConfig.AuthcDomain authc) { - testSecurityConfig.authc(authc); - return this; - } - - public Builder authz(AuthzDomain authzDomain) { - testSecurityConfig.authz(authzDomain); - return this; - } - - public Builder clusterName(String clusterName) { - this.clusterName = clusterName; - return this; - } - - public Builder configIndexName(String configIndexName) { - testSecurityConfig.configIndexName(configIndexName); - return this; - } - - public Builder testCertificates(TestCertificates certificates) { - this.testCertificates = certificates; - return this; - } - - public Builder anonymousAuth(boolean anonAuthEnabled) { - testSecurityConfig.anonymousAuth(anonAuthEnabled); - return this; - } - - public Builder xff(XffConfig xffConfig){ - testSecurityConfig.xff(xffConfig); - return this; - } - - public Builder loadConfigurationIntoIndex(boolean loadConfigurationIntoIndex) { - this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; - return this; - } - public Builder certificates(TestCertificates certificates) { - this.testCertificates = certificates; - return this; - } - - public Builder doNotFailOnForbidden(boolean doNotFailOnForbidden) { - testSecurityConfig.doNotFailOnForbidden(doNotFailOnForbidden); - return this; - } - - public Builder defaultConfigurationInitDirectory(String defaultConfigurationInitDirectory){ - this.defaultConfigurationInitDirectory = defaultConfigurationInitDirectory; - return this; - } - - public LocalCluster build() { - try { - if(testCertificates == null) { - testCertificates = new TestCertificates(); - } - clusterName += "_" + num.incrementAndGet(); - Settings settings = nodeOverrideSettingsBuilder.build(); - return new LocalCluster(clusterName, testSecurityConfig, sslOnly, settings, clusterManager, plugins, testCertificates, - clusterDependencies, remoteClusters, testIndices, loadConfigurationIntoIndex, defaultConfigurationInitDirectory); - } catch (Exception e) { - log.error("Failed to build LocalCluster", e); - throw new RuntimeException(e); - } - } - - } - - @Override - public TestCertificates getTestCertificates() { - return testCertificates; - } + private static final Logger log = LogManager.getLogger(LocalCluster.class); + + public static final String INIT_CONFIGURATION_DIR = "security.default_init.dir"; + + protected static final AtomicLong num = new AtomicLong(); + + private boolean sslOnly; + + private final List> plugins; + private final ClusterManager clusterManager; + private final TestSecurityConfig testSecurityConfig; + private Settings nodeOverride; + private final String clusterName; + private final MinimumSecuritySettingsSupplierFactory minimumOpenSearchSettingsSupplierFactory; + private final TestCertificates testCertificates; + private final List clusterDependencies; + private final Map remotes; + private volatile LocalOpenSearchCluster localOpenSearchCluster; + private final List testIndices; + + private boolean loadConfigurationIntoIndex; + + private LocalCluster( + String clusterName, + TestSecurityConfig testSgConfig, + boolean sslOnly, + Settings nodeOverride, + ClusterManager clusterManager, + List> plugins, + TestCertificates testCertificates, + List clusterDependencies, + Map remotes, + List testIndices, + boolean loadConfigurationIntoIndex, + String defaultConfigurationInitDirectory + ) { + this.plugins = plugins; + this.testCertificates = testCertificates; + this.clusterManager = clusterManager; + this.testSecurityConfig = testSgConfig; + this.sslOnly = sslOnly; + this.nodeOverride = nodeOverride; + this.clusterName = clusterName; + this.minimumOpenSearchSettingsSupplierFactory = new MinimumSecuritySettingsSupplierFactory(testCertificates); + this.remotes = remotes; + this.clusterDependencies = clusterDependencies; + this.testIndices = testIndices; + this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; + if (StringUtils.isNoneBlank(defaultConfigurationInitDirectory)) { + System.setProperty(INIT_CONFIGURATION_DIR, defaultConfigurationInitDirectory); + } + } + + public String getSnapshotDirPath() { + return localOpenSearchCluster.getSnapshotDirPath(); + } + + @Override + public void before() throws Throwable { + if (localOpenSearchCluster == null) { + for (LocalCluster dependency : clusterDependencies) { + if (!dependency.isStarted()) { + dependency.before(); + } + } + + for (Map.Entry entry : remotes.entrySet()) { + @SuppressWarnings("resource") + InetSocketAddress transportAddress = entry.getValue().localOpenSearchCluster.clusterManagerNode().getTransportAddress(); + String key = "cluster.remote." + entry.getKey() + ".seeds"; + String value = transportAddress.getHostString() + ":" + transportAddress.getPort(); + log.info("Remote cluster '{}' added to configuration with the following seed '{}'", key, value); + nodeOverride = Settings.builder().put(nodeOverride).putList(key, value).build(); + } + start(); + } + } + + @Override + protected void after() { + System.clearProperty(INIT_CONFIGURATION_DIR); + close(); + } + + @Override + public void close() { + if (localOpenSearchCluster != null && localOpenSearchCluster.isStarted()) { + try { + localOpenSearchCluster.destroy(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + localOpenSearchCluster = null; + } + } + } + + @Override + public String getClusterName() { + return clusterName; + } + + @Override + public InetSocketAddress getHttpAddress() { + return localOpenSearchCluster.clientNode().getHttpAddress(); + } + + public int getHttpPort() { + return getHttpAddress().getPort(); + } + + @Override + public InetSocketAddress getTransportAddress() { + return localOpenSearchCluster.clientNode().getTransportAddress(); + } + + /** + * Returns a Client object that performs cluster-internal requests. As these requests are regard as cluster-internal, + * no authentication is performed and no user-information is attached to these requests. Thus, this client should + * be only used for preparing test environments, but not as a test subject. + */ + public Client getInternalNodeClient() { + return localOpenSearchCluster.clientNode().getInternalNodeClient(); + } + + /** + * Returns a random node of this cluster. + */ + public PluginAwareNode node() { + return this.localOpenSearchCluster.clusterManagerNode().esNode(); + } + + /** + * Returns all nodes of this cluster. + */ + public List nodes() { + return this.localOpenSearchCluster.getNodes(); + } + + public LocalOpenSearchCluster.Node getNodeByName(String name) { + return this.localOpenSearchCluster.getNodeByName(name); + } + + public boolean isStarted() { + return localOpenSearchCluster != null; + } + + public List getConfiguredUsers() { + return testSecurityConfig.getUsers(); + } + + public Random getRandom() { + return localOpenSearchCluster.getRandom(); + } + + private void start() { + try { + NodeSettingsSupplier nodeSettingsSupplier = minimumOpenSearchSettingsSupplierFactory.minimumOpenSearchSettings( + sslOnly, + nodeOverride + ); + localOpenSearchCluster = new LocalOpenSearchCluster( + clusterName, + clusterManager, + nodeSettingsSupplier, + plugins, + testCertificates + ); + + localOpenSearchCluster.start(); + + if (loadConfigurationIntoIndex) { + initSecurityIndex(testSecurityConfig); + } + + try (Client client = getInternalNodeClient()) { + for (TestIndex index : this.testIndices) { + index.create(client); + } + } + + } catch (Exception e) { + log.error("Local ES cluster start failed", e); + throw new RuntimeException(e); + } + } + + private void initSecurityIndex(TestSecurityConfig testSecurityConfig) { + log.info("Initializing OpenSearch Security index"); + try ( + Client client = new ContextHeaderDecoratorClient( + this.getInternalNodeClient(), + Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER, "true") + ) + ) { + testSecurityConfig.initIndex(client); + triggerConfigurationReload(client); + } + } + + public void updateUserConfiguration(List users) { + try ( + Client client = new ContextHeaderDecoratorClient( + this.getInternalNodeClient(), + Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER, "true") + ) + ) { + testSecurityConfig.updateInternalUsersConfiguration(client, users); + triggerConfigurationReload(client); + } + } + + private static void triggerConfigurationReload(Client client) { + ConfigUpdateResponse configUpdateResponse = client.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(CType.lcStringValues().toArray(new String[0])) + ).actionGet(); + if (configUpdateResponse.hasFailures()) { + throw new RuntimeException("ConfigUpdateResponse produced failures: " + configUpdateResponse.failures()); + } + } + + public CertificateData getAdminCertificate() { + return testCertificates.getAdminCertificateData(); + } + + public static class Builder { + + private final Settings.Builder nodeOverrideSettingsBuilder = Settings.builder(); + + private boolean sslOnly = false; + private final List> plugins = new ArrayList<>(); + private Map remoteClusters = new HashMap<>(); + private List clusterDependencies = new ArrayList<>(); + private List testIndices = new ArrayList<>(); + private ClusterManager clusterManager = ClusterManager.DEFAULT; + private TestSecurityConfig testSecurityConfig = new TestSecurityConfig(); + private String clusterName = "local_cluster"; + private TestCertificates testCertificates; + + private boolean loadConfigurationIntoIndex = true; + + private String defaultConfigurationInitDirectory = null; + + public Builder() {} + + public Builder dependsOn(Object object) { + // We just want to make sure that the object is already done + if (object == null) { + throw new IllegalStateException("Dependency not fulfilled"); + } + return this; + } + + public Builder clusterManager(ClusterManager clusterManager) { + this.clusterManager = clusterManager; + return this; + } + + /** + * Starts a cluster with only one node and thus saves some resources during startup. This shall be only used + * for tests where the node interactions are not relevant to the test. An example for this would be + * authentication tests, as authentication is always done on the directly connected node. + */ + public Builder singleNode() { + this.clusterManager = ClusterManager.SINGLENODE; + return this; + } + + /** + * Specifies the configuration of the security plugin that shall be used by this cluster. + */ + public Builder config(TestSecurityConfig testSecurityConfig) { + this.testSecurityConfig = testSecurityConfig; + return this; + } + + public Builder sslOnly(boolean sslOnly) { + this.sslOnly = sslOnly; + return this; + } + + public Builder nodeSettings(Map settings) { + settings.forEach((key, value) -> { + if (value instanceof List) { + List values = ((List) value).stream().map(String::valueOf).collect(Collectors.toList()); + nodeOverrideSettingsBuilder.putList(key, values); + } else { + nodeOverrideSettingsBuilder.put(key, String.valueOf(value)); + } + }); + + return this; + } + + /** + * Adds additional plugins to the cluster + */ + public Builder plugin(Class plugin) { + this.plugins.add(plugin); + + return this; + } + + public Builder authFailureListeners(AuthFailureListeners listener) { + testSecurityConfig.authFailureListeners(listener); + return this; + } + + /** + * Specifies a remote cluster and its name. The remote cluster can be then used in Cross Cluster Search + * operations with the specified name. + */ + public Builder remote(String name, LocalCluster anotherCluster) { + remoteClusters.put(name, anotherCluster); + + clusterDependencies.add(anotherCluster); + + return this; + } + + /** + * Specifies test indices that shall be created upon startup of the cluster. + */ + public Builder indices(TestIndex... indices) { + this.testIndices.addAll(Arrays.asList(indices)); + return this; + } + + public Builder users(TestSecurityConfig.User... users) { + for (TestSecurityConfig.User user : users) { + testSecurityConfig.user(user); + } + return this; + } + + public Builder audit(AuditConfiguration auditConfiguration) { + if (auditConfiguration != null) { + testSecurityConfig.audit(auditConfiguration); + } + if (auditConfiguration.isEnabled()) { + nodeOverrideSettingsBuilder.put("plugins.security.audit.type", TestRuleAuditLogSink.class.getName()); + } else { + nodeOverrideSettingsBuilder.put("plugins.security.audit.type", "noop"); + } + return this; + } + + public List getUsers() { + return testSecurityConfig.getUsers(); + } + + public Builder roles(Role... roles) { + testSecurityConfig.roles(roles); + return this; + } + + public Builder rolesMapping(RolesMapping... mappings) { + testSecurityConfig.rolesMapping(mappings); + return this; + } + + public Builder authc(TestSecurityConfig.AuthcDomain authc) { + testSecurityConfig.authc(authc); + return this; + } + + public Builder authz(AuthzDomain authzDomain) { + testSecurityConfig.authz(authzDomain); + return this; + } + + public Builder clusterName(String clusterName) { + this.clusterName = clusterName; + return this; + } + + public Builder configIndexName(String configIndexName) { + testSecurityConfig.configIndexName(configIndexName); + return this; + } + + public Builder testCertificates(TestCertificates certificates) { + this.testCertificates = certificates; + return this; + } + + public Builder anonymousAuth(boolean anonAuthEnabled) { + testSecurityConfig.anonymousAuth(anonAuthEnabled); + return this; + } + + public Builder xff(XffConfig xffConfig) { + testSecurityConfig.xff(xffConfig); + return this; + } + + public Builder loadConfigurationIntoIndex(boolean loadConfigurationIntoIndex) { + this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; + return this; + } + + public Builder certificates(TestCertificates certificates) { + this.testCertificates = certificates; + return this; + } + + public Builder doNotFailOnForbidden(boolean doNotFailOnForbidden) { + testSecurityConfig.doNotFailOnForbidden(doNotFailOnForbidden); + return this; + } + + public Builder defaultConfigurationInitDirectory(String defaultConfigurationInitDirectory) { + this.defaultConfigurationInitDirectory = defaultConfigurationInitDirectory; + return this; + } + + public LocalCluster build() { + try { + if (testCertificates == null) { + testCertificates = new TestCertificates(); + } + clusterName += "_" + num.incrementAndGet(); + Settings settings = nodeOverrideSettingsBuilder.build(); + return new LocalCluster( + clusterName, + testSecurityConfig, + sslOnly, + settings, + clusterManager, + plugins, + testCertificates, + clusterDependencies, + remoteClusters, + testIndices, + loadConfigurationIntoIndex, + defaultConfigurationInitDirectory + ); + } catch (Exception e) { + log.error("Failed to build LocalCluster", e); + throw new RuntimeException(e); + } + } + + } + + @Override + public TestCertificates getTestCertificates() { + return testCertificates; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java index 1b7befbcfc..2a4b417145 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java @@ -83,444 +83,491 @@ */ public class LocalOpenSearchCluster { - static { - System.setProperty("opensearch.enforce.bootstrap.checks", "true"); - } - - private static final Logger log = LogManager.getLogger(LocalOpenSearchCluster.class); - - private final String clusterName; - private final ClusterManager clusterManager; - private final NodeSettingsSupplier nodeSettingsSupplier; - private final List> additionalPlugins; - private final List nodes = new ArrayList<>(); - private final TestCertificates testCertificates; - - private File clusterHomeDir; - private List seedHosts; - private List initialClusterManagerHosts; - private int retry = 0; - private boolean started; - private Random random = new Random(); - - private File snapshotDir; - - public LocalOpenSearchCluster(String clusterName, ClusterManager clusterManager, NodeSettingsSupplier nodeSettingsSupplier, - List> additionalPlugins, TestCertificates testCertificates) { - this.clusterName = clusterName; - this.clusterManager = clusterManager; - this.nodeSettingsSupplier = nodeSettingsSupplier; - this.additionalPlugins = additionalPlugins; - this.testCertificates = testCertificates; - try { - createClusterDirectory(clusterName); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - public String getSnapshotDirPath() { - return snapshotDir.getAbsolutePath(); - } - - private void createClusterDirectory(String clusterName) throws IOException { - this.clusterHomeDir = Files.createTempDirectory("local_cluster_" + clusterName).toFile(); - log.debug("Cluster home directory '{}'.", clusterHomeDir.getAbsolutePath()); - this.snapshotDir = new File(this.clusterHomeDir, "snapshots"); - this.snapshotDir.mkdir(); - } - - private List getNodesByType(NodeType nodeType) { - return nodes.stream() - .filter(currentNode -> currentNode.hasAssignedType(nodeType)) - .collect(Collectors.toList()); - } - - private long countNodesByType(NodeType nodeType) { - return getNodesByType(nodeType).stream().count(); - } - - public void start() throws Exception { - log.info("Starting {}", clusterName); - - int clusterManagerNodeCount = clusterManager.getClusterManagerNodes(); - int nonClusterManagerNodeCount = clusterManager.getDataNodes() + clusterManager.getClientNodes(); - - SortedSet clusterManagerNodeTransportPorts = TCP.allocate(clusterName, Math.max(clusterManagerNodeCount, 4), 5000 + 42 * 1000 + 300); - SortedSet clusterManagerNodeHttpPorts = TCP.allocate(clusterName, clusterManagerNodeCount, 5000 + 42 * 1000 + 200); - - this.seedHosts = toHostList(clusterManagerNodeTransportPorts); - Set clusterManagerPorts = clusterManagerNodeTransportPorts - .stream().limit(clusterManagerNodeCount).collect(Collectors.toSet()); - this.initialClusterManagerHosts = toHostList(clusterManagerPorts); - - started = true; - - CompletableFuture clusterManagerNodeFuture = startNodes( - clusterManager.getClusterManagerNodeSettings(), clusterManagerNodeTransportPorts, - clusterManagerNodeHttpPorts); - - SortedSet nonClusterManagerNodeTransportPorts = TCP.allocate(clusterName, nonClusterManagerNodeCount, 5000 + 42 * 1000 + 310); - SortedSet nonClusterManagerNodeHttpPorts = TCP.allocate(clusterName, nonClusterManagerNodeCount, 5000 + 42 * 1000 + 210); - - CompletableFuture nonClusterManagerNodeFuture = startNodes( - clusterManager.getNonClusterManagerNodeSettings(), nonClusterManagerNodeTransportPorts, - nonClusterManagerNodeHttpPorts); - - CompletableFuture.allOf(clusterManagerNodeFuture, nonClusterManagerNodeFuture).join(); - - if (isNodeFailedWithPortCollision()) { - log.info("Detected port collision for cluster manager node. Retrying."); - - retry(); - return; - } - - log.info("Startup finished. Waiting for GREEN"); - - waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), nodes.size()); - - log.info("Started: {}", this); - - } - - public String getClusterName() { - return clusterName; - } - - public boolean isStarted() { - return started; - } - - public void stop() { - List> stopFutures = new ArrayList<>(); - for (Node node : nodes) { - stopFutures.add(node.stop(2, TimeUnit.SECONDS)); - } - CompletableFuture.allOf(stopFutures.toArray(size -> new CompletableFuture[size])).join(); - } - - public void destroy() { - stop(); - nodes.clear(); - - try { - FileUtils.deleteDirectory(clusterHomeDir); - } catch (IOException e) { - log.warn("Error while deleting " + clusterHomeDir, e); - } - } - - public Node clientNode() { - return findRunningNode(getNodesByType(CLIENT), getNodesByType(DATA), getNodesByType(CLUSTER_MANAGER)); - } - - public Node clusterManagerNode() { - return findRunningNode(getNodesByType(CLUSTER_MANAGER)); - } - - public List getNodes() { - return Collections.unmodifiableList(nodes); - } - - public Node getNodeByName(String name) { - return nodes.stream().filter(node -> node.getNodeName().equals(name)).findAny().orElseThrow(() -> new RuntimeException( - "No such node with name: " + name + "; available: " + nodes.stream().map(Node::getNodeName).collect(Collectors.toList()))); - } - - private boolean isNodeFailedWithPortCollision() { - return nodes.stream().anyMatch(Node::isPortCollision); - } - - private void retry() throws Exception { - retry++; - - if (retry > 10) { - throw new RuntimeException("Detected port collisions for cluster manager node. Giving up."); - } - - stop(); - - this.nodes.clear(); - this.seedHosts = null; - this.initialClusterManagerHosts = null; - createClusterDirectory("local_cluster_" + clusterName + "_retry_" + retry); - start(); - } - - @SafeVarargs - private final Node findRunningNode(List nodes, List... moreNodes) { - for (Node node : nodes) { - if (node.isRunning()) { - return node; - } - } - - if (moreNodes != null && moreNodes.length > 0) { - for (List nodesList : moreNodes) { - for (Node node : nodesList) { - if (node.isRunning()) { - return node; - } - } - } - } - - return null; - } - - private CompletableFuture startNodes(List nodeSettingList, SortedSet transportPorts, SortedSet httpPorts) { - Iterator transportPortIterator = transportPorts.iterator(); - Iterator httpPortIterator = httpPorts.iterator(); - List> futures = new ArrayList<>(); - - for (NodeSettings nodeSettings : nodeSettingList) { - Node node = new Node(nodeSettings, transportPortIterator.next(), httpPortIterator.next()); - futures.add(node.start()); - } - - return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); - } - - public void waitForCluster(ClusterHealthStatus status, TimeValue timeout, int expectedNodeCount) throws IOException { - Client client = clientNode().getInternalNodeClient(); - - - log.debug("waiting for cluster state {} and {} nodes", status.name(), expectedNodeCount); - AdminClient adminClient = client.admin(); - - final ClusterHealthResponse healthResponse = adminClient.cluster().prepareHealth().setWaitForStatus(status).setTimeout(timeout) - .setClusterManagerNodeTimeout(timeout).setWaitForNodes("" + expectedNodeCount).execute().actionGet(); - - if (log.isDebugEnabled()) { - log.debug("Current ClusterState:\n{}", Strings.toString(XContentType.JSON,healthResponse)); - } - - if (healthResponse.isTimedOut()) { - throw new IOException( - "cluster state is " + healthResponse.getStatus().name() + " with " + healthResponse.getNumberOfNodes() + " nodes"); - } else { - log.debug("... cluster state ok {} with {} nodes", healthResponse.getStatus().name(), healthResponse.getNumberOfNodes()); - } - - assertEquals(expectedNodeCount, healthResponse.getNumberOfNodes()); - - } - - @Override - public String toString() { - String clusterManagerNodes = nodeByTypeToString(CLUSTER_MANAGER); - String dataNodes = nodeByTypeToString(DATA); - String clientNodes = nodeByTypeToString(CLIENT); - return "\nES Cluster " + clusterName - + "\ncluster manager nodes: " + clusterManagerNodes - + "\n data nodes: " + dataNodes - + "\nclient nodes: " + clientNodes + "\n"; - } - - private String nodeByTypeToString(NodeType type) { - return getNodesByType(type).stream().map(Objects::toString).collect(Collectors.joining(", ")); - } - - private static List toHostList(Collection ports) { - return ports.stream().map(port -> "127.0.0.1:" + port).collect(Collectors.toList()); - } - - private String createNextNodeName(NodeSettings nodeSettings) { - NodeType type = nodeSettings.recognizeNodeType(); - long nodeTypeCount = countNodesByType(type); - String nodeType = type.name().toLowerCase(Locale.ROOT); - return nodeType + "_" + nodeTypeCount; - } - - public class Node implements OpenSearchClientProvider { - private final NodeType nodeType; - private final String nodeName; - private final NodeSettings nodeSettings; - private final File nodeHomeDir; - private final File dataDir; - private final File logsDir; - private final int transportPort; - private final int httpPort; - private final InetSocketAddress httpAddress; - private final InetSocketAddress transportAddress; - private PluginAwareNode node; - private boolean running = false; - private boolean portCollision = false; - - Node(NodeSettings nodeSettings, int transportPort, int httpPort) { - this.nodeName = createNextNodeName(requireNonNull(nodeSettings, "Node settings are required.")); - this.nodeSettings = nodeSettings; - this.nodeHomeDir = new File(clusterHomeDir, nodeName); - this.dataDir = new File(this.nodeHomeDir, "data"); - this.logsDir = new File(this.nodeHomeDir, "logs"); - this.transportPort = transportPort; - this.httpPort = httpPort; - InetAddress hostAddress = InetAddresses.forString("127.0.0.1"); - this.httpAddress = new InetSocketAddress(hostAddress, httpPort); - this.transportAddress = new InetSocketAddress(hostAddress, transportPort); - - this.nodeType = nodeSettings.recognizeNodeType(); - nodes.add(this); - } - - boolean hasAssignedType(NodeType type) { - return requireNonNull(type, "Node type is required.").equals(this.nodeType); - } - - CompletableFuture start() { - CompletableFuture completableFuture = new CompletableFuture<>(); - Class[] mergedPlugins = nodeSettings.pluginsWithAddition(additionalPlugins); - this.node = new PluginAwareNode(nodeSettings.containRole(NodeRole.CLUSTER_MANAGER), getOpenSearchSettings(), mergedPlugins); - - new Thread(new Runnable() { - - @Override - public void run() { - try { - node.start(); - running = true; - completableFuture.complete(StartStage.INITIALIZED); - } catch (BindTransportException | BindHttpException e) { - log.warn("Port collision detected for {}", this, e); - portCollision = true; - try { - node.close(); - } catch (IOException e1) { - log.error(e1); - } - - node = null; - TCP.reserve(transportPort, httpPort); - - completableFuture.complete(StartStage.RETRY); - - } catch (Throwable e) { - log.error("Unable to start {}", this, e); - node = null; - completableFuture.completeExceptionally(e); - } - } - }).start(); - - return completableFuture; - } - - public Client getInternalNodeClient() { - return node.client(); - } - - public PluginAwareNode esNode() { - return node; - } - - public boolean isRunning() { - return running; - } - - public X getInjectable(Class clazz) { - return node.injector().getInstance(clazz); - } - - public CompletableFuture stop(long timeout, TimeUnit timeUnit) { - return CompletableFuture.supplyAsync(() -> { - try { - log.info("Stopping {}", this); - - running = false; - - if (node != null) { - node.close(); - boolean stopped = node.awaitClose(timeout, timeUnit); - node = null; - return stopped; - } else { - return false; - } - } catch (Throwable e) { - String message = "Error while stopping " + this; - log.warn(message, e); - throw new RuntimeException(message, e); - } - }); - } - - @Override - public String toString() { - String state = running ? "RUNNING" : node != null ? "INITIALIZING" : "STOPPED"; - - return nodeName + " " + state + " [" + transportPort + ", " + httpPort + "]"; - } - - public boolean isPortCollision() { - return portCollision; - } - - public String getNodeName() { - return nodeName; - } - - @Override - public InetSocketAddress getHttpAddress() { - return httpAddress; - } - - @Override - public InetSocketAddress getTransportAddress() { - return transportAddress; - } - - private Settings getOpenSearchSettings() { - Settings settings = Settings.builder() - .put(getMinimalOpenSearchSettings()) - .putList("path.repo", List.of(getSnapshotDirPath())) - .build(); - - if (nodeSettingsSupplier != null) { - // TODO node number - return Settings.builder().put(settings).put(nodeSettingsSupplier.get(0)).build(); - } - return settings; - } - - private Settings getMinimalOpenSearchSettings() { - return Settings.builder().put("node.name", nodeName).putList("node.roles", createNodeRolesSettings()) - .put("cluster.name", clusterName).put("path.home", nodeHomeDir.toPath()).put("path.data", dataDir.toPath()) - .put("path.logs", logsDir.toPath()).putList("cluster.initial_cluster_manager_nodes", initialClusterManagerHosts) - .put("discovery.initial_state_timeout", "8s").putList("discovery.seed_hosts", seedHosts).put("transport.tcp.port", transportPort) - .put("http.port", httpPort).put("cluster.routing.allocation.disk.threshold_enabled", false) - .put("discovery.probe.connect_timeout", "10s").put("discovery.probe.handshake_timeout", "10s").put("http.cors.enabled", true) - .put("gateway.auto_import_dangling_indices", "true") - .build(); - } - - private List createNodeRolesSettings() { - final ImmutableList.Builder nodeRolesBuilder = ImmutableList.builder(); - if (nodeSettings.containRole(NodeRole.DATA)) { - nodeRolesBuilder.add("data"); - } - if (nodeSettings.containRole(NodeRole.CLUSTER_MANAGER)) { - nodeRolesBuilder.add("cluster_manager"); - } - if(nodeSettings.containRole(NodeRole.REMOTE_CLUSTER_CLIENT)) { - nodeRolesBuilder.add("remote_cluster_client"); - } - return nodeRolesBuilder.build(); - } - - @Override - public String getClusterName() { - return clusterName; - } - - @Override - public TestCertificates getTestCertificates() { - return testCertificates; - } - } - - public Random getRandom() { - return random; - } + static { + System.setProperty("opensearch.enforce.bootstrap.checks", "true"); + } + + private static final Logger log = LogManager.getLogger(LocalOpenSearchCluster.class); + + private final String clusterName; + private final ClusterManager clusterManager; + private final NodeSettingsSupplier nodeSettingsSupplier; + private final List> additionalPlugins; + private final List nodes = new ArrayList<>(); + private final TestCertificates testCertificates; + + private File clusterHomeDir; + private List seedHosts; + private List initialClusterManagerHosts; + private int retry = 0; + private boolean started; + private Random random = new Random(); + + private File snapshotDir; + + public LocalOpenSearchCluster( + String clusterName, + ClusterManager clusterManager, + NodeSettingsSupplier nodeSettingsSupplier, + List> additionalPlugins, + TestCertificates testCertificates + ) { + this.clusterName = clusterName; + this.clusterManager = clusterManager; + this.nodeSettingsSupplier = nodeSettingsSupplier; + this.additionalPlugins = additionalPlugins; + this.testCertificates = testCertificates; + try { + createClusterDirectory(clusterName); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public String getSnapshotDirPath() { + return snapshotDir.getAbsolutePath(); + } + + private void createClusterDirectory(String clusterName) throws IOException { + this.clusterHomeDir = Files.createTempDirectory("local_cluster_" + clusterName).toFile(); + log.debug("Cluster home directory '{}'.", clusterHomeDir.getAbsolutePath()); + this.snapshotDir = new File(this.clusterHomeDir, "snapshots"); + this.snapshotDir.mkdir(); + } + + private List getNodesByType(NodeType nodeType) { + return nodes.stream().filter(currentNode -> currentNode.hasAssignedType(nodeType)).collect(Collectors.toList()); + } + + private long countNodesByType(NodeType nodeType) { + return getNodesByType(nodeType).stream().count(); + } + + public void start() throws Exception { + log.info("Starting {}", clusterName); + + int clusterManagerNodeCount = clusterManager.getClusterManagerNodes(); + int nonClusterManagerNodeCount = clusterManager.getDataNodes() + clusterManager.getClientNodes(); + + SortedSet clusterManagerNodeTransportPorts = TCP.allocate( + clusterName, + Math.max(clusterManagerNodeCount, 4), + 5000 + 42 * 1000 + 300 + ); + SortedSet clusterManagerNodeHttpPorts = TCP.allocate(clusterName, clusterManagerNodeCount, 5000 + 42 * 1000 + 200); + + this.seedHosts = toHostList(clusterManagerNodeTransportPorts); + Set clusterManagerPorts = clusterManagerNodeTransportPorts.stream() + .limit(clusterManagerNodeCount) + .collect(Collectors.toSet()); + this.initialClusterManagerHosts = toHostList(clusterManagerPorts); + + started = true; + + CompletableFuture clusterManagerNodeFuture = startNodes( + clusterManager.getClusterManagerNodeSettings(), + clusterManagerNodeTransportPorts, + clusterManagerNodeHttpPorts + ); + + SortedSet nonClusterManagerNodeTransportPorts = TCP.allocate( + clusterName, + nonClusterManagerNodeCount, + 5000 + 42 * 1000 + 310 + ); + SortedSet nonClusterManagerNodeHttpPorts = TCP.allocate(clusterName, nonClusterManagerNodeCount, 5000 + 42 * 1000 + 210); + + CompletableFuture nonClusterManagerNodeFuture = startNodes( + clusterManager.getNonClusterManagerNodeSettings(), + nonClusterManagerNodeTransportPorts, + nonClusterManagerNodeHttpPorts + ); + + CompletableFuture.allOf(clusterManagerNodeFuture, nonClusterManagerNodeFuture).join(); + + if (isNodeFailedWithPortCollision()) { + log.info("Detected port collision for cluster manager node. Retrying."); + + retry(); + return; + } + + log.info("Startup finished. Waiting for GREEN"); + + waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), nodes.size()); + + log.info("Started: {}", this); + + } + + public String getClusterName() { + return clusterName; + } + + public boolean isStarted() { + return started; + } + + public void stop() { + List> stopFutures = new ArrayList<>(); + for (Node node : nodes) { + stopFutures.add(node.stop(2, TimeUnit.SECONDS)); + } + CompletableFuture.allOf(stopFutures.toArray(size -> new CompletableFuture[size])).join(); + } + + public void destroy() { + stop(); + nodes.clear(); + + try { + FileUtils.deleteDirectory(clusterHomeDir); + } catch (IOException e) { + log.warn("Error while deleting " + clusterHomeDir, e); + } + } + + public Node clientNode() { + return findRunningNode(getNodesByType(CLIENT), getNodesByType(DATA), getNodesByType(CLUSTER_MANAGER)); + } + + public Node clusterManagerNode() { + return findRunningNode(getNodesByType(CLUSTER_MANAGER)); + } + + public List getNodes() { + return Collections.unmodifiableList(nodes); + } + + public Node getNodeByName(String name) { + return nodes.stream() + .filter(node -> node.getNodeName().equals(name)) + .findAny() + .orElseThrow( + () -> new RuntimeException( + "No such node with name: " + name + "; available: " + nodes.stream().map(Node::getNodeName).collect(Collectors.toList()) + ) + ); + } + + private boolean isNodeFailedWithPortCollision() { + return nodes.stream().anyMatch(Node::isPortCollision); + } + + private void retry() throws Exception { + retry++; + + if (retry > 10) { + throw new RuntimeException("Detected port collisions for cluster manager node. Giving up."); + } + + stop(); + + this.nodes.clear(); + this.seedHosts = null; + this.initialClusterManagerHosts = null; + createClusterDirectory("local_cluster_" + clusterName + "_retry_" + retry); + start(); + } + + @SafeVarargs + private final Node findRunningNode(List nodes, List... moreNodes) { + for (Node node : nodes) { + if (node.isRunning()) { + return node; + } + } + + if (moreNodes != null && moreNodes.length > 0) { + for (List nodesList : moreNodes) { + for (Node node : nodesList) { + if (node.isRunning()) { + return node; + } + } + } + } + + return null; + } + + private CompletableFuture startNodes( + List nodeSettingList, + SortedSet transportPorts, + SortedSet httpPorts + ) { + Iterator transportPortIterator = transportPorts.iterator(); + Iterator httpPortIterator = httpPorts.iterator(); + List> futures = new ArrayList<>(); + + for (NodeSettings nodeSettings : nodeSettingList) { + Node node = new Node(nodeSettings, transportPortIterator.next(), httpPortIterator.next()); + futures.add(node.start()); + } + + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + } + + public void waitForCluster(ClusterHealthStatus status, TimeValue timeout, int expectedNodeCount) throws IOException { + Client client = clientNode().getInternalNodeClient(); + + log.debug("waiting for cluster state {} and {} nodes", status.name(), expectedNodeCount); + AdminClient adminClient = client.admin(); + + final ClusterHealthResponse healthResponse = adminClient.cluster() + .prepareHealth() + .setWaitForStatus(status) + .setTimeout(timeout) + .setClusterManagerNodeTimeout(timeout) + .setWaitForNodes("" + expectedNodeCount) + .execute() + .actionGet(); + + if (log.isDebugEnabled()) { + log.debug("Current ClusterState:\n{}", Strings.toString(XContentType.JSON, healthResponse)); + } + + if (healthResponse.isTimedOut()) { + throw new IOException( + "cluster state is " + healthResponse.getStatus().name() + " with " + healthResponse.getNumberOfNodes() + " nodes" + ); + } else { + log.debug("... cluster state ok {} with {} nodes", healthResponse.getStatus().name(), healthResponse.getNumberOfNodes()); + } + + assertEquals(expectedNodeCount, healthResponse.getNumberOfNodes()); + + } + + @Override + public String toString() { + String clusterManagerNodes = nodeByTypeToString(CLUSTER_MANAGER); + String dataNodes = nodeByTypeToString(DATA); + String clientNodes = nodeByTypeToString(CLIENT); + return "\nES Cluster " + + clusterName + + "\ncluster manager nodes: " + + clusterManagerNodes + + "\n data nodes: " + + dataNodes + + "\nclient nodes: " + + clientNodes + + "\n"; + } + + private String nodeByTypeToString(NodeType type) { + return getNodesByType(type).stream().map(Objects::toString).collect(Collectors.joining(", ")); + } + + private static List toHostList(Collection ports) { + return ports.stream().map(port -> "127.0.0.1:" + port).collect(Collectors.toList()); + } + + private String createNextNodeName(NodeSettings nodeSettings) { + NodeType type = nodeSettings.recognizeNodeType(); + long nodeTypeCount = countNodesByType(type); + String nodeType = type.name().toLowerCase(Locale.ROOT); + return nodeType + "_" + nodeTypeCount; + } + + public class Node implements OpenSearchClientProvider { + private final NodeType nodeType; + private final String nodeName; + private final NodeSettings nodeSettings; + private final File nodeHomeDir; + private final File dataDir; + private final File logsDir; + private final int transportPort; + private final int httpPort; + private final InetSocketAddress httpAddress; + private final InetSocketAddress transportAddress; + private PluginAwareNode node; + private boolean running = false; + private boolean portCollision = false; + + Node(NodeSettings nodeSettings, int transportPort, int httpPort) { + this.nodeName = createNextNodeName(requireNonNull(nodeSettings, "Node settings are required.")); + this.nodeSettings = nodeSettings; + this.nodeHomeDir = new File(clusterHomeDir, nodeName); + this.dataDir = new File(this.nodeHomeDir, "data"); + this.logsDir = new File(this.nodeHomeDir, "logs"); + this.transportPort = transportPort; + this.httpPort = httpPort; + InetAddress hostAddress = InetAddresses.forString("127.0.0.1"); + this.httpAddress = new InetSocketAddress(hostAddress, httpPort); + this.transportAddress = new InetSocketAddress(hostAddress, transportPort); + + this.nodeType = nodeSettings.recognizeNodeType(); + nodes.add(this); + } + + boolean hasAssignedType(NodeType type) { + return requireNonNull(type, "Node type is required.").equals(this.nodeType); + } + + CompletableFuture start() { + CompletableFuture completableFuture = new CompletableFuture<>(); + Class[] mergedPlugins = nodeSettings.pluginsWithAddition(additionalPlugins); + this.node = new PluginAwareNode(nodeSettings.containRole(NodeRole.CLUSTER_MANAGER), getOpenSearchSettings(), mergedPlugins); + + new Thread(new Runnable() { + + @Override + public void run() { + try { + node.start(); + running = true; + completableFuture.complete(StartStage.INITIALIZED); + } catch (BindTransportException | BindHttpException e) { + log.warn("Port collision detected for {}", this, e); + portCollision = true; + try { + node.close(); + } catch (IOException e1) { + log.error(e1); + } + + node = null; + TCP.reserve(transportPort, httpPort); + + completableFuture.complete(StartStage.RETRY); + + } catch (Throwable e) { + log.error("Unable to start {}", this, e); + node = null; + completableFuture.completeExceptionally(e); + } + } + }).start(); + + return completableFuture; + } + + public Client getInternalNodeClient() { + return node.client(); + } + + public PluginAwareNode esNode() { + return node; + } + + public boolean isRunning() { + return running; + } + + public X getInjectable(Class clazz) { + return node.injector().getInstance(clazz); + } + + public CompletableFuture stop(long timeout, TimeUnit timeUnit) { + return CompletableFuture.supplyAsync(() -> { + try { + log.info("Stopping {}", this); + + running = false; + + if (node != null) { + node.close(); + boolean stopped = node.awaitClose(timeout, timeUnit); + node = null; + return stopped; + } else { + return false; + } + } catch (Throwable e) { + String message = "Error while stopping " + this; + log.warn(message, e); + throw new RuntimeException(message, e); + } + }); + } + + @Override + public String toString() { + String state = running ? "RUNNING" : node != null ? "INITIALIZING" : "STOPPED"; + + return nodeName + " " + state + " [" + transportPort + ", " + httpPort + "]"; + } + + public boolean isPortCollision() { + return portCollision; + } + + public String getNodeName() { + return nodeName; + } + + @Override + public InetSocketAddress getHttpAddress() { + return httpAddress; + } + + @Override + public InetSocketAddress getTransportAddress() { + return transportAddress; + } + + private Settings getOpenSearchSettings() { + Settings settings = Settings.builder() + .put(getMinimalOpenSearchSettings()) + .putList("path.repo", List.of(getSnapshotDirPath())) + .build(); + + if (nodeSettingsSupplier != null) { + // TODO node number + return Settings.builder().put(settings).put(nodeSettingsSupplier.get(0)).build(); + } + return settings; + } + + private Settings getMinimalOpenSearchSettings() { + return Settings.builder() + .put("node.name", nodeName) + .putList("node.roles", createNodeRolesSettings()) + .put("cluster.name", clusterName) + .put("path.home", nodeHomeDir.toPath()) + .put("path.data", dataDir.toPath()) + .put("path.logs", logsDir.toPath()) + .putList("cluster.initial_cluster_manager_nodes", initialClusterManagerHosts) + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.seed_hosts", seedHosts) + .put("transport.tcp.port", transportPort) + .put("http.port", httpPort) + .put("cluster.routing.allocation.disk.threshold_enabled", false) + .put("discovery.probe.connect_timeout", "10s") + .put("discovery.probe.handshake_timeout", "10s") + .put("http.cors.enabled", true) + .put("gateway.auto_import_dangling_indices", "true") + .build(); + } + + private List createNodeRolesSettings() { + final ImmutableList.Builder nodeRolesBuilder = ImmutableList.builder(); + if (nodeSettings.containRole(NodeRole.DATA)) { + nodeRolesBuilder.add("data"); + } + if (nodeSettings.containRole(NodeRole.CLUSTER_MANAGER)) { + nodeRolesBuilder.add("cluster_manager"); + } + if (nodeSettings.containRole(NodeRole.REMOTE_CLUSTER_CLIENT)) { + nodeRolesBuilder.add("remote_cluster_client"); + } + return nodeRolesBuilder.build(); + } + + @Override + public String getClusterName() { + return clusterName; + } + + @Override + public TestCertificates getTestCertificates() { + return testCertificates; + } + } + + public Random getRandom() { + return random; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java index 318dce63d6..4ad5f8420e 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java @@ -34,45 +34,51 @@ public class MinimumSecuritySettingsSupplierFactory { - private final String PRIVATE_KEY_HTTP_PASSWORD = "aWVV63OJ4qzZyPrBwl2MFny4ZV8lQRZchjL"; - private final String PRIVATE_KEY_TRANSPORT_PASSWORD = "iWbUv9w79sbd5tcxvSJNfHXS9GhcPCvdw9x"; + private final String PRIVATE_KEY_HTTP_PASSWORD = "aWVV63OJ4qzZyPrBwl2MFny4ZV8lQRZchjL"; + private final String PRIVATE_KEY_TRANSPORT_PASSWORD = "iWbUv9w79sbd5tcxvSJNfHXS9GhcPCvdw9x"; - private TestCertificates testCertificates; + private TestCertificates testCertificates; - public MinimumSecuritySettingsSupplierFactory(TestCertificates testCertificates) { - if (testCertificates == null) { - throw new IllegalArgumentException("certificates must not be null"); - } - this.testCertificates = testCertificates; + public MinimumSecuritySettingsSupplierFactory(TestCertificates testCertificates) { + if (testCertificates == null) { + throw new IllegalArgumentException("certificates must not be null"); + } + this.testCertificates = testCertificates; - } + } - public NodeSettingsSupplier minimumOpenSearchSettings(boolean sslOnly, Settings other) { - return i -> minimumOpenSearchSettingsBuilder(i, sslOnly).put(other).build(); - } + public NodeSettingsSupplier minimumOpenSearchSettings(boolean sslOnly, Settings other) { + return i -> minimumOpenSearchSettingsBuilder(i, sslOnly).put(other).build(); + } - private Settings.Builder minimumOpenSearchSettingsBuilder(int node, boolean sslOnly) { + private Settings.Builder minimumOpenSearchSettingsBuilder(int node, boolean sslOnly) { - Settings.Builder builder = Settings.builder(); + Settings.Builder builder = Settings.builder(); - builder.put("plugins.security.ssl.transport.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); - builder.put("plugins.security.ssl.transport.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); - builder.put("plugins.security.ssl.transport.pemkey_filepath", testCertificates.getNodeKey(node, PRIVATE_KEY_TRANSPORT_PASSWORD).getAbsolutePath()); - builder.put("plugins.security.ssl.transport.pemkey_password", PRIVATE_KEY_TRANSPORT_PASSWORD); + builder.put("plugins.security.ssl.transport.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); + builder.put("plugins.security.ssl.transport.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); + builder.put( + "plugins.security.ssl.transport.pemkey_filepath", + testCertificates.getNodeKey(node, PRIVATE_KEY_TRANSPORT_PASSWORD).getAbsolutePath() + ); + builder.put("plugins.security.ssl.transport.pemkey_password", PRIVATE_KEY_TRANSPORT_PASSWORD); - builder.put("plugins.security.ssl.http.enabled", true); - builder.put("plugins.security.ssl.http.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); - builder.put("plugins.security.ssl.http.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); - builder.put("plugins.security.ssl.http.pemkey_filepath", testCertificates.getNodeKey(node, PRIVATE_KEY_HTTP_PASSWORD).getAbsolutePath()); - builder.put("plugins.security.ssl.http.pemkey_password", PRIVATE_KEY_HTTP_PASSWORD); - if(sslOnly == false) { - builder.put(ConfigConstants.SECURITY_BACKGROUND_INIT_IF_SECURITYINDEX_NOT_EXIST, false); - builder.putList("plugins.security.authcz.admin_dn", testCertificates.getAdminDNs()); - builder.put("plugins.security.compliance.salt", "1234567890123456"); - builder.put("plugins.security.audit.type", "noop"); - builder.put("plugins.security.background_init_if_securityindex_not_exist", "false"); - } - return builder; + builder.put("plugins.security.ssl.http.enabled", true); + builder.put("plugins.security.ssl.http.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); + builder.put("plugins.security.ssl.http.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); + builder.put( + "plugins.security.ssl.http.pemkey_filepath", + testCertificates.getNodeKey(node, PRIVATE_KEY_HTTP_PASSWORD).getAbsolutePath() + ); + builder.put("plugins.security.ssl.http.pemkey_password", PRIVATE_KEY_HTTP_PASSWORD); + if (sslOnly == false) { + builder.put(ConfigConstants.SECURITY_BACKGROUND_INIT_IF_SECURITYINDEX_NOT_EXIST, false); + builder.putList("plugins.security.authcz.admin_dn", testCertificates.getAdminDNs()); + builder.put("plugins.security.compliance.salt", "1234567890123456"); + builder.put("plugins.security.audit.type", "noop"); + builder.put("plugins.security.background_init_if_securityindex_not_exist", "false"); + } + return builder; - } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java index 7dc77ef37e..0d465fa119 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java @@ -10,5 +10,7 @@ package org.opensearch.test.framework.cluster; enum NodeRole { - DATA, CLUSTER_MANAGER, REMOTE_CLUSTER_CLIENT + DATA, + CLUSTER_MANAGER, + REMOTE_CLUSTER_CLIENT } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java index 75c728287b..cab3a760ca 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java @@ -30,5 +30,5 @@ @FunctionalInterface public interface NodeSettingsSupplier { - Settings get(int i); + Settings get(int i); } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java index 915f99daa8..8ae8941e8d 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java @@ -11,5 +11,7 @@ package org.opensearch.test.framework.cluster; enum NodeType { - CLIENT, DATA, CLUSTER_MANAGER + CLIENT, + DATA, + CLUSTER_MANAGER } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java index e395bfceda..45a68994f8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java @@ -79,197 +79,203 @@ */ public interface OpenSearchClientProvider { - String getClusterName(); - - TestCertificates getTestCertificates(); - - InetSocketAddress getHttpAddress(); - - InetSocketAddress getTransportAddress(); - - default URI getHttpAddressAsURI() { - InetSocketAddress address = getHttpAddress(); - return URI.create("https://" + address.getHostString() + ":" + address.getPort()); - } - - /** - * Returns a REST client that sends requests with basic authentication for the specified User object. Optionally, - * additional HTTP headers can be specified which will be sent with each request. - * - * This method should be usually preferred. The other getRestClient() methods shall be only used for specific - * situations. - */ - default TestRestClient getRestClient(UserCredentialsHolder user, CertificateData useCertificateData, Header... headers) { - return getRestClient(user.getName(), user.getPassword(), useCertificateData, headers); - } - - default TestRestClient getRestClient(UserCredentialsHolder user, Header... headers) { - return getRestClient(user.getName(), user.getPassword(), null, headers); - } - - default RestHighLevelClient getRestHighLevelClient(String username, String password, Header... headers) { - return getRestHighLevelClient(new UserCredentialsHolder() { - @Override - public String getName() { - return username; - } - - @Override - public String getPassword() { - return password; - } - }, Arrays.asList(headers)); - } - - - default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user) { - return getRestHighLevelClient(user, Collections.emptySet()); - } - - default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user, Collection defaultHeaders) { - - BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(user.getName(), user.getPassword().toCharArray())); - - return getRestHighLevelClient(credentialsProvider, defaultHeaders); - } - - default RestHighLevelClient getRestHighLevelClient(Collection defaultHeaders) { - return getRestHighLevelClient((BasicCredentialsProvider)null, defaultHeaders); - } - - default RestHighLevelClient getRestHighLevelClient(BasicCredentialsProvider credentialsProvider, Collection defaultHeaders) { - RestClientBuilder.HttpClientConfigCallback configCallback = httpClientBuilder -> { - TlsStrategy tlsStrategy = ClientTlsStrategyBuilder - .create() - .setSslContext(getSSLContext()) - .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) - // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 - .setTlsDetailsFactory(new Factory() { - @Override - public TlsDetails create(final SSLEngine sslEngine) { - return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); - } - }) - .build(); - - final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(tlsStrategy) - .build(); - - if(credentialsProvider != null) { - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - } - httpClientBuilder.setDefaultHeaders(defaultHeaders); - httpClientBuilder.setConnectionManager(cm); - httpClientBuilder.setDefaultHeaders(defaultHeaders); - return httpClientBuilder; - }; - - InetSocketAddress httpAddress = getHttpAddress(); - RestClientBuilder builder = RestClient.builder(new HttpHost("https", httpAddress.getHostString(), httpAddress.getPort())) - .setHttpClientConfigCallback(configCallback); - - - return new RestHighLevelClient(builder); - } - - default CloseableHttpClient getClosableHttpClient(String[] supportedCipherSuit) { - CloseableHttpClientFactory factory = new CloseableHttpClientFactory(getSSLContext(), null, null, supportedCipherSuit); - return factory.getHTTPClient(); - } - - /** - * Returns a REST client that sends requests with basic authentication for the specified user name and password. Optionally, - * additional HTTP headers can be specified which will be sent with each request. - * - * Normally, you should use the method with the User object argument instead. Use this only if you need more - * control over username and password - for example, when you want to send a wrong password. - */ - default TestRestClient getRestClient(String user, String password, Header... headers) { - return createGenericClientRestClient(new TestRestClientConfiguration().username(user).password(password).headers(headers)); - } - default TestRestClient getRestClient(String user, String password, CertificateData useCertificateData, Header... headers) { - Header basicAuthHeader = getBasicAuthHeader(user, password); - if (headers != null && headers.length > 0) { - List
concatenatedHeaders = Stream.concat(Stream.of(basicAuthHeader), Stream.of(headers)).collect(Collectors.toList()); - return getRestClient(concatenatedHeaders, useCertificateData); - } - return getRestClient(useCertificateData, basicAuthHeader); - } - /** - * Returns a REST client. You can specify additional HTTP headers that will be sent with each request. Use this - * method to test non-basic authentication, such as JWT bearer authentication. - */ - default TestRestClient getRestClient(CertificateData useCertificateData, Header... headers) { - return getRestClient(Arrays.asList(headers), useCertificateData); - } - - default TestRestClient getRestClient(Header... headers) { - return getRestClient((CertificateData) null, headers); - } - - - default TestRestClient getRestClient(List
headers) { - return createGenericClientRestClient(new TestRestClientConfiguration().headers(headers)); - - } - - default TestRestClient getRestClient(List
headers, CertificateData useCertificateData) { - return createGenericClientRestClient(headers, useCertificateData, null); - } - - default TestRestClient createGenericClientRestClient(List
headers, CertificateData useCertificateData, - InetAddress sourceInetAddress) { - return new TestRestClient(getHttpAddress(), headers, getSSLContext(useCertificateData), sourceInetAddress); - } - - default TestRestClient createGenericClientRestClient(TestRestClientConfiguration configuration) { - return new TestRestClient(getHttpAddress(), configuration.getHeaders(), getSSLContext(), configuration.getSourceInetAddress()); - } - - private SSLContext getSSLContext() { - return getSSLContext(null); - } - - private SSLContext getSSLContext(CertificateData useCertificateData) { - X509Certificate[] trustCertificates; - - try { - trustCertificates = PemKeyReader.loadCertificatesFromFile(getTestCertificates().getRootCertificate() ); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - - ks.load(null); - - for (int i = 0; i < trustCertificates.length; i++) { - ks.setCertificateEntry("caCert-" + i, trustCertificates[i]); - } - KeyManager[] keyManagers = null; - if(useCertificateData != null) { - Certificate[] chainOfTrust = {useCertificateData.certificate()}; - ks.setKeyEntry("admin-certificate", useCertificateData.getKey(), null, chainOfTrust); - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(ks, null); - keyManagers = keyManagerFactory.getKeyManagers(); - } - - tmf.init(ks); - - SSLContext sslContext = SSLContext.getInstance("TLS"); - - sslContext.init(keyManagers, tmf.getTrustManagers(), null); - return sslContext; - - } catch (Exception e) { - throw new RuntimeException("Error loading root CA ", e); - } - } - - public interface UserCredentialsHolder { - String getName(); - String getPassword(); - } + String getClusterName(); + + TestCertificates getTestCertificates(); + + InetSocketAddress getHttpAddress(); + + InetSocketAddress getTransportAddress(); + + default URI getHttpAddressAsURI() { + InetSocketAddress address = getHttpAddress(); + return URI.create("https://" + address.getHostString() + ":" + address.getPort()); + } + + /** + * Returns a REST client that sends requests with basic authentication for the specified User object. Optionally, + * additional HTTP headers can be specified which will be sent with each request. + * + * This method should be usually preferred. The other getRestClient() methods shall be only used for specific + * situations. + */ + default TestRestClient getRestClient(UserCredentialsHolder user, CertificateData useCertificateData, Header... headers) { + return getRestClient(user.getName(), user.getPassword(), useCertificateData, headers); + } + + default TestRestClient getRestClient(UserCredentialsHolder user, Header... headers) { + return getRestClient(user.getName(), user.getPassword(), null, headers); + } + + default RestHighLevelClient getRestHighLevelClient(String username, String password, Header... headers) { + return getRestHighLevelClient(new UserCredentialsHolder() { + @Override + public String getName() { + return username; + } + + @Override + public String getPassword() { + return password; + } + }, Arrays.asList(headers)); + } + + default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user) { + return getRestHighLevelClient(user, Collections.emptySet()); + } + + default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user, Collection defaultHeaders) { + + BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials( + new AuthScope(null, -1), + new UsernamePasswordCredentials(user.getName(), user.getPassword().toCharArray()) + ); + + return getRestHighLevelClient(credentialsProvider, defaultHeaders); + } + + default RestHighLevelClient getRestHighLevelClient(Collection defaultHeaders) { + return getRestHighLevelClient((BasicCredentialsProvider) null, defaultHeaders); + } + + default RestHighLevelClient getRestHighLevelClient( + BasicCredentialsProvider credentialsProvider, + Collection defaultHeaders + ) { + RestClientBuilder.HttpClientConfigCallback configCallback = httpClientBuilder -> { + TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() + .setSslContext(getSSLContext()) + .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) + // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 + .setTlsDetailsFactory(new Factory() { + @Override + public TlsDetails create(final SSLEngine sslEngine) { + return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); + } + }) + .build(); + + final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(tlsStrategy).build(); + + if (credentialsProvider != null) { + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + httpClientBuilder.setDefaultHeaders(defaultHeaders); + httpClientBuilder.setConnectionManager(cm); + httpClientBuilder.setDefaultHeaders(defaultHeaders); + return httpClientBuilder; + }; + + InetSocketAddress httpAddress = getHttpAddress(); + RestClientBuilder builder = RestClient.builder(new HttpHost("https", httpAddress.getHostString(), httpAddress.getPort())) + .setHttpClientConfigCallback(configCallback); + + return new RestHighLevelClient(builder); + } + + default CloseableHttpClient getClosableHttpClient(String[] supportedCipherSuit) { + CloseableHttpClientFactory factory = new CloseableHttpClientFactory(getSSLContext(), null, null, supportedCipherSuit); + return factory.getHTTPClient(); + } + + /** + * Returns a REST client that sends requests with basic authentication for the specified user name and password. Optionally, + * additional HTTP headers can be specified which will be sent with each request. + * + * Normally, you should use the method with the User object argument instead. Use this only if you need more + * control over username and password - for example, when you want to send a wrong password. + */ + default TestRestClient getRestClient(String user, String password, Header... headers) { + return createGenericClientRestClient(new TestRestClientConfiguration().username(user).password(password).headers(headers)); + } + + default TestRestClient getRestClient(String user, String password, CertificateData useCertificateData, Header... headers) { + Header basicAuthHeader = getBasicAuthHeader(user, password); + if (headers != null && headers.length > 0) { + List
concatenatedHeaders = Stream.concat(Stream.of(basicAuthHeader), Stream.of(headers)).collect(Collectors.toList()); + return getRestClient(concatenatedHeaders, useCertificateData); + } + return getRestClient(useCertificateData, basicAuthHeader); + } + + /** + * Returns a REST client. You can specify additional HTTP headers that will be sent with each request. Use this + * method to test non-basic authentication, such as JWT bearer authentication. + */ + default TestRestClient getRestClient(CertificateData useCertificateData, Header... headers) { + return getRestClient(Arrays.asList(headers), useCertificateData); + } + + default TestRestClient getRestClient(Header... headers) { + return getRestClient((CertificateData) null, headers); + } + + default TestRestClient getRestClient(List
headers) { + return createGenericClientRestClient(new TestRestClientConfiguration().headers(headers)); + + } + + default TestRestClient getRestClient(List
headers, CertificateData useCertificateData) { + return createGenericClientRestClient(headers, useCertificateData, null); + } + + default TestRestClient createGenericClientRestClient( + List
headers, + CertificateData useCertificateData, + InetAddress sourceInetAddress + ) { + return new TestRestClient(getHttpAddress(), headers, getSSLContext(useCertificateData), sourceInetAddress); + } + + default TestRestClient createGenericClientRestClient(TestRestClientConfiguration configuration) { + return new TestRestClient(getHttpAddress(), configuration.getHeaders(), getSSLContext(), configuration.getSourceInetAddress()); + } + + private SSLContext getSSLContext() { + return getSSLContext(null); + } + + private SSLContext getSSLContext(CertificateData useCertificateData) { + X509Certificate[] trustCertificates; + + try { + trustCertificates = PemKeyReader.loadCertificatesFromFile(getTestCertificates().getRootCertificate()); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + + ks.load(null); + + for (int i = 0; i < trustCertificates.length; i++) { + ks.setCertificateEntry("caCert-" + i, trustCertificates[i]); + } + KeyManager[] keyManagers = null; + if (useCertificateData != null) { + Certificate[] chainOfTrust = { useCertificateData.certificate() }; + ks.setKeyEntry("admin-certificate", useCertificateData.getKey(), null, chainOfTrust); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(ks, null); + keyManagers = keyManagerFactory.getKeyManagers(); + } + + tmf.init(ks); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + + sslContext.init(keyManagers, tmf.getTrustManagers(), null); + return sslContext; + + } catch (Exception e) { + throw new RuntimeException("Error loading root CA ", e); + } + } + + public interface UserCredentialsHolder { + String getName(); + + String getPassword(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java index ed72fae91f..139378fd22 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java @@ -47,118 +47,119 @@ */ public class PortAllocator { - public static final PortAllocator TCP = new PortAllocator(SocketType.TCP, Duration.ofSeconds(100)); - public static final PortAllocator UDP = new PortAllocator(SocketType.UDP, Duration.ofSeconds(100)); + public static final PortAllocator TCP = new PortAllocator(SocketType.TCP, Duration.ofSeconds(100)); + public static final PortAllocator UDP = new PortAllocator(SocketType.UDP, Duration.ofSeconds(100)); - private final SocketType socketType; - private final Duration timeoutDuration; - private final Map allocatedPorts = new HashMap<>(); + private final SocketType socketType; + private final Duration timeoutDuration; + private final Map allocatedPorts = new HashMap<>(); - PortAllocator(SocketType socketType, Duration timeoutDuration) { - this.socketType = socketType; - this.timeoutDuration = timeoutDuration; - } + PortAllocator(SocketType socketType, Duration timeoutDuration) { + this.socketType = socketType; + this.timeoutDuration = timeoutDuration; + } - public SortedSet allocate(String clientName, int numRequested, int minPort) { + public SortedSet allocate(String clientName, int numRequested, int minPort) { - int startPort = minPort; + int startPort = minPort; - while (!isAvailable(startPort)) { - startPort += 10; - } + while (!isAvailable(startPort)) { + startPort += 10; + } - SortedSet foundPorts = new TreeSet<>(); + SortedSet foundPorts = new TreeSet<>(); - for (int currentPort = startPort; foundPorts.size() < numRequested && currentPort < SocketUtils.PORT_RANGE_MAX - && (currentPort - startPort) < 10000; currentPort++) { - if (allocate(clientName, currentPort)) { - foundPorts.add(currentPort); - } - } + for (int currentPort = startPort; foundPorts.size() < numRequested + && currentPort < SocketUtils.PORT_RANGE_MAX + && (currentPort - startPort) < 10000; currentPort++) { + if (allocate(clientName, currentPort)) { + foundPorts.add(currentPort); + } + } - if (foundPorts.size() < numRequested) { - throw new IllegalStateException("Could not find " + numRequested + " free ports starting at " + minPort + " for " + clientName); - } + if (foundPorts.size() < numRequested) { + throw new IllegalStateException("Could not find " + numRequested + " free ports starting at " + minPort + " for " + clientName); + } - return foundPorts; - } + return foundPorts; + } - public int allocateSingle(String clientName, int minPort) { + public int allocateSingle(String clientName, int minPort) { - int startPort = minPort; + int startPort = minPort; - for (int currentPort = startPort; currentPort < SocketUtils.PORT_RANGE_MAX && (currentPort - startPort) < 10000; currentPort++) { - if (allocate(clientName, currentPort)) { - return currentPort; - } - } + for (int currentPort = startPort; currentPort < SocketUtils.PORT_RANGE_MAX && (currentPort - startPort) < 10000; currentPort++) { + if (allocate(clientName, currentPort)) { + return currentPort; + } + } - throw new IllegalStateException("Could not find free port starting at " + minPort + " for " + clientName); + throw new IllegalStateException("Could not find free port starting at " + minPort + " for " + clientName); - } + } - public void reserve(int... ports) { + public void reserve(int... ports) { - for (int port : ports) { - allocate("reserved", port); - } - } + for (int port : ports) { + allocate("reserved", port); + } + } - private boolean isInUse(int port) { - boolean result = !this.socketType.isPortAvailable(port); + private boolean isInUse(int port) { + boolean result = !this.socketType.isPortAvailable(port); - if (result) { - synchronized (this) { - allocatedPorts.put(port, new AllocatedPort("external")); - } - } + if (result) { + synchronized (this) { + allocatedPorts.put(port, new AllocatedPort("external")); + } + } - return result; - } + return result; + } - private boolean isAvailable(int port) { - return !isAllocated(port) && !isInUse(port); - } + private boolean isAvailable(int port) { + return !isAllocated(port) && !isInUse(port); + } - private synchronized boolean isAllocated(int port) { - AllocatedPort allocatedPort = this.allocatedPorts.get(port); + private synchronized boolean isAllocated(int port) { + AllocatedPort allocatedPort = this.allocatedPorts.get(port); - return allocatedPort != null && !allocatedPort.isTimedOut(); - } + return allocatedPort != null && !allocatedPort.isTimedOut(); + } - private synchronized boolean allocate(String clientName, int port) { + private synchronized boolean allocate(String clientName, int port) { - AllocatedPort allocatedPort = allocatedPorts.get(port); + AllocatedPort allocatedPort = allocatedPorts.get(port); - if (allocatedPort != null && allocatedPort.isTimedOut()) { - allocatedPort = null; - allocatedPorts.remove(port); - } + if (allocatedPort != null && allocatedPort.isTimedOut()) { + allocatedPort = null; + allocatedPorts.remove(port); + } - if (allocatedPort == null && !isInUse(port)) { - allocatedPorts.put(port, new AllocatedPort(clientName)); - return true; - } else { - return false; - } - } + if (allocatedPort == null && !isInUse(port)) { + allocatedPorts.put(port, new AllocatedPort(clientName)); + return true; + } else { + return false; + } + } - private class AllocatedPort { - final String client; - final Instant allocatedAt; + private class AllocatedPort { + final String client; + final Instant allocatedAt; - AllocatedPort(String client) { - this.client = client; - this.allocatedAt = Instant.now(); - } + AllocatedPort(String client) { + this.client = client; + this.allocatedAt = Instant.now(); + } - boolean isTimedOut() { - return allocatedAt.plus(timeoutDuration).isBefore(Instant.now()); - } + boolean isTimedOut() { + return allocatedAt.plus(timeoutDuration).isBefore(Instant.now()); + } - @Override - public String toString() { - return "AllocatedPort [client=" + client + ", allocatedAt=" + allocatedAt + "]"; - } - } + @Override + public String toString() { + return "AllocatedPort [client=" + client + ", allocatedAt=" + allocatedAt + "]"; + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java index d53258f020..0023d65e98 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java @@ -10,7 +10,7 @@ package org.opensearch.test.framework.cluster; public class RestClientException extends RuntimeException { - RestClientException(String message, Throwable cause) { - super(message, cause); - } + RestClientException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java index 781ad4505c..b40aa9cfcb 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java @@ -23,82 +23,82 @@ public final class SearchRequestFactory { - private SearchRequestFactory() { + private SearchRequestFactory() { - } + } - public static SearchRequest queryByIdsRequest(String indexName, String... ids) { - SearchRequest searchRequest = new SearchRequest(indexName); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.idsQuery().addIds(ids)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryByIdsRequest(String indexName, String... ids) { + SearchRequest searchRequest = new SearchRequest(indexName); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.idsQuery().addIds(ids)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest queryStringQueryRequest(String indexName, String queryString) { - SearchRequest searchRequest = new SearchRequest(indexName); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryStringQueryRequest(String indexName, String queryString) { + SearchRequest searchRequest = new SearchRequest(indexName); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest queryStringQueryRequest(String[] indicesNames, String queryString) { - SearchRequest searchRequest = new SearchRequest(indicesNames); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryStringQueryRequest(String[] indicesNames, String queryString) { + SearchRequest searchRequest = new SearchRequest(indicesNames); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest queryStringQueryRequest(String queryString) { - SearchRequest searchRequest = new SearchRequest(); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryStringQueryRequest(String queryString) { + SearchRequest searchRequest = new SearchRequest(); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest searchRequestWithScroll(String indexName, int pageSize) { - SearchRequest searchRequest = new SearchRequest(indexName); - searchRequest.scroll(new TimeValue(1, MINUTES)); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.matchAllQuery()); - searchSourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC)); - searchSourceBuilder.size(pageSize); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest searchRequestWithScroll(String indexName, int pageSize) { + SearchRequest searchRequest = new SearchRequest(indexName); + searchRequest.scroll(new TimeValue(1, MINUTES)); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.matchAllQuery()); + searchSourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC)); + searchSourceBuilder.size(pageSize); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest searchAll(String...indexNames) { - SearchRequest searchRequest = new SearchRequest(indexNames); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.matchAllQuery()); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest searchAll(String... indexNames) { + SearchRequest searchRequest = new SearchRequest(indexNames); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.matchAllQuery()); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchScrollRequest getSearchScrollRequest(SearchResponse searchResponse) { - SearchScrollRequest scrollRequest = new SearchScrollRequest(searchResponse.getScrollId()); - scrollRequest.scroll(new TimeValue(1, MINUTES)); - return scrollRequest; - } + public static SearchScrollRequest getSearchScrollRequest(SearchResponse searchResponse) { + SearchScrollRequest scrollRequest = new SearchScrollRequest(searchResponse.getScrollId()); + scrollRequest.scroll(new TimeValue(1, MINUTES)); + return scrollRequest; + } - public static SearchRequest averageAggregationRequest(String indexName, String aggregationName, String fieldName) { - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.aggregation(AggregationBuilders.avg(aggregationName).field(fieldName)); - searchSourceBuilder.size(0); - SearchRequest searchRequest = new SearchRequest(indexName); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest averageAggregationRequest(String indexName, String aggregationName, String fieldName) { + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.aggregation(AggregationBuilders.avg(aggregationName).field(fieldName)); + searchSourceBuilder.size(0); + SearchRequest searchRequest = new SearchRequest(indexName); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest statsAggregationRequest(String indexName, String aggregationName, String fieldName) { - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.aggregation(AggregationBuilders.stats(aggregationName).field(fieldName)); - searchSourceBuilder.size(0); - SearchRequest searchRequest = new SearchRequest(indexName); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest statsAggregationRequest(String indexName, String aggregationName, String fieldName) { + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.aggregation(AggregationBuilders.stats(aggregationName).field(fieldName)); + searchSourceBuilder.size(0); + SearchRequest searchRequest = new SearchRequest(indexName); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java index 92ec47d658..5895829243 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java @@ -52,261 +52,260 @@ */ public class SocketUtils { - /** - * The default minimum value for port ranges used when finding an available - * socket port. - */ - public static final int PORT_RANGE_MIN = 1024; - - /** - * The default maximum value for port ranges used when finding an available - * socket port. - */ - public static final int PORT_RANGE_MAX = 65535; - - - private static final Random random = new Random(System.currentTimeMillis()); - - - /** - * Although {@code SocketUtils} consists solely of static utility methods, - * this constructor is intentionally {@code public}. - *

Rationale

- *

Static methods from this class may be invoked from within XML - * configuration files using the Spring Expression Language (SpEL) and the - * following syntax. - *

<bean id="bean1" ... p:port="#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" />
- * If this constructor were {@code private}, you would be required to supply - * the fully qualified class name to SpEL's {@code T()} function for each usage. - * Thus, the fact that this constructor is {@code public} allows you to reduce - * boilerplate configuration with SpEL as can be seen in the following example. - *
<bean id="socketUtils" class="org.springframework.util.SocketUtils" />
-	* <bean id="bean1" ... p:port="#{socketUtils.findAvailableTcpPort(12000)}" />
-	* <bean id="bean2" ... p:port="#{socketUtils.findAvailableTcpPort(30000)}" />
- */ - public SocketUtils() { - /* no-op */ - } - - - /** - * Find an available TCP port randomly selected from the range - * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort() { - return findAvailableTcpPort(PORT_RANGE_MIN); - } - - /** - * Find an available TCP port randomly selected from the range - * [{@code minPort}, {@value #PORT_RANGE_MAX}]. - * @param minPort the minimum port number - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort(int minPort) { - return findAvailableTcpPort(minPort, PORT_RANGE_MAX); - } - - /** - * Find an available TCP port randomly selected from the range - * [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort(int minPort, int maxPort) { - return SocketType.TCP.findAvailablePort(minPort, maxPort); - } - - /** - * Find the requested number of available TCP ports, each randomly selected - * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @param numRequested the number of available ports to find - * @return a sorted set of available TCP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableTcpPorts(int numRequested) { - return findAvailableTcpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - /** - * Find the requested number of available TCP ports, each randomly selected - * from the range [{@code minPort}, {@code maxPort}]. - * @param numRequested the number of available ports to find - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a sorted set of available TCP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { - return SocketType.TCP.findAvailablePorts(numRequested, minPort, maxPort); - } - - /** - * Find an available UDP port randomly selected from the range - * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @return an available UDP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableUdpPort() { - return findAvailableUdpPort(PORT_RANGE_MIN); - } - - /** - * Find an available UDP port randomly selected from the range - * [{@code minPort}, {@value #PORT_RANGE_MAX}]. - * @param minPort the minimum port number - * @return an available UDP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableUdpPort(int minPort) { - return findAvailableUdpPort(minPort, PORT_RANGE_MAX); - } - - /** - * Find an available UDP port randomly selected from the range - * [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return an available UDP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableUdpPort(int minPort, int maxPort) { - return SocketType.UDP.findAvailablePort(minPort, maxPort); - } - - /** - * Find the requested number of available UDP ports, each randomly selected - * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @param numRequested the number of available ports to find - * @return a sorted set of available UDP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableUdpPorts(int numRequested) { - return findAvailableUdpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - /** - * Find the requested number of available UDP ports, each randomly selected - * from the range [{@code minPort}, {@code maxPort}]. - * @param numRequested the number of available ports to find - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a sorted set of available UDP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { - return SocketType.UDP.findAvailablePorts(numRequested, minPort, maxPort); - } - - - public enum SocketType { - - TCP { - @Override - protected boolean isPortAvailable(int port) { - try { - ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket( - port, 1, InetAddress.getByName("localhost")); - serverSocket.close(); - return true; - } - catch (Exception ex) { - return false; - } - } - }, - - UDP { - @Override - protected boolean isPortAvailable(int port) { - try { - DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost")); - socket.close(); - return true; - } - catch (Exception ex) { - return false; - } - } - }; - - /** - * Determine if the specified port for this {@code SocketType} is - * currently available on {@code localhost}. - */ - protected abstract boolean isPortAvailable(int port); - - /** - * Find a pseudo-random port number within the range - * [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a random port number within the specified range - */ - private int findRandomPort(int minPort, int maxPort) { - int portRange = maxPort - minPort; - return minPort + random.nextInt(portRange + 1); - } - - /** - * Find an available port for this {@code SocketType}, randomly selected - * from the range [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return an available port number for this socket type - * @throws IllegalStateException if no available port could be found - */ - int findAvailablePort(int minPort, int maxPort) { - //Assert.assertTrue(minPort > 0, "'minPort' must be greater than 0"); - //Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'"); - //Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); - - int portRange = maxPort - minPort; - int candidatePort; - int searchCounter = 0; - do { - if (searchCounter > portRange) { - throw new IllegalStateException(String.format( - "Could not find an available %s port in the range [%d, %d] after %d attempts", - name(), minPort, maxPort, searchCounter)); - } - candidatePort = findRandomPort(minPort, maxPort); - searchCounter++; - } - while (!isPortAvailable(candidatePort)); - - return candidatePort; - } - - /** - * Find the requested number of available ports for this {@code SocketType}, - * each randomly selected from the range [{@code minPort}, {@code maxPort}]. - * @param numRequested the number of available ports to find - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a sorted set of available port numbers for this socket type - * @throws IllegalStateException if the requested number of available ports could not be found - */ - SortedSet findAvailablePorts(int numRequested, int minPort, int maxPort) { - SortedSet availablePorts = new TreeSet<>(); - int attemptCount = 0; - while ((++attemptCount <= numRequested + 100) && availablePorts.size() < numRequested) { - availablePorts.add(findAvailablePort(minPort, maxPort)); - } - - if (availablePorts.size() != numRequested) { - throw new IllegalStateException(String.format( - "Could not find %d available %s ports in the range [%d, %d]", - numRequested, name(), minPort, maxPort)); - } - - return availablePorts; - } - } + /** + * The default minimum value for port ranges used when finding an available + * socket port. + */ + public static final int PORT_RANGE_MIN = 1024; + + /** + * The default maximum value for port ranges used when finding an available + * socket port. + */ + public static final int PORT_RANGE_MAX = 65535; + + private static final Random random = new Random(System.currentTimeMillis()); + + /** + * Although {@code SocketUtils} consists solely of static utility methods, + * this constructor is intentionally {@code public}. + *

Rationale

+ *

Static methods from this class may be invoked from within XML + * configuration files using the Spring Expression Language (SpEL) and the + * following syntax. + *

<bean id="bean1" ... p:port="#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" />
+ * If this constructor were {@code private}, you would be required to supply + * the fully qualified class name to SpEL's {@code T()} function for each usage. + * Thus, the fact that this constructor is {@code public} allows you to reduce + * boilerplate configuration with SpEL as can be seen in the following example. + *
<bean id="socketUtils" class="org.springframework.util.SocketUtils" />
+    * <bean id="bean1" ... p:port="#{socketUtils.findAvailableTcpPort(12000)}" />
+    * <bean id="bean2" ... p:port="#{socketUtils.findAvailableTcpPort(30000)}" />
+ */ + public SocketUtils() { + /* no-op */ + } + + /** + * Find an available TCP port randomly selected from the range + * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableTcpPort() { + return findAvailableTcpPort(PORT_RANGE_MIN); + } + + /** + * Find an available TCP port randomly selected from the range + * [{@code minPort}, {@value #PORT_RANGE_MAX}]. + * @param minPort the minimum port number + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableTcpPort(int minPort) { + return findAvailableTcpPort(minPort, PORT_RANGE_MAX); + } + + /** + * Find an available TCP port randomly selected from the range + * [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableTcpPort(int minPort, int maxPort) { + return SocketType.TCP.findAvailablePort(minPort, maxPort); + } + + /** + * Find the requested number of available TCP ports, each randomly selected + * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @param numRequested the number of available ports to find + * @return a sorted set of available TCP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableTcpPorts(int numRequested) { + return findAvailableTcpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + /** + * Find the requested number of available TCP ports, each randomly selected + * from the range [{@code minPort}, {@code maxPort}]. + * @param numRequested the number of available ports to find + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a sorted set of available TCP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { + return SocketType.TCP.findAvailablePorts(numRequested, minPort, maxPort); + } + + /** + * Find an available UDP port randomly selected from the range + * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @return an available UDP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableUdpPort() { + return findAvailableUdpPort(PORT_RANGE_MIN); + } + + /** + * Find an available UDP port randomly selected from the range + * [{@code minPort}, {@value #PORT_RANGE_MAX}]. + * @param minPort the minimum port number + * @return an available UDP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableUdpPort(int minPort) { + return findAvailableUdpPort(minPort, PORT_RANGE_MAX); + } + + /** + * Find an available UDP port randomly selected from the range + * [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available UDP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableUdpPort(int minPort, int maxPort) { + return SocketType.UDP.findAvailablePort(minPort, maxPort); + } + + /** + * Find the requested number of available UDP ports, each randomly selected + * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @param numRequested the number of available ports to find + * @return a sorted set of available UDP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableUdpPorts(int numRequested) { + return findAvailableUdpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + /** + * Find the requested number of available UDP ports, each randomly selected + * from the range [{@code minPort}, {@code maxPort}]. + * @param numRequested the number of available ports to find + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a sorted set of available UDP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { + return SocketType.UDP.findAvailablePorts(numRequested, minPort, maxPort); + } + + public enum SocketType { + + TCP { + @Override + protected boolean isPortAvailable(int port) { + try { + ServerSocket serverSocket = ServerSocketFactory.getDefault() + .createServerSocket(port, 1, InetAddress.getByName("localhost")); + serverSocket.close(); + return true; + } catch (Exception ex) { + return false; + } + } + }, + + UDP { + @Override + protected boolean isPortAvailable(int port) { + try { + DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost")); + socket.close(); + return true; + } catch (Exception ex) { + return false; + } + } + }; + + /** + * Determine if the specified port for this {@code SocketType} is + * currently available on {@code localhost}. + */ + protected abstract boolean isPortAvailable(int port); + + /** + * Find a pseudo-random port number within the range + * [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a random port number within the specified range + */ + private int findRandomPort(int minPort, int maxPort) { + int portRange = maxPort - minPort; + return minPort + random.nextInt(portRange + 1); + } + + /** + * Find an available port for this {@code SocketType}, randomly selected + * from the range [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available port number for this socket type + * @throws IllegalStateException if no available port could be found + */ + int findAvailablePort(int minPort, int maxPort) { + // Assert.assertTrue(minPort > 0, "'minPort' must be greater than 0"); + // Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'"); + // Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); + + int portRange = maxPort - minPort; + int candidatePort; + int searchCounter = 0; + do { + if (searchCounter > portRange) { + throw new IllegalStateException( + String.format( + "Could not find an available %s port in the range [%d, %d] after %d attempts", + name(), + minPort, + maxPort, + searchCounter + ) + ); + } + candidatePort = findRandomPort(minPort, maxPort); + searchCounter++; + } while (!isPortAvailable(candidatePort)); + + return candidatePort; + } + + /** + * Find the requested number of available ports for this {@code SocketType}, + * each randomly selected from the range [{@code minPort}, {@code maxPort}]. + * @param numRequested the number of available ports to find + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a sorted set of available port numbers for this socket type + * @throws IllegalStateException if the requested number of available ports could not be found + */ + SortedSet findAvailablePorts(int numRequested, int minPort, int maxPort) { + SortedSet availablePorts = new TreeSet<>(); + int attemptCount = 0; + while ((++attemptCount <= numRequested + 100) && availablePorts.size() < numRequested) { + availablePorts.add(findAvailablePort(minPort, maxPort)); + } + + if (availablePorts.size() != numRequested) { + throw new IllegalStateException( + String.format("Could not find %d available %s ports in the range [%d, %d]", numRequested, name(), minPort, maxPort) + ); + } + + return availablePorts; + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java index 548bedbfa6..fb298c5283 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java @@ -55,158 +55,153 @@ */ public class SocketUtilsTests { - // TCP - - @Test - public void findAvailableTcpPort() { - int port = SocketUtils.findAvailableTcpPort(); - assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - @Test - public void findAvailableTcpPortWithMinPortEqualToMaxPort() { - int minMaxPort = SocketUtils.findAvailableTcpPort(); - int port = SocketUtils.findAvailableTcpPort(minMaxPort, minMaxPort); - assertThat(port, equalTo(minMaxPort)); - } - - @Test - public void findAvailableTcpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { - int port = SocketUtils.findAvailableTcpPort(); - try (ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost"))) { - assertThat(socket, notNullValue()); - // will only look for the exact port - IllegalStateException exception = assertThrows( - IllegalStateException.class, - () -> SocketUtils.findAvailableTcpPort(port, port) - ); - assertThat(exception.getMessage(), startsWith("Could not find an available TCP port")); - assertThat(exception.getMessage(), endsWith("after 1 attempts")); - } - } - - @Test - public void findAvailableTcpPortWithMin() { - int port = SocketUtils.findAvailableTcpPort(50000); - assertPortInRange(port, 50000, PORT_RANGE_MAX); - } - - @Test - public void findAvailableTcpPortInRange() { - int minPort = 20000; - int maxPort = minPort + 1000; - int port = SocketUtils.findAvailableTcpPort(minPort, maxPort); - assertPortInRange(port, minPort, maxPort); - } - - @Test - public void find4AvailableTcpPorts() { - findAvailableTcpPorts(4); - } - - @Test - public void find50AvailableTcpPorts() { - findAvailableTcpPorts(50); - } - - @Test - public void find4AvailableTcpPortsInRange() { - findAvailableTcpPorts(4, 30000, 35000); - } - - @Test - public void find50AvailableTcpPortsInRange() { - findAvailableTcpPorts(50, 40000, 45000); - } - - // UDP - - @Test - public void findAvailableUdpPort() { - int port = SocketUtils.findAvailableUdpPort(); - assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - @Test - public void findAvailableUdpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { - int port = SocketUtils.findAvailableUdpPort(); - try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost"))) { - assertThat(socket, notNullValue()); - // will only look for the exact port - IllegalStateException exception = assertThrows( - IllegalStateException.class, - () -> SocketUtils.findAvailableUdpPort(port, port) - ); - assertThat(exception.getMessage(), startsWith("Could not find an available UDP port")); - assertThat(exception.getMessage(), endsWith("after 1 attempts")); - } - } - - @Test - public void findAvailableUdpPortWithMin() { - int port = SocketUtils.findAvailableUdpPort(50000); - assertPortInRange(port, 50000, PORT_RANGE_MAX); - } - - @Test - public void findAvailableUdpPortInRange() { - int minPort = 20000; - int maxPort = minPort + 1000; - int port = SocketUtils.findAvailableUdpPort(minPort, maxPort); - assertPortInRange(port, minPort, maxPort); - } - - @Test - public void find4AvailableUdpPorts() { - findAvailableUdpPorts(4); - } - - @Test - public void find50AvailableUdpPorts() { - findAvailableUdpPorts(50); - } - - @Test - public void find4AvailableUdpPortsInRange() { - findAvailableUdpPorts(4, 30000, 35000); - } - - @Test - public void find50AvailableUdpPortsInRange() { - findAvailableUdpPorts(50, 40000, 45000); - } - - // Helpers - - private void findAvailableTcpPorts(int numRequested) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested); - assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); - assertAvailablePorts(ports, numRequested, minPort, maxPort); - } - - private void findAvailableUdpPorts(int numRequested) { - SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested); - assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - private void findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { - SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort); - assertAvailablePorts(ports, numRequested, minPort, maxPort); - } - private void assertPortInRange(int port, int minPort, int maxPort) { - assertThat("port [" + port + "] >= " + minPort, port, greaterThanOrEqualTo(minPort)); - assertThat("port [" + port + "] <= " + maxPort, port, lessThanOrEqualTo(maxPort)); - } - - private void assertAvailablePorts(SortedSet ports, int numRequested, int minPort, int maxPort) { - assertThat("number of ports requested", ports.size(), equalTo(numRequested)); - for (int port : ports) { - assertPortInRange(port, minPort, maxPort); - } - } + // TCP + + @Test + public void findAvailableTcpPort() { + int port = SocketUtils.findAvailableTcpPort(); + assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + @Test + public void findAvailableTcpPortWithMinPortEqualToMaxPort() { + int minMaxPort = SocketUtils.findAvailableTcpPort(); + int port = SocketUtils.findAvailableTcpPort(minMaxPort, minMaxPort); + assertThat(port, equalTo(minMaxPort)); + } + + @Test + public void findAvailableTcpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { + int port = SocketUtils.findAvailableTcpPort(); + try (ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost"))) { + assertThat(socket, notNullValue()); + // will only look for the exact port + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> SocketUtils.findAvailableTcpPort(port, port)); + assertThat(exception.getMessage(), startsWith("Could not find an available TCP port")); + assertThat(exception.getMessage(), endsWith("after 1 attempts")); + } + } + + @Test + public void findAvailableTcpPortWithMin() { + int port = SocketUtils.findAvailableTcpPort(50000); + assertPortInRange(port, 50000, PORT_RANGE_MAX); + } + + @Test + public void findAvailableTcpPortInRange() { + int minPort = 20000; + int maxPort = minPort + 1000; + int port = SocketUtils.findAvailableTcpPort(minPort, maxPort); + assertPortInRange(port, minPort, maxPort); + } + + @Test + public void find4AvailableTcpPorts() { + findAvailableTcpPorts(4); + } + + @Test + public void find50AvailableTcpPorts() { + findAvailableTcpPorts(50); + } + + @Test + public void find4AvailableTcpPortsInRange() { + findAvailableTcpPorts(4, 30000, 35000); + } + + @Test + public void find50AvailableTcpPortsInRange() { + findAvailableTcpPorts(50, 40000, 45000); + } + + // UDP + + @Test + public void findAvailableUdpPort() { + int port = SocketUtils.findAvailableUdpPort(); + assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + @Test + public void findAvailableUdpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { + int port = SocketUtils.findAvailableUdpPort(); + try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost"))) { + assertThat(socket, notNullValue()); + // will only look for the exact port + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> SocketUtils.findAvailableUdpPort(port, port)); + assertThat(exception.getMessage(), startsWith("Could not find an available UDP port")); + assertThat(exception.getMessage(), endsWith("after 1 attempts")); + } + } + + @Test + public void findAvailableUdpPortWithMin() { + int port = SocketUtils.findAvailableUdpPort(50000); + assertPortInRange(port, 50000, PORT_RANGE_MAX); + } + + @Test + public void findAvailableUdpPortInRange() { + int minPort = 20000; + int maxPort = minPort + 1000; + int port = SocketUtils.findAvailableUdpPort(minPort, maxPort); + assertPortInRange(port, minPort, maxPort); + } + + @Test + public void find4AvailableUdpPorts() { + findAvailableUdpPorts(4); + } + + @Test + public void find50AvailableUdpPorts() { + findAvailableUdpPorts(50); + } + + @Test + public void find4AvailableUdpPortsInRange() { + findAvailableUdpPorts(4, 30000, 35000); + } + + @Test + public void find50AvailableUdpPortsInRange() { + findAvailableUdpPorts(50, 40000, 45000); + } + + // Helpers + + private void findAvailableTcpPorts(int numRequested) { + SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested); + assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { + SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); + assertAvailablePorts(ports, numRequested, minPort, maxPort); + } + + private void findAvailableUdpPorts(int numRequested) { + SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested); + assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + private void findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { + SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort); + assertAvailablePorts(ports, numRequested, minPort, maxPort); + } + + private void assertPortInRange(int port, int minPort, int maxPort) { + assertThat("port [" + port + "] >= " + minPort, port, greaterThanOrEqualTo(minPort)); + assertThat("port [" + port + "] <= " + maxPort, port, lessThanOrEqualTo(maxPort)); + } + + private void assertAvailablePorts(SortedSet ports, int numRequested, int minPort, int maxPort) { + assertThat("number of ports requested", ports.size(), equalTo(numRequested)); + for (int port : ports) { + assertPortInRange(port, minPort, maxPort); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java index 80db4ba87a..d5dce0056a 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java @@ -10,6 +10,6 @@ package org.opensearch.test.framework.cluster; enum StartStage { - INITIALIZED, - RETRY + INITIALIZED, + RETRY } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java index 864b8db3f1..f446cac933 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java @@ -88,347 +88,353 @@ * instance from OpenSearchClientProvider. */ public class TestRestClient implements AutoCloseable { - - private static final Logger log = LogManager.getLogger(TestRestClient.class); - - private boolean enableHTTPClientSSL = true; - private boolean sendHTTPClientCertificate = false; - private InetSocketAddress nodeHttpAddress; - private RequestConfig requestConfig; - private List
headers = new ArrayList<>(); - private Header CONTENT_TYPE_JSON = new BasicHeader("Content-Type", "application/json"); - private SSLContext sslContext; - - private final InetAddress sourceInetAddress; - - public TestRestClient(InetSocketAddress nodeHttpAddress, List
headers, SSLContext sslContext, InetAddress sourceInetAddress) { - this.nodeHttpAddress = nodeHttpAddress; - this.headers.addAll(headers); - this.sslContext = sslContext; - this.sourceInetAddress = sourceInetAddress; - } - - public HttpResponse get(String path, List queryParameters, Header... headers) { - try { - URI uri = new URIBuilder(getHttpServerUri()).setPath(path).addParameters(queryParameters).build(); - return executeRequest(new HttpGet(uri), headers); - } catch (URISyntaxException ex) { - throw new RuntimeException("Incorrect URI syntax", ex); - } - } - - public HttpResponse get(String path, Header... headers) { - return get(path, Collections.emptyList(), headers); - } - - public HttpResponse getWithJsonBody(String path, String body, Header... headers) { - try { - HttpGet httpGet = new HttpGet( new URIBuilder(getHttpServerUri()).setPath(path).build()); - httpGet.setEntity(toStringEntity(body)); - return executeRequest(httpGet, mergeHeaders(CONTENT_TYPE_JSON, headers)); - } catch (URISyntaxException ex) { - throw new RuntimeException("Incorrect URI syntax", ex); - } - } - - public HttpResponse getAuthInfo( Header... headers) { - return executeRequest(new HttpGet(getHttpServerUri() + "/_opendistro/_security/authinfo?pretty"), headers); - } - - public void assertCorrectCredentials(String expectedUserName) { - HttpResponse response = getAuthInfo(); - assertThat(response, notNullValue()); - response.assertStatusCode(200); - String username = response.getTextFromJsonBody("/user_name"); - String message = String.format("Expected user name is '%s', but was '%s'", expectedUserName, username); - assertThat(message, username, equalTo(expectedUserName)); - } - - public HttpResponse head(String path, Header... headers) { - return executeRequest(new HttpHead(getHttpServerUri() + "/" + path), headers); - } - - public HttpResponse options(String path, Header... headers) { - return executeRequest(new HttpOptions(getHttpServerUri() + "/" + path), headers); - } - - public HttpResponse putJson(String path, String body, Header... headers) { - HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); - uriRequest.setEntity(toStringEntity(body)); - return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); - } - - private StringEntity toStringEntity(String body) { - return new StringEntity(body); - } - - public HttpResponse putJson(String path, ToXContentObject body) { - return putJson(path, Strings.toString(XContentType.JSON, body)); - } - - public HttpResponse put(String path) { - HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); - return executeRequest(uriRequest); - } - - public HttpResponse delete(String path, Header... headers) { - return executeRequest(new HttpDelete(getHttpServerUri() + "/" + path), headers); - } - - public HttpResponse postJson(String path, String body, Header... headers) { - HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); - uriRequest.setEntity(toStringEntity(body)); - return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); - } - - public HttpResponse postJson(String path, ToXContentObject body) { - return postJson(path, Strings.toString(XContentType.JSON, body)); - } - - public HttpResponse post(String path) { - HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); - return executeRequest(uriRequest); - } - - public HttpResponse patch(String path, String body) { - HttpPatch uriRequest = new HttpPatch(getHttpServerUri() + "/" + path); - uriRequest.setEntity(toStringEntity(body)); - return executeRequest(uriRequest, CONTENT_TYPE_JSON); - } - - public HttpResponse assignRoleToUser(String username, String roleName) { - Objects.requireNonNull(roleName, "Role name is required"); - Objects.requireNonNull(username, "User name is required"); - String body = String.format("[{\"op\":\"add\",\"path\":\"/opendistro_security_roles\",\"value\":[\"%s\"]}]", roleName); - return patch("_plugins/_security/api/internalusers/" + username, body); - } - - public HttpResponse createRole(String roleName, ToXContentObject role) { - Objects.requireNonNull(roleName, "Role name is required"); - Objects.requireNonNull(role, "Role is required"); - return putJson("_plugins/_security/api/roles/" + roleName, role); - } - - public HttpResponse createUser(String userName, ToXContentObject user) { - Objects.requireNonNull(userName, "User name is required"); - Objects.requireNonNull(user, "User is required"); - return putJson("_plugins/_security/api/internalusers/" + userName, user); - } - - public HttpResponse executeRequest(HttpUriRequest uriRequest, Header... requestSpecificHeaders) { - try(CloseableHttpClient httpClient = getHTTPClient()) { - - - if (requestSpecificHeaders != null && requestSpecificHeaders.length > 0) { - for (int i = 0; i < requestSpecificHeaders.length; i++) { - Header h = requestSpecificHeaders[i]; - uriRequest.addHeader(h); - } - } - - for (Header header : headers) { - uriRequest.addHeader(header); - } - - HttpResponse res = new HttpResponse(httpClient.execute(uriRequest)); - log.debug(res.getBody()); - return res; - } catch (IOException e) { - throw new RestClientException("Error occured during HTTP request execution", e); - } - } - - public void createRoleMapping(String backendRoleName, String roleName) { - requireNonNull(backendRoleName, "Backend role name is required"); - requireNonNull(roleName, "Role name is required"); - String path = "_plugins/_security/api/rolesmapping/" + roleName; - String body = String.format("{\"backend_roles\": [\"%s\"]}", backendRoleName); - HttpResponse response = putJson(path, body); - response.assertStatusCode(201); - } - - protected final String getHttpServerUri() { - return "http" + (enableHTTPClientSSL ? "s" : "") + "://" + nodeHttpAddress.getHostString() + ":" + nodeHttpAddress.getPort(); - } - - protected final CloseableHttpClient getHTTPClient() { - HttpRoutePlanner routePlanner = Optional.ofNullable(sourceInetAddress).map(LocalAddressRoutePlanner::new).orElse(null); - var factory = new CloseableHttpClientFactory(sslContext, requestConfig, routePlanner, null); - return factory.getHTTPClient(); - } - - private Header[] mergeHeaders(Header header, Header... headers) { - - if (headers == null || headers.length == 0) { - return new Header[] { header }; - } else { - Header[] result = new Header[headers.length + 1]; - result[0] = header; - System.arraycopy(headers, 0, result, 1, headers.length); - return result; - } - } - - public static class HttpResponse { - private final CloseableHttpResponse inner; - private final String body; - private final Header[] header; - private final int statusCode; - private final String statusReason; - - public HttpResponse(CloseableHttpResponse inner) throws IllegalStateException, IOException { - super(); - this.inner = inner; - final HttpEntity entity = inner.getEntity(); - if (entity == null) { //head request does not have a entity - this.body = ""; - } else { - this.body = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8); - } - this.header = inner.getHeaders(); - this.statusCode = inner.getCode(); - this.statusReason = inner.getReasonPhrase(); - inner.close(); - } - - public String getContentType() { - Header h = getInner().getFirstHeader("content-type"); - if (h != null) { - return h.getValue(); - } - return null; - } - - public boolean isJsonContentType() { - String ct = getContentType(); - if (ct == null) { - return false; - } - return ct.contains("application/json"); - } - - public CloseableHttpResponse getInner() { - return inner; - } - - public String getBody() { - return body; - } - - public Header[] getHeader() { - return header; - } - - public Optional
findHeader(String name) { - return Arrays.stream(header) - .filter(header -> requireNonNull(name, "Header name is mandatory.").equalsIgnoreCase(header.getName())) - .findFirst(); - } - - public Header getHeader(String name) { - return findHeader(name).orElseThrow(); - } - - public boolean containHeader(String name) { - return findHeader(name).isPresent(); - } - - public int getStatusCode() { - return statusCode; - } - - public String getStatusReason() { - return statusReason; - } - - public List
getHeaders() { - return header == null ? Collections.emptyList() : Arrays.asList(header); - } - - public String getTextFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asText(); - } - - public List getTextArrayFromJsonBody(String jsonPointer) { - return StreamSupport.stream(getJsonNodeAt(jsonPointer).spliterator(), false) - .map(JsonNode::textValue) - .collect(Collectors.toList()); - } - - public int getIntFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asInt(); - } - - public Boolean getBooleanFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asBoolean(); - } - - public Double getDoubleFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asDouble(); - } - - public Long getLongFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asLong(); - } - - private JsonNode getJsonNodeAt(String jsonPointer) { - try { - return toJsonNode().at(jsonPointer); - } catch (IOException e) { - throw new IllegalArgumentException("Cound not convert response body to JSON node ",e); - } - } - - private JsonNode toJsonNode() throws JsonProcessingException, IOException { - return DefaultObjectMapper.objectMapper.readTree(getBody()); - } - - - - @Override - public String toString() { - return "HttpResponse [inner=" + inner + ", body=" + body + ", header=" + Arrays.toString(header) + ", statusCode=" + statusCode - + ", statusReason=" + statusReason + "]"; - } - - public T getBodyAs(Class authInfoClass) { - try { - return DefaultObjectMapper.readValue(getBody(), authInfoClass); - } catch (IOException e) { - throw new RuntimeException("Cannot parse response body", e); - } - } - - public void assertStatusCode(int expectedHttpStatus) { - String reason = format("Expected status code is '%d', but was '%d'. Response body '%s'.", expectedHttpStatus, statusCode, body); - assertThat(reason, statusCode, equalTo(expectedHttpStatus)); - } - } - - @Override - public String toString() { - return "TestRestClient [server=" + getHttpServerUri() + ", node=" + nodeHttpAddress + "]"; - } - - public RequestConfig getRequestConfig() { - return requestConfig; - } - - public void setRequestConfig(RequestConfig requestConfig) { - this.requestConfig = requestConfig; - } - - public boolean isSendHTTPClientCertificate() { - return sendHTTPClientCertificate; - } - - public void setSendHTTPClientCertificate(boolean sendHTTPClientCertificate) { - this.sendHTTPClientCertificate = sendHTTPClientCertificate; - } - - @Override - public void close() { - // TODO: Is there anything to clean up here? - } + + private static final Logger log = LogManager.getLogger(TestRestClient.class); + + private boolean enableHTTPClientSSL = true; + private boolean sendHTTPClientCertificate = false; + private InetSocketAddress nodeHttpAddress; + private RequestConfig requestConfig; + private List
headers = new ArrayList<>(); + private Header CONTENT_TYPE_JSON = new BasicHeader("Content-Type", "application/json"); + private SSLContext sslContext; + + private final InetAddress sourceInetAddress; + + public TestRestClient(InetSocketAddress nodeHttpAddress, List
headers, SSLContext sslContext, InetAddress sourceInetAddress) { + this.nodeHttpAddress = nodeHttpAddress; + this.headers.addAll(headers); + this.sslContext = sslContext; + this.sourceInetAddress = sourceInetAddress; + } + + public HttpResponse get(String path, List queryParameters, Header... headers) { + try { + URI uri = new URIBuilder(getHttpServerUri()).setPath(path).addParameters(queryParameters).build(); + return executeRequest(new HttpGet(uri), headers); + } catch (URISyntaxException ex) { + throw new RuntimeException("Incorrect URI syntax", ex); + } + } + + public HttpResponse get(String path, Header... headers) { + return get(path, Collections.emptyList(), headers); + } + + public HttpResponse getWithJsonBody(String path, String body, Header... headers) { + try { + HttpGet httpGet = new HttpGet(new URIBuilder(getHttpServerUri()).setPath(path).build()); + httpGet.setEntity(toStringEntity(body)); + return executeRequest(httpGet, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } catch (URISyntaxException ex) { + throw new RuntimeException("Incorrect URI syntax", ex); + } + } + + public HttpResponse getAuthInfo(Header... headers) { + return executeRequest(new HttpGet(getHttpServerUri() + "/_opendistro/_security/authinfo?pretty"), headers); + } + + public void assertCorrectCredentials(String expectedUserName) { + HttpResponse response = getAuthInfo(); + assertThat(response, notNullValue()); + response.assertStatusCode(200); + String username = response.getTextFromJsonBody("/user_name"); + String message = String.format("Expected user name is '%s', but was '%s'", expectedUserName, username); + assertThat(message, username, equalTo(expectedUserName)); + } + + public HttpResponse head(String path, Header... headers) { + return executeRequest(new HttpHead(getHttpServerUri() + "/" + path), headers); + } + + public HttpResponse options(String path, Header... headers) { + return executeRequest(new HttpOptions(getHttpServerUri() + "/" + path), headers); + } + + public HttpResponse putJson(String path, String body, Header... headers) { + HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); + uriRequest.setEntity(toStringEntity(body)); + return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } + + private StringEntity toStringEntity(String body) { + return new StringEntity(body); + } + + public HttpResponse putJson(String path, ToXContentObject body) { + return putJson(path, Strings.toString(XContentType.JSON, body)); + } + + public HttpResponse put(String path) { + HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); + return executeRequest(uriRequest); + } + + public HttpResponse delete(String path, Header... headers) { + return executeRequest(new HttpDelete(getHttpServerUri() + "/" + path), headers); + } + + public HttpResponse postJson(String path, String body, Header... headers) { + HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); + uriRequest.setEntity(toStringEntity(body)); + return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } + + public HttpResponse postJson(String path, ToXContentObject body) { + return postJson(path, Strings.toString(XContentType.JSON, body)); + } + + public HttpResponse post(String path) { + HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); + return executeRequest(uriRequest); + } + + public HttpResponse patch(String path, String body) { + HttpPatch uriRequest = new HttpPatch(getHttpServerUri() + "/" + path); + uriRequest.setEntity(toStringEntity(body)); + return executeRequest(uriRequest, CONTENT_TYPE_JSON); + } + + public HttpResponse assignRoleToUser(String username, String roleName) { + Objects.requireNonNull(roleName, "Role name is required"); + Objects.requireNonNull(username, "User name is required"); + String body = String.format("[{\"op\":\"add\",\"path\":\"/opendistro_security_roles\",\"value\":[\"%s\"]}]", roleName); + return patch("_plugins/_security/api/internalusers/" + username, body); + } + + public HttpResponse createRole(String roleName, ToXContentObject role) { + Objects.requireNonNull(roleName, "Role name is required"); + Objects.requireNonNull(role, "Role is required"); + return putJson("_plugins/_security/api/roles/" + roleName, role); + } + + public HttpResponse createUser(String userName, ToXContentObject user) { + Objects.requireNonNull(userName, "User name is required"); + Objects.requireNonNull(user, "User is required"); + return putJson("_plugins/_security/api/internalusers/" + userName, user); + } + + public HttpResponse executeRequest(HttpUriRequest uriRequest, Header... requestSpecificHeaders) { + try (CloseableHttpClient httpClient = getHTTPClient()) { + + if (requestSpecificHeaders != null && requestSpecificHeaders.length > 0) { + for (int i = 0; i < requestSpecificHeaders.length; i++) { + Header h = requestSpecificHeaders[i]; + uriRequest.addHeader(h); + } + } + + for (Header header : headers) { + uriRequest.addHeader(header); + } + + HttpResponse res = new HttpResponse(httpClient.execute(uriRequest)); + log.debug(res.getBody()); + return res; + } catch (IOException e) { + throw new RestClientException("Error occured during HTTP request execution", e); + } + } + + public void createRoleMapping(String backendRoleName, String roleName) { + requireNonNull(backendRoleName, "Backend role name is required"); + requireNonNull(roleName, "Role name is required"); + String path = "_plugins/_security/api/rolesmapping/" + roleName; + String body = String.format("{\"backend_roles\": [\"%s\"]}", backendRoleName); + HttpResponse response = putJson(path, body); + response.assertStatusCode(201); + } + + protected final String getHttpServerUri() { + return "http" + (enableHTTPClientSSL ? "s" : "") + "://" + nodeHttpAddress.getHostString() + ":" + nodeHttpAddress.getPort(); + } + + protected final CloseableHttpClient getHTTPClient() { + HttpRoutePlanner routePlanner = Optional.ofNullable(sourceInetAddress).map(LocalAddressRoutePlanner::new).orElse(null); + var factory = new CloseableHttpClientFactory(sslContext, requestConfig, routePlanner, null); + return factory.getHTTPClient(); + } + + private Header[] mergeHeaders(Header header, Header... headers) { + + if (headers == null || headers.length == 0) { + return new Header[] { header }; + } else { + Header[] result = new Header[headers.length + 1]; + result[0] = header; + System.arraycopy(headers, 0, result, 1, headers.length); + return result; + } + } + + public static class HttpResponse { + private final CloseableHttpResponse inner; + private final String body; + private final Header[] header; + private final int statusCode; + private final String statusReason; + + public HttpResponse(CloseableHttpResponse inner) throws IllegalStateException, IOException { + super(); + this.inner = inner; + final HttpEntity entity = inner.getEntity(); + if (entity == null) { // head request does not have a entity + this.body = ""; + } else { + this.body = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8); + } + this.header = inner.getHeaders(); + this.statusCode = inner.getCode(); + this.statusReason = inner.getReasonPhrase(); + inner.close(); + } + + public String getContentType() { + Header h = getInner().getFirstHeader("content-type"); + if (h != null) { + return h.getValue(); + } + return null; + } + + public boolean isJsonContentType() { + String ct = getContentType(); + if (ct == null) { + return false; + } + return ct.contains("application/json"); + } + + public CloseableHttpResponse getInner() { + return inner; + } + + public String getBody() { + return body; + } + + public Header[] getHeader() { + return header; + } + + public Optional
findHeader(String name) { + return Arrays.stream(header) + .filter(header -> requireNonNull(name, "Header name is mandatory.").equalsIgnoreCase(header.getName())) + .findFirst(); + } + + public Header getHeader(String name) { + return findHeader(name).orElseThrow(); + } + + public boolean containHeader(String name) { + return findHeader(name).isPresent(); + } + + public int getStatusCode() { + return statusCode; + } + + public String getStatusReason() { + return statusReason; + } + + public List
getHeaders() { + return header == null ? Collections.emptyList() : Arrays.asList(header); + } + + public String getTextFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asText(); + } + + public List getTextArrayFromJsonBody(String jsonPointer) { + return StreamSupport.stream(getJsonNodeAt(jsonPointer).spliterator(), false) + .map(JsonNode::textValue) + .collect(Collectors.toList()); + } + + public int getIntFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asInt(); + } + + public Boolean getBooleanFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asBoolean(); + } + + public Double getDoubleFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asDouble(); + } + + public Long getLongFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asLong(); + } + + private JsonNode getJsonNodeAt(String jsonPointer) { + try { + return toJsonNode().at(jsonPointer); + } catch (IOException e) { + throw new IllegalArgumentException("Cound not convert response body to JSON node ", e); + } + } + + private JsonNode toJsonNode() throws JsonProcessingException, IOException { + return DefaultObjectMapper.objectMapper.readTree(getBody()); + } + + @Override + public String toString() { + return "HttpResponse [inner=" + + inner + + ", body=" + + body + + ", header=" + + Arrays.toString(header) + + ", statusCode=" + + statusCode + + ", statusReason=" + + statusReason + + "]"; + } + + public T getBodyAs(Class authInfoClass) { + try { + return DefaultObjectMapper.readValue(getBody(), authInfoClass); + } catch (IOException e) { + throw new RuntimeException("Cannot parse response body", e); + } + } + + public void assertStatusCode(int expectedHttpStatus) { + String reason = format("Expected status code is '%d', but was '%d'. Response body '%s'.", expectedHttpStatus, statusCode, body); + assertThat(reason, statusCode, equalTo(expectedHttpStatus)); + } + } + + @Override + public String toString() { + return "TestRestClient [server=" + getHttpServerUri() + ", node=" + nodeHttpAddress + "]"; + } + + public RequestConfig getRequestConfig() { + return requestConfig; + } + + public void setRequestConfig(RequestConfig requestConfig) { + this.requestConfig = requestConfig; + } + + public boolean isSendHTTPClientCertificate() { + return sendHTTPClientCertificate; + } + + public void setSendHTTPClientCertificate(boolean sendHTTPClientCertificate) { + this.sendHTTPClientCertificate = sendHTTPClientCertificate; + } + + @Override + public void close() { + // TODO: Is there anything to clean up here? + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java index c1f7a7a737..3b75730303 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java @@ -36,134 +36,134 @@ */ public class TestRestClientConfiguration { - /** - * Username - */ - private String username; - /** - * Password - */ - private String password; - /** - * HTTP headers which should be attached to each HTTP request which is sent by {@link TestRestClient} - */ - private final List
headers = new ArrayList<>(); - /** - * IP address of client socket of {@link TestRestClient} - */ - private InetAddress sourceInetAddress; - - /** - * Set username - * @param username username - * @return builder - */ - public TestRestClientConfiguration username(String username) { - this.username = username; - return this; - } - - /** - * Set user's password - * @param password password - * @return builder - */ - public TestRestClientConfiguration password(String password) { - this.password = password; - return this; - } - - /** - * The method sets username and password read form userCredentialsHolder - * @param userCredentialsHolder source of credentials - * @return builder - */ - public TestRestClientConfiguration credentials(UserCredentialsHolder userCredentialsHolder) { - Objects.requireNonNull(userCredentialsHolder, "User credential holder is required."); - this.username = userCredentialsHolder.getName(); - this.password = userCredentialsHolder.getPassword(); - return this; - } - - /** - * Add HTTP headers which are attached to each HTTP request - * @param headers headers - * @return builder - */ - public TestRestClientConfiguration headers(Header...headers) { - this.headers.addAll(Arrays.asList(Objects.requireNonNull(headers, "Headers are required"))); - return this; - } - /** - * Add HTTP headers which are attached to each HTTP request - * @param headers list of headers - * @return builder - */ - public TestRestClientConfiguration headers(List
headers) { - this.headers.addAll(Objects.requireNonNull(headers, "Cannot add null headers")); - return this; - } - - /** - * Add HTTP header to each request - * @param name header name - * @param value header value - * @return builder - */ - public TestRestClientConfiguration header(String name, Object value) { - return headers(new BasicHeader(name, value)); - } - - /** - * Set IP address of client socket used by {@link TestRestClient} - * @param sourceInetAddress IP address - * @return builder - */ - public TestRestClientConfiguration sourceInetAddress(InetAddress sourceInetAddress) { - this.sourceInetAddress = sourceInetAddress; - return this; - } - - public TestRestClientConfiguration sourceInetAddress(String sourceInetAddress) { - try { - this.sourceInetAddress = InetAddress.getByName(sourceInetAddress); - return this; - } catch (UnknownHostException e) { - throw new RuntimeException("Cannot get IP address for string " + sourceInetAddress, e); - } - } - - public static TestRestClientConfiguration userWithSourceIp(UserCredentialsHolder credentials, String sourceIpAddress) { - return new TestRestClientConfiguration().credentials(credentials).sourceInetAddress(sourceIpAddress); - } - - /** - * Return complete header list. Basic authentication header is created using fields {@link #username} and {@link #password} - * @return header list - */ - List
getHeaders() { - return Stream.concat(createBasicAuthHeader().stream(), headers.stream()).collect(Collectors.toList()); - } - - private Optional
createBasicAuthHeader() { - if(containsCredentials()) { - return Optional.of(getBasicAuthHeader(username, password)); - } - return Optional.empty(); - } - - private boolean containsCredentials() { - return StringUtils.isNoneBlank(username) && StringUtils.isNoneBlank(password); - } - - InetAddress getSourceInetAddress() { - return sourceInetAddress; - } - - public static Header getBasicAuthHeader(String user, String password) { - String value ="Basic " + Base64.getEncoder() - .encodeToString((user + ":" + requireNonNull(password)) - .getBytes(StandardCharsets.UTF_8)); - return new BasicHeader("Authorization", value); - } + /** + * Username + */ + private String username; + /** + * Password + */ + private String password; + /** + * HTTP headers which should be attached to each HTTP request which is sent by {@link TestRestClient} + */ + private final List
headers = new ArrayList<>(); + /** + * IP address of client socket of {@link TestRestClient} + */ + private InetAddress sourceInetAddress; + + /** + * Set username + * @param username username + * @return builder + */ + public TestRestClientConfiguration username(String username) { + this.username = username; + return this; + } + + /** + * Set user's password + * @param password password + * @return builder + */ + public TestRestClientConfiguration password(String password) { + this.password = password; + return this; + } + + /** + * The method sets username and password read form userCredentialsHolder + * @param userCredentialsHolder source of credentials + * @return builder + */ + public TestRestClientConfiguration credentials(UserCredentialsHolder userCredentialsHolder) { + Objects.requireNonNull(userCredentialsHolder, "User credential holder is required."); + this.username = userCredentialsHolder.getName(); + this.password = userCredentialsHolder.getPassword(); + return this; + } + + /** + * Add HTTP headers which are attached to each HTTP request + * @param headers headers + * @return builder + */ + public TestRestClientConfiguration headers(Header... headers) { + this.headers.addAll(Arrays.asList(Objects.requireNonNull(headers, "Headers are required"))); + return this; + } + + /** + * Add HTTP headers which are attached to each HTTP request + * @param headers list of headers + * @return builder + */ + public TestRestClientConfiguration headers(List
headers) { + this.headers.addAll(Objects.requireNonNull(headers, "Cannot add null headers")); + return this; + } + + /** + * Add HTTP header to each request + * @param name header name + * @param value header value + * @return builder + */ + public TestRestClientConfiguration header(String name, Object value) { + return headers(new BasicHeader(name, value)); + } + + /** + * Set IP address of client socket used by {@link TestRestClient} + * @param sourceInetAddress IP address + * @return builder + */ + public TestRestClientConfiguration sourceInetAddress(InetAddress sourceInetAddress) { + this.sourceInetAddress = sourceInetAddress; + return this; + } + + public TestRestClientConfiguration sourceInetAddress(String sourceInetAddress) { + try { + this.sourceInetAddress = InetAddress.getByName(sourceInetAddress); + return this; + } catch (UnknownHostException e) { + throw new RuntimeException("Cannot get IP address for string " + sourceInetAddress, e); + } + } + + public static TestRestClientConfiguration userWithSourceIp(UserCredentialsHolder credentials, String sourceIpAddress) { + return new TestRestClientConfiguration().credentials(credentials).sourceInetAddress(sourceIpAddress); + } + + /** + * Return complete header list. Basic authentication header is created using fields {@link #username} and {@link #password} + * @return header list + */ + List
getHeaders() { + return Stream.concat(createBasicAuthHeader().stream(), headers.stream()).collect(Collectors.toList()); + } + + private Optional
createBasicAuthHeader() { + if (containsCredentials()) { + return Optional.of(getBasicAuthHeader(username, password)); + } + return Optional.empty(); + } + + private boolean containsCredentials() { + return StringUtils.isNoneBlank(username) && StringUtils.isNoneBlank(password); + } + + InetAddress getSourceInetAddress() { + return sourceInetAddress; + } + + public static Header getBasicAuthHeader(String user, String password) { + String value = "Basic " + + Base64.getEncoder().encodeToString((user + ":" + requireNonNull(password)).getBytes(StandardCharsets.UTF_8)); + return new BasicHeader("Authorization", value); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java index fd40a85292..583a0cdaeb 100755 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java @@ -19,38 +19,38 @@ public class EmbeddedLDAPServer extends ExternalResource { - private final LdapServer server; - - private final LdifData ldifData; - - public EmbeddedLDAPServer(CertificateData trustAnchor, CertificateData ldapCertificate, LdifData ldifData) { - this.ldifData = Objects.requireNonNull(ldifData, "Ldif data is required"); - this.server = new LdapServer(trustAnchor, ldapCertificate); - } - - @Override - protected void before() { - try { - server.start(ldifData); - } catch (Exception e) { - throw new RuntimeException("Cannot start ldap server", e); - } - } - - @Override - protected void after() { - try { - server.stop(); - } catch (InterruptedException e) { - throw new RuntimeException("Cannot stop LDAP server.", e); - } - } - - public int getLdapNonTlsPort() { - return server.getLdapNonTlsPort(); - } - - public int getLdapTlsPort() { - return server.getLdapsTlsPort(); - } + private final LdapServer server; + + private final LdifData ldifData; + + public EmbeddedLDAPServer(CertificateData trustAnchor, CertificateData ldapCertificate, LdifData ldifData) { + this.ldifData = Objects.requireNonNull(ldifData, "Ldif data is required"); + this.server = new LdapServer(trustAnchor, ldapCertificate); + } + + @Override + protected void before() { + try { + server.start(ldifData); + } catch (Exception e) { + throw new RuntimeException("Cannot start ldap server", e); + } + } + + @Override + protected void after() { + try { + server.stop(); + } catch (InterruptedException e) { + throw new RuntimeException("Cannot stop LDAP server.", e); + } + } + + public int getLdapNonTlsPort() { + return server.getLdapNonTlsPort(); + } + + public int getLdapTlsPort() { + return server.getLdapsTlsPort(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java index 13add742e4..18a14242cc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java @@ -52,173 +52,175 @@ * Based on class com.amazon.dlic.auth.ldap.srv.LdapServer from older tests */ final class LdapServer { - private static final Logger log = LogManager.getLogger(LdapServer.class); - - private static final int LOCK_TIMEOUT = 60; - private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; - - private static final String LOCK_TIMEOUT_MSG = "Unable to obtain lock due to timeout after " + LOCK_TIMEOUT + " " + TIME_UNIT.toString(); - private static final String SERVER_NOT_STARTED = "The LDAP server is not started."; - private static final String SERVER_ALREADY_STARTED = "The LDAP server is already started."; - - private final CertificateData trustAnchor; - - private final CertificateData ldapCertificate; - - private InMemoryDirectoryServer server; - private final AtomicBoolean isStarted = new AtomicBoolean(Boolean.FALSE); - private final ReentrantLock serverStateLock = new ReentrantLock(); - - private int ldapNonTlsPort = -1; - private int ldapTlsPort = -1; - - - public LdapServer(CertificateData trustAnchor, CertificateData ldapCertificate) { - this.trustAnchor = trustAnchor; - this.ldapCertificate = ldapCertificate; - } - - public boolean isStarted() { - return this.isStarted.get(); - } - - public int getLdapNonTlsPort() { - return ldapNonTlsPort; - } - - public int getLdapsTlsPort() { - return ldapTlsPort; - } - - public void start(LdifData ldifData) throws Exception { - Objects.requireNonNull(ldifData, "Ldif data is required"); - boolean hasLock = false; - try { - hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); - if (hasLock) { - doStart(ldifData); - this.isStarted.set(Boolean.TRUE); - } else { - throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); - } - } catch (InterruptedException ioe) { - //lock interrupted - log.error("LDAP server start lock interrupted", ioe); - throw ioe; - } finally { - if (hasLock) { - serverStateLock.unlock(); - } - } - } - - private void doStart(LdifData ldifData) throws Exception { - if (isStarted.get()) { - throw new IllegalStateException(LdapServer.SERVER_ALREADY_STARTED); - } - configureAndStartServer(ldifData); - } - - private Collection getInMemoryListenerConfigs() throws Exception { - KeyStore keyStore = createEmptyKeyStore(); - addLdapCertificatesToKeystore(keyStore); - final SSLUtil sslUtil = new SSLUtil(createKeyManager(keyStore), createTrustManagers(keyStore)); - - ldapNonTlsPort = SocketUtils.findAvailableTcpPort(); - ldapTlsPort = SocketUtils.findAvailableTcpPort(); - - Collection listenerConfigs = new ArrayList<>(); - listenerConfigs.add(InMemoryListenerConfig.createLDAPConfig("ldap", null, ldapNonTlsPort, sslUtil.createSSLSocketFactory())); - listenerConfigs.add(InMemoryListenerConfig.createLDAPSConfig("ldaps", ldapTlsPort, sslUtil.createSSLServerSocketFactory())); - return listenerConfigs; - } - - private static KeyManager[] createKeyManager(KeyStore keyStore) - throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException { - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(keyStore, null); - return keyManagerFactory.getKeyManagers(); - } - - private static TrustManager[] createTrustManagers(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException { - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(keyStore); - return trustManagerFactory.getTrustManagers(); - } - - private void addLdapCertificatesToKeystore(KeyStore keyStore) throws KeyStoreException { - keyStore.setCertificateEntry("trustAnchor", trustAnchor.certificate()); - keyStore.setKeyEntry("ldap-key", ldapCertificate.getKey(), null, new Certificate[]{ ldapCertificate.certificate()}); - } - - private static KeyStore createEmptyKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null); - return keyStore; - } - - private synchronized void configureAndStartServer(LdifData ldifData) throws Exception { - Collection listenerConfigs = getInMemoryListenerConfigs(); - - Schema schema = Schema.getDefaultStandardSchema(); - - final String rootObjectDN = ldifData.getRootDistinguishedName(); - InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(new DN(rootObjectDN)); - - config.setSchema(schema); //schema can be set on the rootDN too, per javadoc. - config.setListenerConfigs(listenerConfigs); - config.setEnforceAttributeSyntaxCompliance(false); - config.setEnforceSingleStructuralObjectClass(false); - - server = new InMemoryDirectoryServer(config); - - try { - /* Clear entries from server. */ - server.clear(); - server.startListening(); - loadLdifData(ldifData); - } catch (LDAPException ldape) { - if (ldape.getMessage().contains("java.net.BindException")) { - throw new BindException(ldape.getMessage()); - } - throw ldape; - } - - } - - public void stop() throws InterruptedException { - boolean hasLock = false; - try { - hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); - if (hasLock) { - if (!isStarted.get()) { - throw new IllegalStateException(LdapServer.SERVER_NOT_STARTED); - } - log.info("Shutting down in-Memory Ldap Server."); - server.shutDown(true); - } else { - throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); - } - } catch (InterruptedException ioe) { - //lock interrupted - log.error("Canot stop LDAP server due to interruption", ioe); - throw ioe; - } finally { - if (hasLock) { - serverStateLock.unlock(); - } - } - } - - private void loadLdifData(LdifData ldifData) throws Exception { - try (LDIFReader r = new LDIFReader(new BufferedReader(new StringReader(ldifData.getContent())))){ - Entry entry; - while ((entry = r.readEntry()) != null) { - server.add(entry); - } - } catch(Exception e) { - log.error("Cannot load data into LDAP server", e); - throw e; - } - } + private static final Logger log = LogManager.getLogger(LdapServer.class); + + private static final int LOCK_TIMEOUT = 60; + private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; + + private static final String LOCK_TIMEOUT_MSG = "Unable to obtain lock due to timeout after " + + LOCK_TIMEOUT + + " " + + TIME_UNIT.toString(); + private static final String SERVER_NOT_STARTED = "The LDAP server is not started."; + private static final String SERVER_ALREADY_STARTED = "The LDAP server is already started."; + + private final CertificateData trustAnchor; + + private final CertificateData ldapCertificate; + + private InMemoryDirectoryServer server; + private final AtomicBoolean isStarted = new AtomicBoolean(Boolean.FALSE); + private final ReentrantLock serverStateLock = new ReentrantLock(); + + private int ldapNonTlsPort = -1; + private int ldapTlsPort = -1; + + public LdapServer(CertificateData trustAnchor, CertificateData ldapCertificate) { + this.trustAnchor = trustAnchor; + this.ldapCertificate = ldapCertificate; + } + + public boolean isStarted() { + return this.isStarted.get(); + } + + public int getLdapNonTlsPort() { + return ldapNonTlsPort; + } + + public int getLdapsTlsPort() { + return ldapTlsPort; + } + + public void start(LdifData ldifData) throws Exception { + Objects.requireNonNull(ldifData, "Ldif data is required"); + boolean hasLock = false; + try { + hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); + if (hasLock) { + doStart(ldifData); + this.isStarted.set(Boolean.TRUE); + } else { + throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); + } + } catch (InterruptedException ioe) { + // lock interrupted + log.error("LDAP server start lock interrupted", ioe); + throw ioe; + } finally { + if (hasLock) { + serverStateLock.unlock(); + } + } + } + + private void doStart(LdifData ldifData) throws Exception { + if (isStarted.get()) { + throw new IllegalStateException(LdapServer.SERVER_ALREADY_STARTED); + } + configureAndStartServer(ldifData); + } + + private Collection getInMemoryListenerConfigs() throws Exception { + KeyStore keyStore = createEmptyKeyStore(); + addLdapCertificatesToKeystore(keyStore); + final SSLUtil sslUtil = new SSLUtil(createKeyManager(keyStore), createTrustManagers(keyStore)); + + ldapNonTlsPort = SocketUtils.findAvailableTcpPort(); + ldapTlsPort = SocketUtils.findAvailableTcpPort(); + + Collection listenerConfigs = new ArrayList<>(); + listenerConfigs.add(InMemoryListenerConfig.createLDAPConfig("ldap", null, ldapNonTlsPort, sslUtil.createSSLSocketFactory())); + listenerConfigs.add(InMemoryListenerConfig.createLDAPSConfig("ldaps", ldapTlsPort, sslUtil.createSSLServerSocketFactory())); + return listenerConfigs; + } + + private static KeyManager[] createKeyManager(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException, + UnrecoverableKeyException { + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, null); + return keyManagerFactory.getKeyManagers(); + } + + private static TrustManager[] createTrustManagers(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(keyStore); + return trustManagerFactory.getTrustManagers(); + } + + private void addLdapCertificatesToKeystore(KeyStore keyStore) throws KeyStoreException { + keyStore.setCertificateEntry("trustAnchor", trustAnchor.certificate()); + keyStore.setKeyEntry("ldap-key", ldapCertificate.getKey(), null, new Certificate[] { ldapCertificate.certificate() }); + } + + private static KeyStore createEmptyKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null); + return keyStore; + } + + private synchronized void configureAndStartServer(LdifData ldifData) throws Exception { + Collection listenerConfigs = getInMemoryListenerConfigs(); + + Schema schema = Schema.getDefaultStandardSchema(); + + final String rootObjectDN = ldifData.getRootDistinguishedName(); + InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(new DN(rootObjectDN)); + + config.setSchema(schema); // schema can be set on the rootDN too, per javadoc. + config.setListenerConfigs(listenerConfigs); + config.setEnforceAttributeSyntaxCompliance(false); + config.setEnforceSingleStructuralObjectClass(false); + + server = new InMemoryDirectoryServer(config); + + try { + /* Clear entries from server. */ + server.clear(); + server.startListening(); + loadLdifData(ldifData); + } catch (LDAPException ldape) { + if (ldape.getMessage().contains("java.net.BindException")) { + throw new BindException(ldape.getMessage()); + } + throw ldape; + } + + } + + public void stop() throws InterruptedException { + boolean hasLock = false; + try { + hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); + if (hasLock) { + if (!isStarted.get()) { + throw new IllegalStateException(LdapServer.SERVER_NOT_STARTED); + } + log.info("Shutting down in-Memory Ldap Server."); + server.shutDown(true); + } else { + throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); + } + } catch (InterruptedException ioe) { + // lock interrupted + log.error("Canot stop LDAP server due to interruption", ioe); + throw ioe; + } finally { + if (hasLock) { + serverStateLock.unlock(); + } + } + } + + private void loadLdifData(LdifData ldifData) throws Exception { + try (LDIFReader r = new LDIFReader(new BufferedReader(new StringReader(ldifData.getContent())))) { + Entry entry; + while ((entry = r.readEntry()) != null) { + server.add(entry); + } + } catch (Exception e) { + log.error("Cannot load data into LDAP server", e); + throw e; + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java index cea53a92f3..87f01a2bbc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java @@ -19,50 +19,48 @@ public class LdifBuilder { - private static final Logger log = LogManager.getLogger(LdifBuilder.class); + private static final Logger log = LogManager.getLogger(LdifBuilder.class); - private final List records; + private final List records; - private Record root; + private Record root; - public LdifBuilder() { - this.records = new ArrayList<>(); - } + public LdifBuilder() { + this.records = new ArrayList<>(); + } - public RecordBuilder root(String distinguishedName) { - if(root != null) { - throw new IllegalStateException("Root object is already defined"); - } - return new RecordBuilder(this, distinguishedName); - } + public RecordBuilder root(String distinguishedName) { + if (root != null) { + throw new IllegalStateException("Root object is already defined"); + } + return new RecordBuilder(this, distinguishedName); + } - RecordBuilder newRecord(String distinguishedName) { - if(root == null) { - throw new IllegalStateException("Define root object first"); - } - return new RecordBuilder(this, distinguishedName); - } + RecordBuilder newRecord(String distinguishedName) { + if (root == null) { + throw new IllegalStateException("Define root object first"); + } + return new RecordBuilder(this, distinguishedName); + } - void addRecord(Record record) { - Objects.requireNonNull(record, "Cannot add null record"); - if(records.isEmpty()) { - this.root = record; - } - records.add(Objects.requireNonNull(record, "Cannot add null record")); - } + void addRecord(Record record) { + Objects.requireNonNull(record, "Cannot add null record"); + if (records.isEmpty()) { + this.root = record; + } + records.add(Objects.requireNonNull(record, "Cannot add null record")); + } - public LdifData buildLdif() { - String ldif = records.stream() - .map(record -> record.toLdifRepresentation()) - .collect(Collectors.joining("\n##########\n")); - log.debug("Built ldif file: \n{}", ldif); - return new LdifData(getRootDistinguishedName(), ldif); - } + public LdifData buildLdif() { + String ldif = records.stream().map(record -> record.toLdifRepresentation()).collect(Collectors.joining("\n##########\n")); + log.debug("Built ldif file: \n{}", ldif); + return new LdifData(getRootDistinguishedName(), ldif); + } - private String getRootDistinguishedName() { - if(root == null) { - throw new IllegalStateException("Root object is not present."); - } - return root.getDistinguishedName(); - } + private String getRootDistinguishedName() { + if (root == null) { + throw new IllegalStateException("Root object is not present."); + } + return root.getDistinguishedName(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java index a0f2026b73..4a1af5bc08 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java @@ -11,39 +11,38 @@ import org.apache.commons.lang3.StringUtils; - /** * Value object which represents LDIF file data and some metadata. Ensure type safety. */ public class LdifData { - - private final String rootDistinguishedName; - private final String content; + private final String rootDistinguishedName; + + private final String content; - LdifData(String rootDistinguishedName, String content) { - this.rootDistinguishedName = requireNotBlank(rootDistinguishedName, "Root distinguished name is required"); - this.content = requireNotBlank(content, "Ldif file content is required"); + LdifData(String rootDistinguishedName, String content) { + this.rootDistinguishedName = requireNotBlank(rootDistinguishedName, "Root distinguished name is required"); + this.content = requireNotBlank(content, "Ldif file content is required"); - } + } - private static String requireNotBlank(String string, String message) { - if(StringUtils.isBlank(string)) { - throw new IllegalArgumentException(message); - } - return string; - } + private static String requireNotBlank(String string, String message) { + if (StringUtils.isBlank(string)) { + throw new IllegalArgumentException(message); + } + return string; + } - String getContent() { - return content; - } + String getContent() { + return content; + } - String getRootDistinguishedName() { - return rootDistinguishedName; - } + String getRootDistinguishedName() { + return rootDistinguishedName; + } - @Override - public String toString() { - return "LdifData{" + "content='" + content + '\'' + '}'; - } + @Override + public String toString() { + return "LdifData{" + "content='" + content + '\'' + '}'; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java index 76eea1771d..48e7484777 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java @@ -18,51 +18,50 @@ class Record { - private final String distinguishedName; + private final String distinguishedName; - private final List classes; - private final List> attributes; + private final List classes; + private final List> attributes; - public Record(String distinguishedName) { - this.distinguishedName = Objects.requireNonNull(distinguishedName, "Distinguished name is required"); - this.classes = new ArrayList<>(); - this.attributes = new ArrayList<>(); - } + public Record(String distinguishedName) { + this.distinguishedName = Objects.requireNonNull(distinguishedName, "Distinguished name is required"); + this.classes = new ArrayList<>(); + this.attributes = new ArrayList<>(); + } - public String getDistinguishedName() { - return distinguishedName; - } + public String getDistinguishedName() { + return distinguishedName; + } - public void addClass(String clazz) { - classes.add(Objects.requireNonNull(clazz, "Object class is required.")); - } + public void addClass(String clazz) { + classes.add(Objects.requireNonNull(clazz, "Object class is required.")); + } - public void addAttribute(String name, String value) { - Objects.requireNonNull(name, "Attribute name is required"); - Objects.requireNonNull(value, "Attribute value is required"); - attributes.add(Pair.of(name, value)); - } + public void addAttribute(String name, String value) { + Objects.requireNonNull(name, "Attribute name is required"); + Objects.requireNonNull(value, "Attribute value is required"); + attributes.add(Pair.of(name, value)); + } - boolean isValid() { - return classes.size() > 0; - } + boolean isValid() { + return classes.size() > 0; + } - String toLdifRepresentation() { - return new StringBuilder("dn: ").append(distinguishedName).append("\n") - .append(formattedClasses()).append("\n") - .append(formattedAttributes()).append("\n") - .toString(); - } + String toLdifRepresentation() { + return new StringBuilder("dn: ").append(distinguishedName) + .append("\n") + .append(formattedClasses()) + .append("\n") + .append(formattedAttributes()) + .append("\n") + .toString(); + } - private String formattedAttributes() { - return attributes.stream() - .map(pair -> pair.getKey() + ": " + pair.getValue()) - .collect(Collectors.joining("\n")); - } + private String formattedAttributes() { + return attributes.stream().map(pair -> pair.getKey() + ": " + pair.getValue()).collect(Collectors.joining("\n")); + } - private String formattedClasses() { - return classes.stream() - .map(clazz -> "objectClass: " + clazz) - .collect(Collectors.joining("\n")); - } + private String formattedClasses() { + return classes.stream().map(clazz -> "objectClass: " + clazz).collect(Collectors.joining("\n")); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java index a54caef2af..1df27c72fe 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java @@ -13,80 +13,80 @@ public class RecordBuilder { - private final LdifBuilder builder; - private final Record record; - - RecordBuilder(LdifBuilder builder, String distinguishedName) { - this.builder = Objects.requireNonNull(builder, "LdifBuilder is required"); - this.record = new Record(distinguishedName); - } - - public RecordBuilder classes(String...classes) { - for(String clazz : classes) { - this.record.addClass(clazz); - } - return this; - } - - public RecordBuilder dn(String distinguishedName) { - record.addAttribute("dn", distinguishedName); - return this; - } - - public RecordBuilder dc(String domainComponent) { - record.addAttribute("dc", domainComponent); - return this; - } - - public RecordBuilder ou(String organizationUnit) { - record.addAttribute("ou", organizationUnit); - return this; - } - - public RecordBuilder cn(String commonName) { - record.addAttribute("cn", commonName); - return this; - } - - public RecordBuilder sn(String surname) { - record.addAttribute("sn", surname); - return this; - } - - public RecordBuilder uid(String userId) { - record.addAttribute("uid", userId); - return this; - } - - public RecordBuilder userPassword(String password) { - record.addAttribute("userpassword", password); - return this; - } - - public RecordBuilder mail(String emailAddress) { - record.addAttribute("mail", emailAddress); - return this; - } - - public RecordBuilder uniqueMember(String userDistinguishedName) { - record.addAttribute("uniquemember", userDistinguishedName); - return this; - } - - public RecordBuilder attribute(String name, String value) { - record.addAttribute(name, value); - return this; - } - - public LdifBuilder buildRecord() { - if(record.isValid() == false) { - throw new IllegalStateException("Record is invalid"); - } - builder.addRecord(record); - return builder; - } - - public RecordBuilder newRecord(String distinguishedName) { - return buildRecord().newRecord(distinguishedName); - } + private final LdifBuilder builder; + private final Record record; + + RecordBuilder(LdifBuilder builder, String distinguishedName) { + this.builder = Objects.requireNonNull(builder, "LdifBuilder is required"); + this.record = new Record(distinguishedName); + } + + public RecordBuilder classes(String... classes) { + for (String clazz : classes) { + this.record.addClass(clazz); + } + return this; + } + + public RecordBuilder dn(String distinguishedName) { + record.addAttribute("dn", distinguishedName); + return this; + } + + public RecordBuilder dc(String domainComponent) { + record.addAttribute("dc", domainComponent); + return this; + } + + public RecordBuilder ou(String organizationUnit) { + record.addAttribute("ou", organizationUnit); + return this; + } + + public RecordBuilder cn(String commonName) { + record.addAttribute("cn", commonName); + return this; + } + + public RecordBuilder sn(String surname) { + record.addAttribute("sn", surname); + return this; + } + + public RecordBuilder uid(String userId) { + record.addAttribute("uid", userId); + return this; + } + + public RecordBuilder userPassword(String password) { + record.addAttribute("userpassword", password); + return this; + } + + public RecordBuilder mail(String emailAddress) { + record.addAttribute("mail", emailAddress); + return this; + } + + public RecordBuilder uniqueMember(String userDistinguishedName) { + record.addAttribute("uniquemember", userDistinguishedName); + return this; + } + + public RecordBuilder attribute(String name, String value) { + record.addAttribute(name, value); + return this; + } + + public LdifBuilder buildRecord() { + if (record.isValid() == false) { + throw new IllegalStateException("Record is invalid"); + } + builder.addRecord(record); + return builder; + } + + public RecordBuilder newRecord(String distinguishedName) { + return buildRecord().newRecord(distinguishedName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java b/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java index e0baec9cb2..63765dfd14 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java +++ b/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java @@ -47,84 +47,89 @@ @Plugin(name = PLUGIN_NAME, category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) public class LogCapturingAppender extends AbstractAppender { - public final static String PLUGIN_NAME = "LogCapturingAppender"; - /** - * Appender stores only last MAX_SIZE messages to avoid excessive RAM memory usage. - */ - public static final int MAX_SIZE = 100; + public final static String PLUGIN_NAME = "LogCapturingAppender"; + /** + * Appender stores only last MAX_SIZE messages to avoid excessive RAM memory usage. + */ + public static final int MAX_SIZE = 100; - /** - * Buffer for captured log messages - */ - private static final Buffer messages = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(MAX_SIZE)); + /** + * Buffer for captured log messages + */ + private static final Buffer messages = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(MAX_SIZE)); - /** - * Log messages are stored in buffer {@link #messages} only for classes which are added to the {@link #activeLoggers} set. - */ - private static final Set activeLoggers = Collections.synchronizedSet(new HashSet<>()); + /** + * Log messages are stored in buffer {@link #messages} only for classes which are added to the {@link #activeLoggers} set. + */ + private static final Set activeLoggers = Collections.synchronizedSet(new HashSet<>()); - protected LogCapturingAppender(String name, Filter filter, Layout layout, boolean ignoreExceptions, Property[] properties) { - super(name, filter, layout, ignoreExceptions, properties); - } + protected LogCapturingAppender( + String name, + Filter filter, + Layout layout, + boolean ignoreExceptions, + Property[] properties + ) { + super(name, filter, layout, ignoreExceptions, properties); + } - /** - * Method used by Log4j2 to create appender - * @param name appender name from Log4j2 configuration - * @return newly created appender - */ - @PluginFactory - public static LogCapturingAppender createAppender(@PluginAttribute(value = "name", defaultString = "logCapturingAppender") String name) { - return new LogCapturingAppender(name, null, null, true, Property.EMPTY_ARRAY); - } + /** + * Method used by Log4j2 to create appender + * @param name appender name from Log4j2 configuration + * @return newly created appender + */ + @PluginFactory + public static LogCapturingAppender createAppender( + @PluginAttribute(value = "name", defaultString = "logCapturingAppender") String name + ) { + return new LogCapturingAppender(name, null, null, true, Property.EMPTY_ARRAY); + } - /** - * Method invoked by Log4j2 to append log events - * @param event The LogEvent, represents log message. - */ - @Override - public void append(LogEvent event) { - String loggerName = event.getLoggerName(); - boolean loggable = activeLoggers.contains(loggerName); - if(loggable) { - event.getThrown(); - messages.add(new LogMessage(event.getMessage().getFormattedMessage(), event.getThrown())); - } - } + /** + * Method invoked by Log4j2 to append log events + * @param event The LogEvent, represents log message. + */ + @Override + public void append(LogEvent event) { + String loggerName = event.getLoggerName(); + boolean loggable = activeLoggers.contains(loggerName); + if (loggable) { + event.getThrown(); + messages.add(new LogMessage(event.getMessage().getFormattedMessage(), event.getThrown())); + } + } - /** - * To collect log messages form given logger the logger name must be passed to {@link #enable(String...)} method. - * @param loggerNames logger names - */ - public static void enable(String...loggerNames) { - disable(); - activeLoggers.addAll(Arrays.asList(loggerNames)); - } + /** + * To collect log messages form given logger the logger name must be passed to {@link #enable(String...)} method. + * @param loggerNames logger names + */ + public static void enable(String... loggerNames) { + disable(); + activeLoggers.addAll(Arrays.asList(loggerNames)); + } - /** - * Invocation cause that appender stops collecting log messages. Additionally, memory used by collected messages so far is released. - */ - public static void disable() { - activeLoggers.clear(); - messages.clear(); - } + /** + * Invocation cause that appender stops collecting log messages. Additionally, memory used by collected messages so far is released. + */ + public static void disable() { + activeLoggers.clear(); + messages.clear(); + } - /** - * Is used to obtain gathered log messages - * @return Log messages - */ - public static List getLogMessages() { - return new ArrayList<>(messages); - } + /** + * Is used to obtain gathered log messages + * @return Log messages + */ + public static List getLogMessages() { + return new ArrayList<>(messages); + } - public static List getLogMessagesAsString() { - return getLogMessages() - .stream() - .map(LogMessage::getMessage) - .collect(Collectors.toList()); - } + public static List getLogMessagesAsString() { + return getLogMessages().stream().map(LogMessage::getMessage).collect(Collectors.toList()); + } - @Override - public String toString() { - return "LogCapturingAppender{}"; - } + @Override + public String toString() { + return "LogCapturingAppender{}"; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java b/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java index 327e91c759..9342c7ee30 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java +++ b/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java @@ -16,25 +16,25 @@ class LogMessage { - private final String message; - private final String stackTrace; - - public LogMessage(String message, Throwable throwable) { - this.message = message; - this.stackTrace = Optional.ofNullable(throwable).map(ExceptionUtils::getStackTrace).orElse(""); - } - - public boolean containMessage(String expectedMessage) { - Objects.requireNonNull(expectedMessage, "Expected message must not be null."); - return expectedMessage.equals(message); - } - - public boolean stackTraceContains(String stackTraceFragment) { - Objects.requireNonNull(stackTraceFragment, "Stack trace fragment is required."); - return stackTrace.contains(stackTraceFragment); - } - - public String getMessage() { - return message; - } + private final String message; + private final String stackTrace; + + public LogMessage(String message, Throwable throwable) { + this.message = message; + this.stackTrace = Optional.ofNullable(throwable).map(ExceptionUtils::getStackTrace).orElse(""); + } + + public boolean containMessage(String expectedMessage) { + Objects.requireNonNull(expectedMessage, "Expected message must not be null."); + return expectedMessage.equals(message); + } + + public boolean stackTraceContains(String stackTraceFragment) { + Objects.requireNonNull(stackTraceFragment, "Stack trace fragment is required."); + return stackTrace.contains(stackTraceFragment); + } + + public String getMessage() { + return message; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java b/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java index c2dfabf537..46fa252df4 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java +++ b/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java @@ -27,66 +27,67 @@ */ public class LogsRule extends ExternalResource { - private final String[] loggerNames; + private final String[] loggerNames; - /** - * Constructor used to start gathering log messages from certain loggers - * @param loggerNames Loggers names. Log messages are collected only if the log message is associated with the logger with a name which - * is present in loggerNames parameter. - */ - public LogsRule(String...loggerNames) { - this.loggerNames = Objects.requireNonNull(loggerNames, "Logger names are required"); - } + /** + * Constructor used to start gathering log messages from certain loggers + * @param loggerNames Loggers names. Log messages are collected only if the log message is associated with the logger with a name which + * is present in loggerNames parameter. + */ + public LogsRule(String... loggerNames) { + this.loggerNames = Objects.requireNonNull(loggerNames, "Logger names are required"); + } - @Override - protected void before() { - LogCapturingAppender.enable(loggerNames); - } + @Override + protected void before() { + LogCapturingAppender.enable(loggerNames); + } - @Override - protected void after() { - LogCapturingAppender.disable(); - } + @Override + protected void after() { + LogCapturingAppender.disable(); + } - /** - * Check if during the tests certain log message was logged - * @param expectedLogMessage expected log message - */ - public void assertThatContainExactly(String expectedLogMessage) { - List messages = LogCapturingAppender.getLogMessagesAsString(); - String reason = reasonMessage(expectedLogMessage, messages); - assertThat(reason, messages, hasItem(expectedLogMessage)); - } + /** + * Check if during the tests certain log message was logged + * @param expectedLogMessage expected log message + */ + public void assertThatContainExactly(String expectedLogMessage) { + List messages = LogCapturingAppender.getLogMessagesAsString(); + String reason = reasonMessage(expectedLogMessage, messages); + assertThat(reason, messages, hasItem(expectedLogMessage)); + } - /** - * Check if during the tests certain log message was logged - * @param messageFragment expected log message fragment - */ - public void assertThatContain(String messageFragment) { - List messages = LogCapturingAppender.getLogMessagesAsString();; - String reason = reasonMessage(messageFragment, messages); - assertThat(reason, messages, hasItem(containsString(messageFragment))); - } + /** + * Check if during the tests certain log message was logged + * @param messageFragment expected log message fragment + */ + public void assertThatContain(String messageFragment) { + List messages = LogCapturingAppender.getLogMessagesAsString(); + ; + String reason = reasonMessage(messageFragment, messages); + assertThat(reason, messages, hasItem(containsString(messageFragment))); + } - /** - * Check if during the tests a stack trace was logged which contain given fragment - * @param stackTraceFragment stack trace fragment - */ - public void assertThatStackTraceContain(String stackTraceFragment) { - long count = LogCapturingAppender.getLogMessages() - .stream() - .filter(logMessage -> logMessage.stackTraceContains(stackTraceFragment)) - .count(); - String reason = "Stack trace does not contain element " + stackTraceFragment; - assertThat(reason, count, greaterThan(0L)); - } + /** + * Check if during the tests a stack trace was logged which contain given fragment + * @param stackTraceFragment stack trace fragment + */ + public void assertThatStackTraceContain(String stackTraceFragment) { + long count = LogCapturingAppender.getLogMessages() + .stream() + .filter(logMessage -> logMessage.stackTraceContains(stackTraceFragment)) + .count(); + String reason = "Stack trace does not contain element " + stackTraceFragment; + assertThat(reason, count, greaterThan(0L)); + } - private static String reasonMessage(String expectedLogMessage, List messages) { - String concatenatedLogMessages = messages.stream() - .map(message -> String.format("'%s'", message)) - .collect(Collectors.joining(", ")); - return String.format("Expected message '%s' has not been found in logs. All captured log messages: %s", - expectedLogMessage, - concatenatedLogMessages); - } + private static String reasonMessage(String expectedLogMessage, List messages) { + String concatenatedLogMessages = messages.stream().map(message -> String.format("'%s'", message)).collect(Collectors.joining(", ")); + return String.format( + "Expected message '%s' has not been found in logs. All captured log messages: %s", + expectedLogMessage, + concatenatedLogMessages + ); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java index 4d8c81b037..42723168ff 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java @@ -31,37 +31,36 @@ class AliasExistsMatcher extends TypeSafeDiagnosingMatcher { - private final String aliasName; + private final String aliasName; - public AliasExistsMatcher(String aliasName) { - this.aliasName = requireNonNull(aliasName, "Alias name is required"); - } + public AliasExistsMatcher(String aliasName) { + this.aliasName = requireNonNull(aliasName, "Alias name is required"); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetAliasesResponse response = client.admin().indices().getAliases(new GetAliasesRequest(aliasName)).get(); + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetAliasesResponse response = client.admin().indices().getAliases(new GetAliasesRequest(aliasName)).get(); - Map> aliases = response.getAliases(); - Set actualAliasNames = StreamSupport.stream(spliteratorUnknownSize(aliases.values().iterator(), IMMUTABLE), false) - .flatMap(Collection::stream) - .map(AliasMetadata::getAlias) - .collect(Collectors.toSet()); - if(actualAliasNames.contains(aliasName) == false) { - String existingAliases = String.join(", ", actualAliasNames); - mismatchDescription.appendText(" alias does not exist, defined aliases ").appendValue(existingAliases); - return false; - } - return true; - } catch (InterruptedException | ExecutionException e) { - mismatchDescription.appendText("Error occurred during checking if cluster contains alias ") - .appendValue(e); - return false; - } - } + Map> aliases = response.getAliases(); + Set actualAliasNames = StreamSupport.stream(spliteratorUnknownSize(aliases.values().iterator(), IMMUTABLE), false) + .flatMap(Collection::stream) + .map(AliasMetadata::getAlias) + .collect(Collectors.toSet()); + if (actualAliasNames.contains(aliasName) == false) { + String existingAliases = String.join(", ", actualAliasNames); + mismatchDescription.appendText(" alias does not exist, defined aliases ").appendValue(existingAliases); + return false; + } + return true; + } catch (InterruptedException | ExecutionException e) { + mismatchDescription.appendText("Error occurred during checking if cluster contains alias ").appendValue(e); + return false; + } + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster should contain ").appendValue(aliasName).appendText(" alias"); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster should contain ").appendValue(aliasName).appendText(" alias"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java index 922917bc21..ba7feed4c3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java @@ -18,27 +18,31 @@ class AtLeastCertainNumberOfAuditsFulfillPredicateMatcher extends AuditsFulfillPredicateMatcher { - private final long minimumNumberOfAudits; - - public AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(Predicate predicate, long minimumNumberOfAudits) { - super(predicate); - this.minimumNumberOfAudits = minimumNumberOfAudits; - } - - @Override - protected boolean matchesSafely(List audits, Description mismatchDescription) { - long count = countAuditsWhichMatchPredicate(audits); - if(count < minimumNumberOfAudits) { - mismatchDescription.appendText(" only ").appendValue(count).appendText(" match predicate. Examined audit logs ") - .appendText(auditMessagesToString(audits)); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Al least ").appendValue(minimumNumberOfAudits).appendText(" audits records should match predicate ") - .appendValue(predicate); - } + private final long minimumNumberOfAudits; + + public AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(Predicate predicate, long minimumNumberOfAudits) { + super(predicate); + this.minimumNumberOfAudits = minimumNumberOfAudits; + } + + @Override + protected boolean matchesSafely(List audits, Description mismatchDescription) { + long count = countAuditsWhichMatchPredicate(audits); + if (count < minimumNumberOfAudits) { + mismatchDescription.appendText(" only ") + .appendValue(count) + .appendText(" match predicate. Examined audit logs ") + .appendText(auditMessagesToString(audits)); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Al least ") + .appendValue(minimumNumberOfAudits) + .appendText(" audits records should match predicate ") + .appendValue(predicate); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java index f15750259f..080d4473e1 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java @@ -18,15 +18,21 @@ public class AuditMessageMatchers { - private AuditMessageMatchers() { - - } - - public static Matcher> exactNumberOfAuditsFulfillPredicate(long exactNumberOfAuditMessages, Predicate predicate) { - return new ExactNumberOfAuditsFulfillPredicateMatcher(exactNumberOfAuditMessages, predicate); - } - - public static Matcher> atLeastCertainNumberOfAuditsFulfillPredicate(long minimumNumberOfAudits, Predicate predicate) { - return new AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(predicate, minimumNumberOfAudits); - } + private AuditMessageMatchers() { + + } + + public static Matcher> exactNumberOfAuditsFulfillPredicate( + long exactNumberOfAuditMessages, + Predicate predicate + ) { + return new ExactNumberOfAuditsFulfillPredicateMatcher(exactNumberOfAuditMessages, predicate); + } + + public static Matcher> atLeastCertainNumberOfAuditsFulfillPredicate( + long minimumNumberOfAudits, + Predicate predicate + ) { + return new AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(predicate, minimumNumberOfAudits); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java index e73267b452..2864c1df81 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java @@ -19,18 +19,18 @@ abstract class AuditsFulfillPredicateMatcher extends TypeSafeDiagnosingMatcher> { - protected final Predicate predicate; + protected final Predicate predicate; - public AuditsFulfillPredicateMatcher(Predicate predicate) { - this.predicate = predicate; - } + public AuditsFulfillPredicateMatcher(Predicate predicate) { + this.predicate = predicate; + } - protected String auditMessagesToString(List audits) { - return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); - } + protected String auditMessagesToString(List audits) { + return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); + } - protected long countAuditsWhichMatchPredicate(List audits) { - return audits.stream().filter(predicate).count(); - } + protected long countAuditsWhichMatchPredicate(List audits) { + return audits.stream().filter(predicate).count(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java index d0b7e64673..2fb2cc5e74 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java @@ -20,51 +20,57 @@ class BulkResponseContainExceptionsAtIndexMatcher extends TypeSafeDiagnosingMatcher { - private final int errorIndex; - private final Matcher exceptionMatcher; + private final int errorIndex; + private final Matcher exceptionMatcher; - public BulkResponseContainExceptionsAtIndexMatcher(int errorIndex, Matcher exceptionMatcher) { - this.errorIndex = errorIndex; - this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); - } + public BulkResponseContainExceptionsAtIndexMatcher(int errorIndex, Matcher exceptionMatcher) { + this.errorIndex = errorIndex; + this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); + } - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - if(response.hasFailures() == false) { - mismatchDescription.appendText("received successful bulk response what is not expected."); - return false; - } - BulkItemResponse[] items = response.getItems(); - if((items == null) || (items.length == 0) || (errorIndex >= items.length)) { - mismatchDescription.appendText("bulk response does not contain item with index ").appendValue(errorIndex); - return false; - } - BulkItemResponse item = items[errorIndex]; - if(item == null) { - mismatchDescription.appendText("bulk item response with index ").appendValue(errorIndex).appendText(" is null."); - return false; - } - BulkItemResponse.Failure failure = item.getFailure(); - if(failure == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(errorIndex).appendText(" does not contain failure"); - return false; - } - Exception exception = failure.getCause(); - if(exception == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(errorIndex).appendText(" does not contain exception."); - return false; - } - if(exceptionMatcher.matches(exception) == false) { - mismatchDescription.appendText("bulk response item with index ").appendValue(errorIndex) - .appendText(" contains incorrect exception which is ").appendValue(exception); - return false; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + if (response.hasFailures() == false) { + mismatchDescription.appendText("received successful bulk response what is not expected."); + return false; + } + BulkItemResponse[] items = response.getItems(); + if ((items == null) || (items.length == 0) || (errorIndex >= items.length)) { + mismatchDescription.appendText("bulk response does not contain item with index ").appendValue(errorIndex); + return false; + } + BulkItemResponse item = items[errorIndex]; + if (item == null) { + mismatchDescription.appendText("bulk item response with index ").appendValue(errorIndex).appendText(" is null."); + return false; + } + BulkItemResponse.Failure failure = item.getFailure(); + if (failure == null) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(errorIndex) + .appendText(" does not contain failure"); + return false; + } + Exception exception = failure.getCause(); + if (exception == null) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(errorIndex) + .appendText(" does not contain exception."); + return false; + } + if (exceptionMatcher.matches(exception) == false) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(errorIndex) + .appendText(" contains incorrect exception which is ") + .appendValue(exception); + return false; + } - return true; - } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("bulk response should contain exceptions which indicate failure"); - } + @Override + public void describeTo(Description description) { + description.appendText("bulk response should contain exceptions which indicate failure"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java index 646a2aad93..b5e46ba9e2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java @@ -20,50 +20,52 @@ class BulkResponseContainExceptionsMatcher extends TypeSafeDiagnosingMatcher { - private final Matcher exceptionMatcher; + private final Matcher exceptionMatcher; - public BulkResponseContainExceptionsMatcher(Matcher exceptionMatcher) { - this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); - } + public BulkResponseContainExceptionsMatcher(Matcher exceptionMatcher) { + this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); + } - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - if(response.hasFailures() == false) { - mismatchDescription.appendText("received successful bulk response what is not expected."); - return false; - } - BulkItemResponse[] items = response.getItems(); - if((items == null) || (items.length == 0)) { - mismatchDescription.appendText("bulk response does not contain items ").appendValue(items); - return false; - } - for(int i = 0 ; i < items.length; ++i) { - BulkItemResponse item = items[i]; - if(item == null) { - mismatchDescription.appendText("bulk item response with index ").appendValue(i).appendText(" is null."); - return false; - } - BulkItemResponse.Failure failure = item.getFailure(); - if(failure == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain failure"); - return false; - } - Exception exception = failure.getCause(); - if(exception == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain exception."); - return false; - } - if(exceptionMatcher.matches(exception) == false) { - mismatchDescription.appendText("bulk response item with index ").appendValue(i) - .appendText(" contains incorrect exception which is ").appendValue(exception); - return false; - } - } - return true; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + if (response.hasFailures() == false) { + mismatchDescription.appendText("received successful bulk response what is not expected."); + return false; + } + BulkItemResponse[] items = response.getItems(); + if ((items == null) || (items.length == 0)) { + mismatchDescription.appendText("bulk response does not contain items ").appendValue(items); + return false; + } + for (int i = 0; i < items.length; ++i) { + BulkItemResponse item = items[i]; + if (item == null) { + mismatchDescription.appendText("bulk item response with index ").appendValue(i).appendText(" is null."); + return false; + } + BulkItemResponse.Failure failure = item.getFailure(); + if (failure == null) { + mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain failure"); + return false; + } + Exception exception = failure.getCause(); + if (exception == null) { + mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain exception."); + return false; + } + if (exceptionMatcher.matches(exception) == false) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(i) + .appendText(" contains incorrect exception which is ") + .appendValue(exception); + return false; + } + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("bulk response should contain exceptions which indicate failure"); - } + @Override + public void describeTo(Description description) { + description.appendText("bulk response should contain exceptions which indicate failure"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java index 4a72a67aba..eedcd3a3a0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java @@ -13,25 +13,25 @@ import org.opensearch.action.bulk.BulkResponse; -public class BulkResponseMatchers { +public class BulkResponseMatchers { - private BulkResponseMatchers(){ + private BulkResponseMatchers() { - } + } - public static Matcher successBulkResponse() { - return new SuccessBulkResponseMatcher(); - } + public static Matcher successBulkResponse() { + return new SuccessBulkResponseMatcher(); + } - public static Matcher failureBulkResponse() { - return new FailureBulkResponseMatcher(); - } + public static Matcher failureBulkResponse() { + return new FailureBulkResponseMatcher(); + } - public static Matcher bulkResponseContainExceptions(Matcher exceptionMatcher) { - return new BulkResponseContainExceptionsMatcher(exceptionMatcher); - } + public static Matcher bulkResponseContainExceptions(Matcher exceptionMatcher) { + return new BulkResponseContainExceptionsMatcher(exceptionMatcher); + } - public static Matcher bulkResponseContainExceptions(int index, Matcher exceptionMatcher) { - return new BulkResponseContainExceptionsAtIndexMatcher(index, exceptionMatcher); - } + public static Matcher bulkResponseContainExceptions(int index, Matcher exceptionMatcher) { + return new BulkResponseContainExceptionsAtIndexMatcher(index, exceptionMatcher); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java index a8e1b5d78d..91d2a28ef8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java @@ -20,24 +20,24 @@ class ClusterContainDocumentCountIndexMatcher extends TypeSafeDiagnosingMatcher { - private final String indexName; - private final int expectedDocumentCount; - - public ClusterContainDocumentCountIndexMatcher(String indexName, int expectedDocumentCount) { - this.indexName = requireNonNull(indexName, "Index name is required."); - this.expectedDocumentCount = expectedDocumentCount; - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - GetIndexResponse response = client.admin().indices().getIndex(null).actionGet(); - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("contains ").appendValue(expectedDocumentCount).appendText(" in index ").appendText(indexName); - } + private final String indexName; + private final int expectedDocumentCount; + + public ClusterContainDocumentCountIndexMatcher(String indexName, int expectedDocumentCount) { + this.indexName = requireNonNull(indexName, "Index name is required."); + this.expectedDocumentCount = expectedDocumentCount; + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + GetIndexResponse response = client.admin().indices().getIndex(null).actionGet(); + } + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("contains ").appendValue(expectedDocumentCount).appendText(" in index ").appendText(indexName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java index f710e2c1fa..362663e07b 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java @@ -24,43 +24,46 @@ class ClusterContainSuccessSnapshotMatcher extends TypeSafeDiagnosingMatcher { - private final String repositoryName; - private final String snapshotName; + private final String repositoryName; + private final String snapshotName; - public ClusterContainSuccessSnapshotMatcher(String repositoryName, String snapshotName) { - this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); - this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); - } + public ClusterContainSuccessSnapshotMatcher(String repositoryName, String snapshotName) { + this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); + this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); - GetSnapshotsResponse response = client.admin().cluster().getSnapshots(request).actionGet(); - long count = response.getSnapshots() - .stream() - .map(snapshot -> snapshot.state()) - .filter(status -> SnapshotState.SUCCESS.equals(status)) - .count(); - if(count != 1){ - String snapshotStatuses = response.getSnapshots() - .stream() - .map(info -> String.format("%s %s", info.snapshotId().getName(), info.state())) - .collect(Collectors.joining(", ")); - mismatchDescription.appendText("snapshot is not present or has incorrect state, snapshots statuses ") - .appendValue(snapshotStatuses); - return false; - } - }catch (SnapshotMissingException e) { - mismatchDescription.appendText(" snapshot does not exist"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); + GetSnapshotsResponse response = client.admin().cluster().getSnapshots(request).actionGet(); + long count = response.getSnapshots() + .stream() + .map(snapshot -> snapshot.state()) + .filter(status -> SnapshotState.SUCCESS.equals(status)) + .count(); + if (count != 1) { + String snapshotStatuses = response.getSnapshots() + .stream() + .map(info -> String.format("%s %s", info.snapshotId().getName(), info.state())) + .collect(Collectors.joining(", ")); + mismatchDescription.appendText("snapshot is not present or has incorrect state, snapshots statuses ") + .appendValue(snapshotStatuses); + return false; + } + } catch (SnapshotMissingException e) { + mismatchDescription.appendText(" snapshot does not exist"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain snapshot ").appendValue(snapshotName).appendText(" in repository ") - .appendValue(repositoryName).appendText(" with success status"); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain snapshot ") + .appendValue(snapshotName) + .appendText(" in repository ") + .appendValue(repositoryName) + .appendText(" with success status"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java index 2d64a95c65..119e3a6a2f 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java @@ -9,7 +9,6 @@ */ package org.opensearch.test.framework.matcher; - import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; @@ -20,25 +19,25 @@ class ClusterContainTemplateMatcher extends TypeSafeDiagnosingMatcher { - private final String templateName; + private final String templateName; - public ClusterContainTemplateMatcher(String templateName) { - this.templateName = requireNonNull(templateName, "Index template name is required."); + public ClusterContainTemplateMatcher(String templateName) { + this.templateName = requireNonNull(templateName, "Index template name is required."); - } + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); - if(response.getIndexTemplates().isEmpty()) { - mismatchDescription.appendText("But template does not exists"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); + if (response.getIndexTemplates().isEmpty()) { + mismatchDescription.appendText("But template does not exists"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("template ").appendValue(templateName).appendText(" exists"); - } + @Override + public void describeTo(Description description) { + description.appendText("template ").appendValue(templateName).appendText(" exists"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java index 861aaa72e7..4addaa0dd5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java @@ -27,48 +27,47 @@ class ClusterContainTemplateWithAliasMatcher extends TypeSafeDiagnosingMatcher { - private final String templateName; - private final String aliasName; + private final String templateName; + private final String aliasName; - public ClusterContainTemplateWithAliasMatcher(String templateName, String aliasName) { - this.templateName = requireNonNull(templateName, "Index template name is required."); - this.aliasName = requireNonNull(aliasName, "Alias name is required."); - } + public ClusterContainTemplateWithAliasMatcher(String templateName, String aliasName) { + this.templateName = requireNonNull(templateName, "Index template name is required."); + this.aliasName = requireNonNull(aliasName, "Alias name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); - if(response.getIndexTemplates().isEmpty()) { - mismatchDescription.appendText("but template does not exists"); - return false; - } - Set aliases = getAliases(response); - if(aliases.contains(aliasName) == false) { - mismatchDescription.appendText("alias ").appendValue(aliasName) - .appendText(" is not present in template, other aliases in template ") - .appendValue(aliases.stream().collect(Collectors.joining(", "))); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); + if (response.getIndexTemplates().isEmpty()) { + mismatchDescription.appendText("but template does not exists"); + return false; + } + Set aliases = getAliases(response); + if (aliases.contains(aliasName) == false) { + mismatchDescription.appendText("alias ") + .appendValue(aliasName) + .appendText(" is not present in template, other aliases in template ") + .appendValue(aliases.stream().collect(Collectors.joining(", "))); + return false; + } + return true; + } - private Set getAliases(GetIndexTemplatesResponse response) { - return response.getIndexTemplates() - .stream() - .map(metadata -> metadata.getAliases()) - .flatMap(aliasMap -> aliasNames(aliasMap)) - .collect(Collectors.toSet()); - } + private Set getAliases(GetIndexTemplatesResponse response) { + return response.getIndexTemplates() + .stream() + .map(metadata -> metadata.getAliases()) + .flatMap(aliasMap -> aliasNames(aliasMap)) + .collect(Collectors.toSet()); + } - private Stream aliasNames(Map aliasMap) { - Iterable> iterable = () -> aliasMap.entrySet().iterator(); - return StreamSupport.stream(iterable.spliterator(), false) - .map(entry -> entry.getValue().getAlias()); - } + private Stream aliasNames(Map aliasMap) { + Iterable> iterable = () -> aliasMap.entrySet().iterator(); + return StreamSupport.stream(iterable.spliterator(), false).map(entry -> entry.getValue().getAlias()); + } - - @Override - public void describeTo(Description description) { - description.appendText("template ").appendValue(templateName).appendText(" exists and "); - } + @Override + public void describeTo(Description description) { + description.appendText("template ").appendValue(templateName).appendText(" exists and "); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java index ffcceaa9cb..3153214213 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java @@ -24,35 +24,34 @@ class ClusterContainsDocumentMatcher extends TypeSafeDiagnosingMatcher { - private static final Logger log = LogManager.getLogger(ClusterContainsDocumentMatcher.class); - - private final String indexName; - private final String documentId; - - ClusterContainsDocumentMatcher(String indexName, String documentId) { - this.indexName = requireNonNull(indexName, "Index name is required."); - this.documentId = requireNonNull(documentId, "Document id is required."); - } - - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try{ - GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); - if(response.isExists() == false) { - mismatchDescription.appendText("Document does not exists"); - return false; - } - } catch (InterruptedException | ExecutionException e) { - log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); - mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain document in index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId); - } + private static final Logger log = LogManager.getLogger(ClusterContainsDocumentMatcher.class); + + private final String indexName; + private final String documentId; + + ClusterContainsDocumentMatcher(String indexName, String documentId) { + this.indexName = requireNonNull(indexName, "Index name is required."); + this.documentId = requireNonNull(documentId, "Document id is required."); + } + + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); + if (response.isExists() == false) { + mismatchDescription.appendText("Document does not exists"); + return false; + } + } catch (InterruptedException | ExecutionException e) { + log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); + mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain document in index ").appendValue(indexName).appendText(" with id ").appendValue(documentId); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java index df67a1669a..21f062fabf 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java @@ -25,56 +25,61 @@ class ClusterContainsDocumentWithFieldValueMatcher extends TypeSafeDiagnosingMatcher { - private static final Logger log = LogManager.getLogger(ClusterContainsDocumentWithFieldValueMatcher.class); + private static final Logger log = LogManager.getLogger(ClusterContainsDocumentWithFieldValueMatcher.class); - private final String indexName; - private final String documentId; + private final String indexName; + private final String documentId; - private final String fieldName; + private final String fieldName; - private final Object fieldValue; + private final Object fieldValue; - ClusterContainsDocumentWithFieldValueMatcher(String indexName, String documentId, String fieldName, Object fieldValue) { - this.indexName = requireNonNull(indexName, "Index name is required."); - this.documentId = requireNonNull(documentId, "Document id is required."); - this.fieldName = requireNonNull(fieldName, "Field name is required."); - this.fieldValue = requireNonNull(fieldValue, "Field value is required."); - } + ClusterContainsDocumentWithFieldValueMatcher(String indexName, String documentId, String fieldName, Object fieldValue) { + this.indexName = requireNonNull(indexName, "Index name is required."); + this.documentId = requireNonNull(documentId, "Document id is required."); + this.fieldName = requireNonNull(fieldName, "Field name is required."); + this.fieldValue = requireNonNull(fieldValue, "Field value is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); - if(response.isExists() == false) { - mismatchDescription.appendText("Document does not exists"); - return false; - } - Map source = response.getSource(); - if(source == null) { - mismatchDescription.appendText("Cannot retrieve document source"); - return false; - } - if(source.containsKey(fieldName) == false) { - mismatchDescription.appendText("document does not contain field ").appendValue(fieldName); - return false; - } - Object actualFieldValue = source.get(fieldName); - if(fieldValue.equals(actualFieldValue) == false) { - mismatchDescription.appendText(" document contain incorrect field value ").appendValue(actualFieldValue); - return false; - } - } catch (InterruptedException | ExecutionException e) { - log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); - mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); + if (response.isExists() == false) { + mismatchDescription.appendText("Document does not exists"); + return false; + } + Map source = response.getSource(); + if (source == null) { + mismatchDescription.appendText("Cannot retrieve document source"); + return false; + } + if (source.containsKey(fieldName) == false) { + mismatchDescription.appendText("document does not contain field ").appendValue(fieldName); + return false; + } + Object actualFieldValue = source.get(fieldName); + if (fieldValue.equals(actualFieldValue) == false) { + mismatchDescription.appendText(" document contain incorrect field value ").appendValue(actualFieldValue); + return false; + } + } catch (InterruptedException | ExecutionException e) { + log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); + mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain document in index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId).appendText(" with field ").appendValue(fieldName).appendText(" which is equal to ") - .appendValue(fieldValue); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain document in index ") + .appendValue(indexName) + .appendText(" with id ") + .appendValue(documentId) + .appendText(" with field ") + .appendValue(fieldName) + .appendText(" which is equal to ") + .appendValue(fieldValue); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java index 8b7dc777e4..fcff8bd6cf 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java @@ -26,41 +26,42 @@ class ClusterContainsSnapshotRepositoryMatcher extends TypeSafeDiagnosingMatcher { - private final String repositoryName; + private final String repositoryName; - public ClusterContainsSnapshotRepositoryMatcher(String repositoryName) { - this.repositoryName = requireNonNull(repositoryName, "Repository name is required."); - } + public ClusterContainsSnapshotRepositoryMatcher(String repositoryName) { + this.repositoryName = requireNonNull(repositoryName, "Repository name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - ClusterAdminClient adminClient = client.admin().cluster(); - GetRepositoriesRequest request = new GetRepositoriesRequest(new String[]{"*"}); - GetRepositoriesResponse response = adminClient.getRepositories(request).actionGet(); - if(response == null) { - mismatchDescription.appendText("Cannot check if cluster contain repository"); - return false; - } - Set actualRepositoryNames = response.repositories() - .stream() - .map(metadata -> metadata.name()) - .collect(Collectors.toSet()); - if(actualRepositoryNames.contains(repositoryName) == false) { - mismatchDescription.appendText("Cluster does not contain snapshot repository ").appendValue(repositoryName) - .appendText(", but the following repositories are defined in the cluster ") - .appendValue(actualRepositoryNames.stream().collect(joining(", "))); - return false; - } - } catch (RepositoryMissingException e) { - mismatchDescription.appendText(" cluster does not contain any repository."); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + ClusterAdminClient adminClient = client.admin().cluster(); + GetRepositoriesRequest request = new GetRepositoriesRequest(new String[] { "*" }); + GetRepositoriesResponse response = adminClient.getRepositories(request).actionGet(); + if (response == null) { + mismatchDescription.appendText("Cannot check if cluster contain repository"); + return false; + } + Set actualRepositoryNames = response.repositories() + .stream() + .map(metadata -> metadata.name()) + .collect(Collectors.toSet()); + if (actualRepositoryNames.contains(repositoryName) == false) { + mismatchDescription.appendText("Cluster does not contain snapshot repository ") + .appendValue(repositoryName) + .appendText(", but the following repositories are defined in the cluster ") + .appendValue(actualRepositoryNames.stream().collect(joining(", "))); + return false; + } + } catch (RepositoryMissingException e) { + mismatchDescription.appendText(" cluster does not contain any repository."); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain snapshot repository with name ").appendValue(repositoryName); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain snapshot repository with name ").appendValue(repositoryName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java index eff1f4c803..3829436d74 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java @@ -20,55 +20,60 @@ public class ClusterMatchers { - private ClusterMatchers() { - - } - - public static Matcher clusterContainsDocument(String indexName, String documentId) { - return new ClusterContainsDocumentMatcher(indexName, documentId); - } - - public static Matcher clusterContainsDocumentWithFieldValue(String indexName, String documentId, String fieldName, Object fieldValue) { - return new ClusterContainsDocumentWithFieldValueMatcher(indexName, documentId, fieldName, fieldValue); - } - - public static Matcher clusterContainTemplate(String templateName) { - return new ClusterContainTemplateMatcher(templateName); - } - - public static Matcher clusterContainTemplateWithAlias(String templateName, String aliasName) { - return new ClusterContainTemplateWithAliasMatcher(templateName, aliasName); - } - - public static Matcher clusterContainsSnapshotRepository(String repositoryName) { - return new ClusterContainsSnapshotRepositoryMatcher(repositoryName); - } - - public static Matcher clusterContainSuccessSnapshot(String repositoryName, String snapshotName) { - return new ClusterContainSuccessSnapshotMatcher(repositoryName, snapshotName); - } - - public static Matcher snapshotInClusterDoesNotExists(String repositoryName, String snapshotName) { - return new SnapshotInClusterDoesNotExist(repositoryName, snapshotName); - } - - public static Matcher aliasExists(String aliasName) { - return new AliasExistsMatcher(aliasName); - } - - public static Matcher indexExists(String expectedIndexName) { - return new IndexExistsMatcher(expectedIndexName); - } - - public static Matcher indexStateIsEqualTo(String expectedIndexName, IndexMetadata.State expectedState) { - return new IndexStateIsEqualToMatcher(expectedIndexName, expectedState); - } - - public static Matcher indexSettingsContainValues(String expectedIndexName, Settings expectedSettings) { - return new IndexSettingsContainValuesMatcher(expectedIndexName, expectedSettings); - } - - public static Matcher indexMappingIsEqualTo(String expectedIndexName, Map expectedMapping) { - return new IndexMappingIsEqualToMatcher(expectedIndexName, expectedMapping); - } + private ClusterMatchers() { + + } + + public static Matcher clusterContainsDocument(String indexName, String documentId) { + return new ClusterContainsDocumentMatcher(indexName, documentId); + } + + public static Matcher clusterContainsDocumentWithFieldValue( + String indexName, + String documentId, + String fieldName, + Object fieldValue + ) { + return new ClusterContainsDocumentWithFieldValueMatcher(indexName, documentId, fieldName, fieldValue); + } + + public static Matcher clusterContainTemplate(String templateName) { + return new ClusterContainTemplateMatcher(templateName); + } + + public static Matcher clusterContainTemplateWithAlias(String templateName, String aliasName) { + return new ClusterContainTemplateWithAliasMatcher(templateName, aliasName); + } + + public static Matcher clusterContainsSnapshotRepository(String repositoryName) { + return new ClusterContainsSnapshotRepositoryMatcher(repositoryName); + } + + public static Matcher clusterContainSuccessSnapshot(String repositoryName, String snapshotName) { + return new ClusterContainSuccessSnapshotMatcher(repositoryName, snapshotName); + } + + public static Matcher snapshotInClusterDoesNotExists(String repositoryName, String snapshotName) { + return new SnapshotInClusterDoesNotExist(repositoryName, snapshotName); + } + + public static Matcher aliasExists(String aliasName) { + return new AliasExistsMatcher(aliasName); + } + + public static Matcher indexExists(String expectedIndexName) { + return new IndexExistsMatcher(expectedIndexName); + } + + public static Matcher indexStateIsEqualTo(String expectedIndexName, IndexMetadata.State expectedState) { + return new IndexStateIsEqualToMatcher(expectedIndexName, expectedState); + } + + public static Matcher indexSettingsContainValues(String expectedIndexName, Settings expectedSettings) { + return new IndexSettingsContainValuesMatcher(expectedIndexName, expectedSettings); + } + + public static Matcher indexMappingIsEqualTo(String expectedIndexName, Map expectedMapping) { + return new IndexMappingIsEqualToMatcher(expectedIndexName, expectedMapping); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java index 094b26f33f..03b9b6bab8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java @@ -17,18 +17,18 @@ class ContainNotEmptyScrollingIdMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - String scrollId = searchResponse.getScrollId(); - if(StringUtils.isEmpty(scrollId)) { - mismatchDescription.appendText("scrolling id is null or empty"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + String scrollId = searchResponse.getScrollId(); + if (StringUtils.isEmpty(scrollId)) { + mismatchDescription.appendText("scrolling id is null or empty"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Search response should contain scrolling id."); - } + @Override + public void describeTo(Description description) { + description.appendText("Search response should contain scrolling id."); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java index 9f8fbd6dba..b1ef21c922 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java @@ -20,36 +20,38 @@ class ContainsAggregationWithNameAndTypeMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedAggregationName; - private final String expectedAggregationType; - - public ContainsAggregationWithNameAndTypeMatcher(String expectedAggregationName, String expectedAggregationType) { - this.expectedAggregationName = requireNonNull(expectedAggregationName, "Aggregation name is required"); - this.expectedAggregationType = requireNonNull(expectedAggregationType, "Expected aggregation type is required."); - } - - @Override - protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { - Aggregations aggregations = response.getAggregations(); - if(aggregations == null) { - mismatchDescription.appendText("search response does not contain aggregations"); - return false; - } - Aggregation aggregation = aggregations.get(expectedAggregationName); - if(aggregation == null) { - mismatchDescription.appendText("Response does not contain aggregation with name ").appendValue(expectedAggregationName); - return false; - } - if(expectedAggregationType.equals(aggregation.getType()) == false) { - mismatchDescription.appendText("Aggregation contain incorrect type which is ").appendValue(aggregation.getType()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Search response should contains aggregation results with name ").appendValue(expectedAggregationName) - .appendText(" and type ").appendValue(expectedAggregationType); - } + private final String expectedAggregationName; + private final String expectedAggregationType; + + public ContainsAggregationWithNameAndTypeMatcher(String expectedAggregationName, String expectedAggregationType) { + this.expectedAggregationName = requireNonNull(expectedAggregationName, "Aggregation name is required"); + this.expectedAggregationType = requireNonNull(expectedAggregationType, "Expected aggregation type is required."); + } + + @Override + protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { + Aggregations aggregations = response.getAggregations(); + if (aggregations == null) { + mismatchDescription.appendText("search response does not contain aggregations"); + return false; + } + Aggregation aggregation = aggregations.get(expectedAggregationName); + if (aggregation == null) { + mismatchDescription.appendText("Response does not contain aggregation with name ").appendValue(expectedAggregationName); + return false; + } + if (expectedAggregationType.equals(aggregation.getType()) == false) { + mismatchDescription.appendText("Aggregation contain incorrect type which is ").appendValue(aggregation.getType()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Search response should contains aggregation results with name ") + .appendValue(expectedAggregationName) + .appendText(" and type ") + .appendValue(expectedAggregationType); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java index 551a1823bf..9b597ad1c8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java @@ -20,27 +20,27 @@ class ContainsExactlyIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedIndices; - - ContainsExactlyIndicesMatcher(String... expectedIndices) { - if (isNull(expectedIndices) || expectedIndices.length == 0) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = Set.of(expectedIndices); - } - - @Override - protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { - Set actualIndices = Set.of(response.getIndices()); - if (!expectedIndices.equals(actualIndices)) { - mismatchDescription.appendText("Actual indices: ").appendValue(actualIndices); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response contains indices: ").appendValue(expectedIndices); - } + private final Set expectedIndices; + + ContainsExactlyIndicesMatcher(String... expectedIndices) { + if (isNull(expectedIndices) || expectedIndices.length == 0) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = Set.of(expectedIndices); + } + + @Override + protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { + Set actualIndices = Set.of(response.getIndices()); + if (!expectedIndices.equals(actualIndices)) { + mismatchDescription.appendText("Actual indices: ").appendValue(actualIndices); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response contains indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java index 41db8a9ed5..cd6b4b05cc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java @@ -21,31 +21,35 @@ class ContainsFieldWithTypeMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedFieldName; - private final String expectedFieldType; - - ContainsFieldWithTypeMatcher(String expectedFieldName, String expectedFieldType) { - this.expectedFieldName = requireNonNull(expectedFieldName, "Field name is required");; - this.expectedFieldType = requireNonNull(expectedFieldType, "Field type is required");; - } - - @Override - protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { - Map> fieldCapabilitiesMap = response.get(); - if (!fieldCapabilitiesMap.containsKey(expectedFieldName)) { - mismatchDescription.appendText("Response does not contain field with name ").appendText(expectedFieldName); - return false; - } - if (!fieldCapabilitiesMap.get(expectedFieldName).containsKey(expectedFieldType)) { - mismatchDescription.appendText("Field type does not match ").appendText(expectedFieldType); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response contains field with name ").appendValue(expectedFieldName) - .appendText(" and type ").appendValue(expectedFieldType); - } + private final String expectedFieldName; + private final String expectedFieldType; + + ContainsFieldWithTypeMatcher(String expectedFieldName, String expectedFieldType) { + this.expectedFieldName = requireNonNull(expectedFieldName, "Field name is required"); + ; + this.expectedFieldType = requireNonNull(expectedFieldType, "Field type is required"); + ; + } + + @Override + protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { + Map> fieldCapabilitiesMap = response.get(); + if (!fieldCapabilitiesMap.containsKey(expectedFieldName)) { + mismatchDescription.appendText("Response does not contain field with name ").appendText(expectedFieldName); + return false; + } + if (!fieldCapabilitiesMap.get(expectedFieldName).containsKey(expectedFieldType)) { + mismatchDescription.appendText("Field type does not match ").appendText(expectedFieldType); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response contains field with name ") + .appendValue(expectedFieldName) + .appendText(" and type ") + .appendValue(expectedFieldType); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java index fd921d0d72..788d023447 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java @@ -22,27 +22,27 @@ class DeletePitContainsExactlyIdsResponseMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedPitIds; - - DeletePitContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { - if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { - throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); - } - this.expectedPitIds = Set.of(expectedPitIds); - } - - @Override - protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { - Set actualPitIds = response.getDeletePitResults().stream().map(DeletePitInfo::getPitId).collect(Collectors.toSet()); - if (!actualPitIds.equals(expectedPitIds)) { - mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); - } + private final Set expectedPitIds; + + DeletePitContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { + if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { + throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); + } + this.expectedPitIds = Set.of(expectedPitIds); + } + + @Override + protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { + Set actualPitIds = response.getDeletePitResults().stream().map(DeletePitInfo::getPitId).collect(Collectors.toSet()); + if (!actualPitIds.equals(expectedPitIds)) { + mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java index 435c2521c8..4112d0bab8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java @@ -15,9 +15,9 @@ public class DeleteResponseMatchers { - private DeleteResponseMatchers() {} + private DeleteResponseMatchers() {} - public static Matcher isSuccessfulDeleteResponse() { - return new SuccessfulDeleteResponseMatcher(); - } + public static Matcher isSuccessfulDeleteResponse() { + return new SuccessfulDeleteResponseMatcher(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java index c7d918db2c..9bbe966e07 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java @@ -18,26 +18,28 @@ class ExactNumberOfAuditsFulfillPredicateMatcher extends AuditsFulfillPredicateMatcher { - private final long exactNumberOfAuditMessages; - - public ExactNumberOfAuditsFulfillPredicateMatcher(long exactNumberOfAuditMessages, Predicate predicate) { - super(predicate); - this.exactNumberOfAuditMessages = exactNumberOfAuditMessages; - } - - @Override - protected boolean matchesSafely(List audits, Description mismatchDescription) { - long count = countAuditsWhichMatchPredicate(audits); - if(exactNumberOfAuditMessages != count) { - mismatchDescription.appendText(" only ").appendValue(count).appendText(" match predicate. Examined audit logs ") - .appendText(auditMessagesToString(audits)); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendValue(exactNumberOfAuditMessages).appendText(" audit records should match predicate ").appendValue(predicate); - } + private final long exactNumberOfAuditMessages; + + public ExactNumberOfAuditsFulfillPredicateMatcher(long exactNumberOfAuditMessages, Predicate predicate) { + super(predicate); + this.exactNumberOfAuditMessages = exactNumberOfAuditMessages; + } + + @Override + protected boolean matchesSafely(List audits, Description mismatchDescription) { + long count = countAuditsWhichMatchPredicate(audits); + if (exactNumberOfAuditMessages != count) { + mismatchDescription.appendText(" only ") + .appendValue(count) + .appendText(" match predicate. Examined audit logs ") + .appendText(auditMessagesToString(audits)); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendValue(exactNumberOfAuditMessages).appendText(" audit records should match predicate ").appendValue(predicate); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java index e0e7b11be3..2e07bd0ec5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java @@ -17,25 +17,27 @@ class ExceptionErrorMessageMatcher extends TypeSafeDiagnosingMatcher { - private final Matcher errorMessageMatcher; - - public ExceptionErrorMessageMatcher(Matcher errorMessageMatcher) { - this.errorMessageMatcher = requireNonNull(errorMessageMatcher, "Error message matcher is required"); - } - - @Override - protected boolean matchesSafely(Throwable ex, Description mismatchDescription) { - boolean matches = errorMessageMatcher.matches(ex.getMessage()); - if(matches == false) { - mismatchDescription.appendText("Exception of class ").appendValue(ex.getClass().getCanonicalName()) - .appendText("contains unexpected error message which is ").appendValue(ex.getMessage()); - } - return matches; - - } - - @Override - public void describeTo(Description description) { - description.appendText("Error message in exception matches").appendValue(errorMessageMatcher); - } + private final Matcher errorMessageMatcher; + + public ExceptionErrorMessageMatcher(Matcher errorMessageMatcher) { + this.errorMessageMatcher = requireNonNull(errorMessageMatcher, "Error message matcher is required"); + } + + @Override + protected boolean matchesSafely(Throwable ex, Description mismatchDescription) { + boolean matches = errorMessageMatcher.matches(ex.getMessage()); + if (matches == false) { + mismatchDescription.appendText("Exception of class ") + .appendValue(ex.getClass().getCanonicalName()) + .appendText("contains unexpected error message which is ") + .appendValue(ex.getMessage()); + } + return matches; + + } + + @Override + public void describeTo(Description description) { + description.appendText("Error message in exception matches").appendValue(errorMessageMatcher); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java index 3a200d8849..ed1b203898 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java @@ -16,28 +16,28 @@ class ExceptionHasCauseMatcher extends TypeSafeDiagnosingMatcher { - private final Class expectedCauseType; + private final Class expectedCauseType; - public ExceptionHasCauseMatcher(Class expectedCauseType) { - this.expectedCauseType = Objects.requireNonNull(expectedCauseType, "Exception cause type is required"); - } + public ExceptionHasCauseMatcher(Class expectedCauseType) { + this.expectedCauseType = Objects.requireNonNull(expectedCauseType, "Exception cause type is required"); + } - @Override - protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { - Throwable cause = throwable.getCause(); - if(cause == null) { - mismatchDescription.appendText("exception cause is null"); - return false; - } - if(expectedCauseType.isInstance(cause) == false) { - mismatchDescription.appendText(" cause is instance of ").appendValue(cause.getClass()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { + Throwable cause = throwable.getCause(); + if (cause == null) { + mismatchDescription.appendText("exception cause is null"); + return false; + } + if (expectedCauseType.isInstance(cause) == false) { + mismatchDescription.appendText(" cause is instance of ").appendValue(cause.getClass()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Exception cause is instance of ").appendValue(expectedCauseType); - } + @Override + public void describeTo(Description description) { + description.appendText("Exception cause is instance of ").appendValue(expectedCauseType); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java index d46107b0fb..671f22b8e3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java @@ -17,24 +17,24 @@ public class ExceptionMatcherAssert { - @FunctionalInterface - public interface ThrowingCallable { - void call() throws Exception; - } + @FunctionalInterface + public interface ThrowingCallable { + void call() throws Exception; + } - public static void assertThatThrownBy(ThrowingCallable throwingCallable, Matcher matcher) { - Throwable expectedException = catchThrowable(throwingCallable); - assertThat("Expected exception was not thrown", expectedException, notNullValue()); - assertThat(expectedException, matcher); - } + public static void assertThatThrownBy(ThrowingCallable throwingCallable, Matcher matcher) { + Throwable expectedException = catchThrowable(throwingCallable); + assertThat("Expected exception was not thrown", expectedException, notNullValue()); + assertThat(expectedException, matcher); + } - public static Throwable catchThrowable(ThrowingCallable throwingCallable) { - Throwable expectedException = null; - try { - requireNonNull(throwingCallable, "ThrowingCallable must not be null.").call(); - } catch (Throwable e) { - expectedException = e; - } - return expectedException; - } + public static Throwable catchThrowable(ThrowingCallable throwingCallable) { + Throwable expectedException = null; + try { + requireNonNull(throwingCallable, "ThrowingCallable must not be null.").call(); + } catch (Throwable e) { + expectedException = e; + } + return expectedException; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java index a018c1c924..3d912e0283 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java @@ -16,17 +16,17 @@ class FailureBulkResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - if(response.hasFailures() == false) { - mismatchDescription.appendText(" bulk operation was executed correctly what is not expected."); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + if (response.hasFailures() == false) { + mismatchDescription.appendText(" bulk operation was executed correctly what is not expected."); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("bulk operation failure"); - } + @Override + public void describeTo(Description description) { + description.appendText("bulk operation failure"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java index c5680f6055..2a78c7b71c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java @@ -15,18 +15,18 @@ public class FieldCapabilitiesResponseMatchers { - private FieldCapabilitiesResponseMatchers() {} + private FieldCapabilitiesResponseMatchers() {} - public static Matcher containsExactlyIndices(String... expectedIndices) { - return new ContainsExactlyIndicesMatcher(expectedIndices); - } + public static Matcher containsExactlyIndices(String... expectedIndices) { + return new ContainsExactlyIndicesMatcher(expectedIndices); + } - public static Matcher containsFieldWithNameAndType(String expectedFieldName, String expectedFieldType) { - return new ContainsFieldWithTypeMatcher(expectedFieldName, expectedFieldType); - } + public static Matcher containsFieldWithNameAndType(String expectedFieldName, String expectedFieldType) { + return new ContainsFieldWithTypeMatcher(expectedFieldName, expectedFieldType); + } - public static Matcher numberOfFieldsIsEqualTo(int expectedNumberOfFields) { - return new NumberOfFieldsIsEqualToMatcher(expectedNumberOfFields); - } + public static Matcher numberOfFieldsIsEqualTo(int expectedNumberOfFields) { + return new NumberOfFieldsIsEqualToMatcher(expectedNumberOfFields); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java index 447224345c..c568bfa9d7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java @@ -22,27 +22,27 @@ class GetAllPitsContainsExactlyIdsResponseMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedPitIds; - - GetAllPitsContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { - if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { - throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); - } - this.expectedPitIds = Set.of(expectedPitIds); - } - - @Override - protected boolean matchesSafely(GetAllPitNodesResponse response, Description mismatchDescription) { - Set actualPitIds = response.getPitInfos().stream().map(ListPitInfo::getPitId).collect(Collectors.toSet()); - if (!actualPitIds.equals(expectedPitIds)) { - mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); - } + private final Set expectedPitIds; + + GetAllPitsContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { + if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { + throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); + } + this.expectedPitIds = Set.of(expectedPitIds); + } + + @Override + protected boolean matchesSafely(GetAllPitNodesResponse response, Description mismatchDescription) { + Set actualPitIds = response.getPitInfos().stream().map(ListPitInfo::getPitId).collect(Collectors.toSet()); + if (!actualPitIds.equals(expectedPitIds)) { + mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java index 43d1bce761..20f02b1319 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java @@ -21,31 +21,29 @@ class GetIndexResponseContainsIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final String[] expectedIndices; - - GetIndexResponseContainsIndicesMatcher(String[] expectedIndices) { - if (isNull(expectedIndices) || 0 == expectedIndices.length) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = expectedIndices; - } - - @Override - protected boolean matchesSafely(GetIndexResponse response, Description mismatchDescription) { - List actual = Arrays.asList(response.getIndices()); - for (String index : expectedIndices) { - if (!actual.contains(index)) { - mismatchDescription - .appendText("Actual indices: ") - .appendValue(response.getIndices()); - return false; - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain indices: ").appendValue(expectedIndices); - } + private final String[] expectedIndices; + + GetIndexResponseContainsIndicesMatcher(String[] expectedIndices) { + if (isNull(expectedIndices) || 0 == expectedIndices.length) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = expectedIndices; + } + + @Override + protected boolean matchesSafely(GetIndexResponse response, Description mismatchDescription) { + List actual = Arrays.asList(response.getIndices()); + for (String index : expectedIndices) { + if (!actual.contains(index)) { + mismatchDescription.appendText("Actual indices: ").appendValue(response.getIndices()); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java index a246ec14b3..8e2b3da097 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java @@ -21,31 +21,29 @@ class GetMappingsResponseContainsIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final String[] expectedIndices; - - GetMappingsResponseContainsIndicesMatcher(String[] expectedIndices) { - if (isNull(expectedIndices) || 0 == expectedIndices.length) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = expectedIndices; - } - - @Override - protected boolean matchesSafely(GetMappingsResponse response, Description mismatchDescription) { - Map indicesMappings = response.mappings(); - for (String index : expectedIndices) { - if (!indicesMappings.containsKey(index)) { - mismatchDescription - .appendText("Response contains mappings of indices: ") - .appendValue(indicesMappings.keySet()); - return false; - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain mappings of indices: ").appendValue(expectedIndices); - } + private final String[] expectedIndices; + + GetMappingsResponseContainsIndicesMatcher(String[] expectedIndices) { + if (isNull(expectedIndices) || 0 == expectedIndices.length) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = expectedIndices; + } + + @Override + protected boolean matchesSafely(GetMappingsResponse response, Description mismatchDescription) { + Map indicesMappings = response.mappings(); + for (String index : expectedIndices) { + if (!indicesMappings.containsKey(index)) { + mismatchDescription.appendText("Response contains mappings of indices: ").appendValue(indicesMappings.keySet()); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain mappings of indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java index b677d6e6e1..e6d7f02c6e 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java @@ -18,34 +18,37 @@ class GetResponseContainOnlyDocumentIdMatcher extends TypeSafeDiagnosingMatcher { - private final String indexName; - private final String documentId; - - public GetResponseContainOnlyDocumentIdMatcher(String indexName, String documentId) { - this.indexName = requireNonNull(indexName, "Index name is required"); - this.documentId = requireNonNull(documentId, "Document id is required"); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - if(indexName.equals(response.getIndex()) == false ) { - mismatchDescription.appendText(" index name ").appendValue(response.getIndex()).appendText(" is incorrect "); - return false; - } - if(documentId.equals(response.getId()) == false) { - mismatchDescription.appendText(" id ").appendValue(response.getId()).appendText(" is incorrect "); - return false; - } - if(response.isExists()) { - mismatchDescription.appendText(" document exist what is not desired "); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain document id from index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId).appendText(" but document should not be present "); - } + private final String indexName; + private final String documentId; + + public GetResponseContainOnlyDocumentIdMatcher(String indexName, String documentId) { + this.indexName = requireNonNull(indexName, "Index name is required"); + this.documentId = requireNonNull(documentId, "Document id is required"); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + if (indexName.equals(response.getIndex()) == false) { + mismatchDescription.appendText(" index name ").appendValue(response.getIndex()).appendText(" is incorrect "); + return false; + } + if (documentId.equals(response.getId()) == false) { + mismatchDescription.appendText(" id ").appendValue(response.getId()).appendText(" is incorrect "); + return false; + } + if (response.isExists()) { + mismatchDescription.appendText(" document exist what is not desired "); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain document id from index ") + .appendValue(indexName) + .appendText(" with id ") + .appendValue(documentId) + .appendText(" but document should not be present "); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java index 5dd0c72576..aa9d702243 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java @@ -18,38 +18,40 @@ class GetResponseContainsDocumentWithIdMatcher extends TypeSafeDiagnosingMatcher { - private final String indexName; - private final String documentId; - - public GetResponseContainsDocumentWithIdMatcher(String indexName, String documentId) { - this.indexName = requireNonNull(indexName, "Index name is required"); - this.documentId = requireNonNull(documentId, "Document id is required"); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - if(indexName.equals(response.getIndex()) == false ) { - mismatchDescription.appendText("Document should not belong to index ").appendValue(response.getIndex()); - return false; - } - if(documentId.equals(response.getId()) == false) { - mismatchDescription.appendText("Document contain incorrect id which is ").appendValue(response.getId()); - return false; - } - if(response.isExists() == false) { - mismatchDescription.appendText("Document does not exist or is inaccessible"); - return false; - } - if(response.isSourceEmpty()) { - mismatchDescription.appendText("Document source is empty"); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain document from index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId); - } + private final String indexName; + private final String documentId; + + public GetResponseContainsDocumentWithIdMatcher(String indexName, String documentId) { + this.indexName = requireNonNull(indexName, "Index name is required"); + this.documentId = requireNonNull(documentId, "Document id is required"); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + if (indexName.equals(response.getIndex()) == false) { + mismatchDescription.appendText("Document should not belong to index ").appendValue(response.getIndex()); + return false; + } + if (documentId.equals(response.getId()) == false) { + mismatchDescription.appendText("Document contain incorrect id which is ").appendValue(response.getId()); + return false; + } + if (response.isExists() == false) { + mismatchDescription.appendText("Document does not exist or is inaccessible"); + return false; + } + if (response.isSourceEmpty()) { + mismatchDescription.appendText("Document source is empty"); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain document from index ") + .appendValue(indexName) + .appendText(" with id ") + .appendValue(documentId); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java index aa8daa0128..66bdc0a9b7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java @@ -21,29 +21,31 @@ class GetResponseDocumentContainsExactlyFieldsWithNamesMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedFieldsNames; - - GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(String... expectedFieldsNames) { - if (isNull(expectedFieldsNames) || expectedFieldsNames.length == 0) { - throw new IllegalArgumentException("expectedFieldsNames cannot be null or empty"); - } - this.expectedFieldsNames = Set.of(expectedFieldsNames); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - Map sourceMap = response.getSourceAsMap(); - Set actualFieldsNames = sourceMap.keySet(); - if (!expectedFieldsNames.equals(actualFieldsNames)) { - mismatchDescription.appendValue("Document with id ").appendValue(response.getId()) - .appendText(" contains fields with names: ").appendValue(actualFieldsNames); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Document contain exactly fields with names: ").appendValue(expectedFieldsNames); - } + private final Set expectedFieldsNames; + + GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(String... expectedFieldsNames) { + if (isNull(expectedFieldsNames) || expectedFieldsNames.length == 0) { + throw new IllegalArgumentException("expectedFieldsNames cannot be null or empty"); + } + this.expectedFieldsNames = Set.of(expectedFieldsNames); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + Map sourceMap = response.getSourceAsMap(); + Set actualFieldsNames = sourceMap.keySet(); + if (!expectedFieldsNames.equals(actualFieldsNames)) { + mismatchDescription.appendValue("Document with id ") + .appendValue(response.getId()) + .appendText(" contains fields with names: ") + .appendValue(actualFieldsNames); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Document contain exactly fields with names: ").appendValue(expectedFieldsNames); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java index f8f81f0e95..508e5b8b61 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java @@ -20,28 +20,28 @@ class GetResponseDocumentDoesNotContainFieldMatcher extends TypeSafeDiagnosingMatcher { - private final String fieldName; - - public GetResponseDocumentDoesNotContainFieldMatcher(String fieldName) { - this.fieldName = requireNonNull(fieldName, "Field name is required."); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - Map source = response.getSource(); - if(source == null) { - mismatchDescription.appendText("Source is not available in search results"); - return false; - } - if(source.containsKey(fieldName)) { - mismatchDescription.appendText("Document contains field ").appendValue(fieldName); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Document does not contain field ").appendValue(fieldName); - } + private final String fieldName; + + public GetResponseDocumentDoesNotContainFieldMatcher(String fieldName) { + this.fieldName = requireNonNull(fieldName, "Field name is required."); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + Map source = response.getSource(); + if (source == null) { + mismatchDescription.appendText("Source is not available in search results"); + return false; + } + if (source.containsKey(fieldName)) { + mismatchDescription.appendText("Document contains field ").appendValue(fieldName); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Document does not contain field ").appendValue(fieldName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java index 72418fe6e0..78bcae5494 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java @@ -20,36 +20,38 @@ class GetResponseDocumentFieldValueMatcher extends TypeSafeDiagnosingMatcher { - private final String fieldName; - private final Object fieldValue; - - public GetResponseDocumentFieldValueMatcher(String fieldName, Object fieldValue) { - this.fieldName = requireNonNull(fieldName, "Field name is required."); - this.fieldValue = requireNonNull(fieldValue, "Field value is required."); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - Map source = response.getSource(); - if(source == null) { - mismatchDescription.appendText("Source is not available in search results"); - return false; - } - if(source.containsKey(fieldName) == false) { - mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); - return false; - } - Object actualFieldValue = source.get(fieldName); - if(fieldValue.equals(actualFieldValue) == false) { - mismatchDescription.appendText("Field ").appendValue(fieldName).appendText(" has incorrect value ") - .appendValue(actualFieldValue); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Document contain field ").appendValue(fieldName).appendText(" with value ").appendValue(fieldValue); - } + private final String fieldName; + private final Object fieldValue; + + public GetResponseDocumentFieldValueMatcher(String fieldName, Object fieldValue) { + this.fieldName = requireNonNull(fieldName, "Field name is required."); + this.fieldValue = requireNonNull(fieldValue, "Field value is required."); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + Map source = response.getSource(); + if (source == null) { + mismatchDescription.appendText("Source is not available in search results"); + return false; + } + if (source.containsKey(fieldName) == false) { + mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); + return false; + } + Object actualFieldValue = source.get(fieldName); + if (fieldValue.equals(actualFieldValue) == false) { + mismatchDescription.appendText("Field ") + .appendValue(fieldName) + .appendText(" has incorrect value ") + .appendValue(actualFieldValue); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Document contain field ").appendValue(fieldName).appendText(" with value ").appendValue(fieldValue); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java index 6a494dc9cd..89c183fc34 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java @@ -13,27 +13,27 @@ import org.opensearch.action.get.GetResponse; -public class GetResponseMatchers { +public class GetResponseMatchers { - private GetResponseMatchers() {} + private GetResponseMatchers() {} - public static Matcher containDocument(String indexName, String documentId) { - return new GetResponseContainsDocumentWithIdMatcher(indexName, documentId); - } + public static Matcher containDocument(String indexName, String documentId) { + return new GetResponseContainsDocumentWithIdMatcher(indexName, documentId); + } - public static Matcher containOnlyDocumentId(String indexName, String documentId) { - return new GetResponseContainOnlyDocumentIdMatcher(indexName, documentId); - } + public static Matcher containOnlyDocumentId(String indexName, String documentId) { + return new GetResponseContainOnlyDocumentIdMatcher(indexName, documentId); + } - public static Matcher documentContainField(String fieldName, Object fieldValue) { - return new GetResponseDocumentFieldValueMatcher(fieldName, fieldValue); - } + public static Matcher documentContainField(String fieldName, Object fieldValue) { + return new GetResponseDocumentFieldValueMatcher(fieldName, fieldValue); + } - public static Matcher documentDoesNotContainField(String fieldName) { - return new GetResponseDocumentDoesNotContainFieldMatcher(fieldName); - } + public static Matcher documentDoesNotContainField(String fieldName) { + return new GetResponseDocumentDoesNotContainFieldMatcher(fieldName); + } - public static Matcher documentContainsExactlyFieldsWithNames(String... expectedFieldsNames) { - return new GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(expectedFieldsNames); - } + public static Matcher documentContainsExactlyFieldsWithNames(String... expectedFieldsNames) { + return new GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(expectedFieldsNames); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java index e4ed4ac6c4..c96deef001 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java @@ -21,32 +21,30 @@ class GetSettingsResponseContainsIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final String[] expectedIndices; - - GetSettingsResponseContainsIndicesMatcher(String[] expectedIndices) { - if (isNull(expectedIndices) || 0 == expectedIndices.length) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = expectedIndices; - } - - @Override - protected boolean matchesSafely(GetSettingsResponse response, Description mismatchDescription) { - - final Map indexToSettings = response.getIndexToSettings(); - for (String index : expectedIndices) { - if (!indexToSettings.containsKey(index)) { - mismatchDescription - .appendText("Response contains settings of indices: ") - .appendValue(indexToSettings.keySet()); - return false; - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain settings of indices: ").appendValue(expectedIndices); - } + private final String[] expectedIndices; + + GetSettingsResponseContainsIndicesMatcher(String[] expectedIndices) { + if (isNull(expectedIndices) || 0 == expectedIndices.length) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = expectedIndices; + } + + @Override + protected boolean matchesSafely(GetSettingsResponse response, Description mismatchDescription) { + + final Map indexToSettings = response.getIndexToSettings(); + for (String index : expectedIndices) { + if (!indexToSettings.containsKey(index)) { + mismatchDescription.appendText("Response contains settings of indices: ").appendValue(indexToSettings.keySet()); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain settings of indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java index 09e76c93e0..aab3d426d2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java @@ -21,26 +21,29 @@ class IndexExistsMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - - IndexExistsMatcher(String expectedIndexName) { - this.expectedIndexName = requireNonNull(expectedIndexName); - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - IndicesExistsResponse indicesExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(expectedIndexName)).actionGet(); - if (!indicesExistsResponse.isExists()) { - mismatchDescription.appendText("Index ").appendValue(expectedIndexName).appendValue(" does not exist"); - return false; - } - return true; - } - } - - @Override - public void describeTo(Description description) { - description.appendText("Index ").appendValue(expectedIndexName).appendText(" exists"); - } + private final String expectedIndexName; + + IndexExistsMatcher(String expectedIndexName) { + this.expectedIndexName = requireNonNull(expectedIndexName); + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + IndicesExistsResponse indicesExistsResponse = client.admin() + .indices() + .exists(new IndicesExistsRequest(expectedIndexName)) + .actionGet(); + if (!indicesExistsResponse.isExists()) { + mismatchDescription.appendText("Index ").appendValue(expectedIndexName).appendValue(" does not exist"); + return false; + } + return true; + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Index ").appendValue(expectedIndexName).appendText(" exists"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java index b90defef7d..ead0e9d1d7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java @@ -25,39 +25,43 @@ class IndexMappingIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - private final Map expectedMapping; - - IndexMappingIsEqualToMatcher(String expectedIndexName, Map expectedMapping) { - this.expectedIndexName = requireNonNull(expectedIndexName); - if (isNull(expectedMapping) || expectedMapping.isEmpty()) { - throw new IllegalArgumentException("expectedMapping cannot be null or empty"); - } - this.expectedMapping = expectedMapping; - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - GetMappingsResponse response = client.admin().indices() - .getMappings(new GetMappingsRequest().indices(expectedIndexName)).actionGet(); - - Map actualIndexMapping = response.getMappings().get(expectedIndexName).sourceAsMap(); - - if (!expectedMapping.equals(actualIndexMapping)) { - mismatchDescription.appendText("Actual mapping ").appendValue(actualIndexMapping).appendText(" does not match expected"); - return false; - } - return true; - } catch (IndexNotFoundException e) { - mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); - return false; - } - } - - @Override - public void describeTo(Description description) { - description.appendText("Index ").appendValue(expectedIndexName) - .appendText(". Mapping should be equal to: ").appendValue(expectedMapping); - } + private final String expectedIndexName; + private final Map expectedMapping; + + IndexMappingIsEqualToMatcher(String expectedIndexName, Map expectedMapping) { + this.expectedIndexName = requireNonNull(expectedIndexName); + if (isNull(expectedMapping) || expectedMapping.isEmpty()) { + throw new IllegalArgumentException("expectedMapping cannot be null or empty"); + } + this.expectedMapping = expectedMapping; + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + GetMappingsResponse response = client.admin() + .indices() + .getMappings(new GetMappingsRequest().indices(expectedIndexName)) + .actionGet(); + + Map actualIndexMapping = response.getMappings().get(expectedIndexName).sourceAsMap(); + + if (!expectedMapping.equals(actualIndexMapping)) { + mismatchDescription.appendText("Actual mapping ").appendValue(actualIndexMapping).appendText(" does not match expected"); + return false; + } + return true; + } catch (IndexNotFoundException e) { + mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); + return false; + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Index ") + .appendValue(expectedIndexName) + .appendText(". Mapping should be equal to: ") + .appendValue(expectedMapping); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java index 80d90ecc6b..88f3ac099d 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java @@ -22,36 +22,36 @@ public class IndexResponseMatchers { - public static Matcher isSuccessfulCreateIndexResponse(String expectedIndexName) { - return new SuccessfulCreateIndexResponseMatcher(expectedIndexName); - } + public static Matcher isSuccessfulCreateIndexResponse(String expectedIndexName) { + return new SuccessfulCreateIndexResponseMatcher(expectedIndexName); + } - public static Matcher getIndexResponseContainsIndices(String... expectedIndices) { - return new GetIndexResponseContainsIndicesMatcher(expectedIndices); - } + public static Matcher getIndexResponseContainsIndices(String... expectedIndices) { + return new GetIndexResponseContainsIndicesMatcher(expectedIndices); + } - public static Matcher isSuccessfulCloseIndexResponse() { - return new SuccessfulCloseIndexResponseMatcher(); - } + public static Matcher isSuccessfulCloseIndexResponse() { + return new SuccessfulCloseIndexResponseMatcher(); + } - public static Matcher isSuccessfulOpenIndexResponse() { - return new SuccessfulOpenIndexResponseMatcher(); - } + public static Matcher isSuccessfulOpenIndexResponse() { + return new SuccessfulOpenIndexResponseMatcher(); + } - public static Matcher isSuccessfulResizeResponse(String expectedIndexName) { - return new SuccessfulResizeResponseMatcher(expectedIndexName); - } + public static Matcher isSuccessfulResizeResponse(String expectedIndexName) { + return new SuccessfulResizeResponseMatcher(expectedIndexName); + } - public static Matcher getSettingsResponseContainsIndices(String... expectedIndices) { - return new GetSettingsResponseContainsIndicesMatcher(expectedIndices); - } + public static Matcher getSettingsResponseContainsIndices(String... expectedIndices) { + return new GetSettingsResponseContainsIndicesMatcher(expectedIndices); + } - public static Matcher isSuccessfulClearIndicesCacheResponse() { - return new SuccessfulClearIndicesCacheResponseMatcher(); - } + public static Matcher isSuccessfulClearIndicesCacheResponse() { + return new SuccessfulClearIndicesCacheResponseMatcher(); + } - public static Matcher getMappingsResponseContainsIndices(String... expectedIndices) { - return new GetMappingsResponseContainsIndicesMatcher(expectedIndices); - } + public static Matcher getMappingsResponseContainsIndices(String... expectedIndices) { + return new GetMappingsResponseContainsIndicesMatcher(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java index 9af40fcd48..6bb89c6cae 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java @@ -24,45 +24,52 @@ class IndexSettingsContainValuesMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - private final Settings expectedSettings; + private final String expectedIndexName; + private final Settings expectedSettings; - IndexSettingsContainValuesMatcher(String expectedIndexName, Settings expectedSettings) { - this.expectedIndexName = requireNonNull(expectedIndexName); - if (isNull(expectedSettings) || expectedSettings.isEmpty()) { - throw new IllegalArgumentException("expectedSettings cannot be null or empty"); - } - this.expectedSettings = expectedSettings; - } + IndexSettingsContainValuesMatcher(String expectedIndexName, Settings expectedSettings) { + this.expectedIndexName = requireNonNull(expectedIndexName); + if (isNull(expectedSettings) || expectedSettings.isEmpty()) { + throw new IllegalArgumentException("expectedSettings cannot be null or empty"); + } + this.expectedSettings = expectedSettings; + } - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - GetSettingsResponse response = client.admin().indices().getSettings(new GetSettingsRequest().indices(expectedIndexName)).actionGet(); + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + GetSettingsResponse response = client.admin() + .indices() + .getSettings(new GetSettingsRequest().indices(expectedIndexName)) + .actionGet(); - Settings actualSettings = response.getIndexToSettings().get(expectedIndexName); + Settings actualSettings = response.getIndexToSettings().get(expectedIndexName); - for (String setting : expectedSettings.keySet()) { - if (isNull(actualSettings.get(setting))) { - mismatchDescription.appendValue("Value of ").appendValue(setting).appendText(" property is missing"); - return false; - } - if (!expectedSettings.get(setting).equals(actualSettings.get(setting))) { - mismatchDescription.appendText("Actual value of `").appendValue(setting) - .appendText("` property: ").appendValue(actualSettings.get(setting)); - return false; - } - } - return true; - } catch (IndexNotFoundException e) { - mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); - return false; - } - } + for (String setting : expectedSettings.keySet()) { + if (isNull(actualSettings.get(setting))) { + mismatchDescription.appendValue("Value of ").appendValue(setting).appendText(" property is missing"); + return false; + } + if (!expectedSettings.get(setting).equals(actualSettings.get(setting))) { + mismatchDescription.appendText("Actual value of `") + .appendValue(setting) + .appendText("` property: ") + .appendValue(actualSettings.get(setting)); + return false; + } + } + return true; + } catch (IndexNotFoundException e) { + mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); + return false; + } + } - @Override - public void describeTo(Description description) { - description.appendText("Settings of index ").appendValue(expectedIndexName) - .appendText(" should contain values: ").appendValue(expectedSettings); - } + @Override + public void describeTo(Description description) { + description.appendText("Settings of index ") + .appendValue(expectedIndexName) + .appendText(" should contain values: ") + .appendValue(expectedSettings); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java index ecff3fe2df..87270b1388 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java @@ -24,36 +24,38 @@ class IndexStateIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - private final IndexMetadata.State expectedState; - - IndexStateIsEqualToMatcher(String expectedIndexName, IndexMetadata.State expectedState) { - this.expectedIndexName = requireNonNull(expectedIndexName); - this.expectedState = requireNonNull(expectedState); - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - ClusterStateRequest clusterStateRequest = new ClusterStateRequest().indices(expectedIndexName); - ClusterStateResponse clusterStateResponse = client.admin().cluster().state(clusterStateRequest).actionGet(); - - Map indicesMetadata = clusterStateResponse.getState().getMetadata().indices(); - if (!indicesMetadata.containsKey(expectedIndexName)) { - mismatchDescription.appendValue("Index does not exist"); - } - IndexMetadata indexMetadata = indicesMetadata.get(expectedIndexName); - if (expectedState != indexMetadata.getState()) { - mismatchDescription.appendValue("Actual index state is equal to ").appendValue(indexMetadata.getState().name()); - return false; - } - return true; - } - } - - @Override - public void describeTo(Description description) { - description.appendText("Index: ").appendValue(expectedIndexName) - .appendText(" . State should be equal to ").appendValue(expectedState.name()); - } + private final String expectedIndexName; + private final IndexMetadata.State expectedState; + + IndexStateIsEqualToMatcher(String expectedIndexName, IndexMetadata.State expectedState) { + this.expectedIndexName = requireNonNull(expectedIndexName); + this.expectedState = requireNonNull(expectedState); + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + ClusterStateRequest clusterStateRequest = new ClusterStateRequest().indices(expectedIndexName); + ClusterStateResponse clusterStateResponse = client.admin().cluster().state(clusterStateRequest).actionGet(); + + Map indicesMetadata = clusterStateResponse.getState().getMetadata().indices(); + if (!indicesMetadata.containsKey(expectedIndexName)) { + mismatchDescription.appendValue("Index does not exist"); + } + IndexMetadata indexMetadata = indicesMetadata.get(expectedIndexName); + if (expectedState != indexMetadata.getState()) { + mismatchDescription.appendValue("Actual index state is equal to ").appendValue(indexMetadata.getState().name()); + return false; + } + return true; + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Index: ") + .appendValue(expectedIndexName) + .appendText(" . State should be equal to ") + .appendValue(expectedState.name()); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java index 30b3037752..c2e86b1310 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java @@ -15,15 +15,14 @@ public class MultiGetResponseMatchers { - private MultiGetResponseMatchers() { - } + private MultiGetResponseMatchers() {} - public static Matcher isSuccessfulMultiGetResponse() { - return new SuccessfulMultiGetResponseMatcher(); - } + public static Matcher isSuccessfulMultiGetResponse() { + return new SuccessfulMultiGetResponseMatcher(); + } - public static Matcher numberOfGetItemResponsesIsEqualTo(int expectedNumberOfResponses) { - return new NumberOfGetItemResponsesIsEqualToMatcher(expectedNumberOfResponses); - } + public static Matcher numberOfGetItemResponsesIsEqualTo(int expectedNumberOfResponses) { + return new NumberOfGetItemResponsesIsEqualToMatcher(expectedNumberOfResponses); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java index 39a2645ce4..9709249d11 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java @@ -15,15 +15,14 @@ public class MultiSearchResponseMatchers { - private MultiSearchResponseMatchers() { - } + private MultiSearchResponseMatchers() {} - public static Matcher isSuccessfulMultiSearchResponse() { - return new SuccessfulMultiSearchResponseMatcher(); - } + public static Matcher isSuccessfulMultiSearchResponse() { + return new SuccessfulMultiSearchResponseMatcher(); + } - public static Matcher numberOfSearchItemResponsesIsEqualTo(int expectedNumberOfResponses) { - return new NumberOfSearchItemResponsesIsEqualToMatcher(expectedNumberOfResponses); - } + public static Matcher numberOfSearchItemResponsesIsEqualTo(int expectedNumberOfResponses) { + return new NumberOfSearchItemResponsesIsEqualToMatcher(expectedNumberOfResponses); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java index a11d360b98..ad8e9725c3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java @@ -16,24 +16,23 @@ class NumberOfFieldsIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfFields; + private final int expectedNumberOfFields; - NumberOfFieldsIsEqualToMatcher(int expectedNumberOfFields) { - this.expectedNumberOfFields = expectedNumberOfFields; - } + NumberOfFieldsIsEqualToMatcher(int expectedNumberOfFields) { + this.expectedNumberOfFields = expectedNumberOfFields; + } - @Override - protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { - if (expectedNumberOfFields != response.get().size()) { - mismatchDescription.appendText("Actual number of fields: ").appendValue(response.get().size()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { + if (expectedNumberOfFields != response.get().size()) { + mismatchDescription.appendText("Actual number of fields: ").appendValue(response.get().size()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Response contains information about ") - .appendValue(expectedNumberOfFields).appendText(" fields"); - } + @Override + public void describeTo(Description description) { + description.appendText("Response contains information about ").appendValue(expectedNumberOfFields).appendText(" fields"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java index 141b235f2f..38cfaeb130 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java @@ -16,25 +16,23 @@ class NumberOfGetItemResponsesIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfResponses; - - NumberOfGetItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { - this.expectedNumberOfResponses = expectedNumberOfResponses; - } - - - @Override - protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { - if (expectedNumberOfResponses != response.getResponses().length) { - mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Multi get response contains: ").appendValue(expectedNumberOfResponses) - .appendText(" item responses"); - } + private final int expectedNumberOfResponses; + + NumberOfGetItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { + this.expectedNumberOfResponses = expectedNumberOfResponses; + } + + @Override + protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { + if (expectedNumberOfResponses != response.getResponses().length) { + mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Multi get response contains: ").appendValue(expectedNumberOfResponses).appendText(" item responses"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java index b8671bb885..8a25a336f3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java @@ -17,29 +17,29 @@ class NumberOfHitsInPageIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfHits; + private final int expectedNumberOfHits; - public NumberOfHitsInPageIsEqualToMatcher(int expectedNumberOfHits) { - this.expectedNumberOfHits = expectedNumberOfHits; - } + public NumberOfHitsInPageIsEqualToMatcher(int expectedNumberOfHits) { + this.expectedNumberOfHits = expectedNumberOfHits; + } - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - SearchHits hits = searchResponse.getHits(); - if((hits == null) || (hits.getHits() == null)) { - mismatchDescription.appendText("contains null hits"); - return false; - } - int actualNumberOfHits = hits.getHits().length; - if(expectedNumberOfHits != actualNumberOfHits) { - mismatchDescription.appendText("actual number of hits is equal to ").appendValue(actualNumberOfHits); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + SearchHits hits = searchResponse.getHits(); + if ((hits == null) || (hits.getHits() == null)) { + mismatchDescription.appendText("contains null hits"); + return false; + } + int actualNumberOfHits = hits.getHits().length; + if (expectedNumberOfHits != actualNumberOfHits) { + mismatchDescription.appendText("actual number of hits is equal to ").appendValue(actualNumberOfHits); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Number of hits on current page should be equal to ").appendValue(expectedNumberOfHits); - } + @Override + public void describeTo(Description description) { + description.appendText("Number of hits on current page should be equal to ").appendValue(expectedNumberOfHits); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java index 971473148c..54bb83cba7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java @@ -16,26 +16,24 @@ class NumberOfSearchItemResponsesIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfResponses; - - NumberOfSearchItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { - this.expectedNumberOfResponses = expectedNumberOfResponses; - } - - - @Override - protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { - if (expectedNumberOfResponses != response.getResponses().length) { - mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); - return false; - } - - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Multi search response contains: ").appendValue(expectedNumberOfResponses) - .appendText(" item responses"); - } + private final int expectedNumberOfResponses; + + NumberOfSearchItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { + this.expectedNumberOfResponses = expectedNumberOfResponses; + } + + @Override + protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { + if (expectedNumberOfResponses != response.getResponses().length) { + mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); + return false; + } + + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Multi search response contains: ").appendValue(expectedNumberOfResponses).appendText(" item responses"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java index 3045da00b1..3f2b379498 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java @@ -21,37 +21,39 @@ class NumberOfTotalHitsIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfHits; - - NumberOfTotalHitsIsEqualToMatcher(int expectedNumberOfHits) { - this.expectedNumberOfHits = expectedNumberOfHits; - } - - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - SearchHits hits = searchResponse.getHits(); - if(hits == null) { - mismatchDescription.appendText("contains null hits"); - return false; - } - TotalHits totalHits = hits.getTotalHits(); - if(totalHits == null) { - mismatchDescription.appendText("Total hits number is null."); - return false; - } - if(expectedNumberOfHits != totalHits.value) { - String documentIds = Arrays.stream(searchResponse.getHits().getHits()) - .map(hit -> hit.getIndex() + "/" + hit.getId()) - .collect(Collectors.joining(",")); - mismatchDescription.appendText( "contains ").appendValue(hits.getHits().length).appendText(" hits, found document ids ") - .appendValue(documentIds); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Search response should contains ").appendValue(expectedNumberOfHits).appendText(" hits"); - } + private final int expectedNumberOfHits; + + NumberOfTotalHitsIsEqualToMatcher(int expectedNumberOfHits) { + this.expectedNumberOfHits = expectedNumberOfHits; + } + + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + SearchHits hits = searchResponse.getHits(); + if (hits == null) { + mismatchDescription.appendText("contains null hits"); + return false; + } + TotalHits totalHits = hits.getTotalHits(); + if (totalHits == null) { + mismatchDescription.appendText("Total hits number is null."); + return false; + } + if (expectedNumberOfHits != totalHits.value) { + String documentIds = Arrays.stream(searchResponse.getHits().getHits()) + .map(hit -> hit.getIndex() + "/" + hit.getId()) + .collect(Collectors.joining(",")); + mismatchDescription.appendText("contains ") + .appendValue(hits.getHits().length) + .appendText(" hits, found document ids ") + .appendValue(documentIds); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Search response should contains ").appendValue(expectedNumberOfHits).appendText(" hits"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java index 008922b4e8..8627e4bda2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java @@ -17,21 +17,21 @@ public class OpenSearchExceptionMatchers { - private OpenSearchExceptionMatchers() {} + private OpenSearchExceptionMatchers() {} - public static Matcher statusException(RestStatus expectedRestStatus) { - return new OpenSearchStatusExceptionMatcher(expectedRestStatus); - } + public static Matcher statusException(RestStatus expectedRestStatus) { + return new OpenSearchStatusExceptionMatcher(expectedRestStatus); + } - public static Matcher errorMessage(Matcher errorMessageMatcher) { - return new ExceptionErrorMessageMatcher(errorMessageMatcher); - } + public static Matcher errorMessage(Matcher errorMessageMatcher) { + return new ExceptionErrorMessageMatcher(errorMessageMatcher); + } - public static Matcher errorMessageContain(String errorMessage) { - return errorMessage(containsString(errorMessage)); - } + public static Matcher errorMessageContain(String errorMessage) { + return errorMessage(containsString(errorMessage)); + } - public static Matcher hasCause(Class clazz) { - return new ExceptionHasCauseMatcher(clazz); - } + public static Matcher hasCause(Class clazz) { + return new ExceptionHasCauseMatcher(clazz); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java index 863f1e52a1..118251ec04 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java @@ -19,30 +19,34 @@ class OpenSearchStatusExceptionMatcher extends TypeSafeDiagnosingMatcher { - private final RestStatus expectedRestStatus; - - public OpenSearchStatusExceptionMatcher(RestStatus expectedRestStatus) { - this.expectedRestStatus = requireNonNull(expectedRestStatus, "Expected rest status is required."); - } - - @Override - protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { - if((throwable instanceof OpenSearchException) == false) { - mismatchDescription.appendText("actual exception type is ").appendValue(throwable.getClass().getCanonicalName()) - .appendText(", error message ").appendValue(throwable.getMessage()); - return false; - } - OpenSearchException openSearchException = (OpenSearchException) throwable; - if(expectedRestStatus.equals(openSearchException.status()) == false) { - mismatchDescription.appendText("actual status code is ").appendValue(openSearchException.status()) - .appendText(", error message ").appendValue(throwable.getMessage()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("OpenSearchException with status code ").appendValue(expectedRestStatus); - } + private final RestStatus expectedRestStatus; + + public OpenSearchStatusExceptionMatcher(RestStatus expectedRestStatus) { + this.expectedRestStatus = requireNonNull(expectedRestStatus, "Expected rest status is required."); + } + + @Override + protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { + if ((throwable instanceof OpenSearchException) == false) { + mismatchDescription.appendText("actual exception type is ") + .appendValue(throwable.getClass().getCanonicalName()) + .appendText(", error message ") + .appendValue(throwable.getMessage()); + return false; + } + OpenSearchException openSearchException = (OpenSearchException) throwable; + if (expectedRestStatus.equals(openSearchException.status()) == false) { + mismatchDescription.appendText("actual status code is ") + .appendValue(openSearchException.status()) + .appendText(", error message ") + .appendValue(throwable.getMessage()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("OpenSearchException with status code ").appendValue(expectedRestStatus); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java index 3e72866092..84ab459210 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java @@ -17,22 +17,21 @@ public class PitResponseMatchers { - private PitResponseMatchers() { - } + private PitResponseMatchers() {} - public static Matcher isSuccessfulCreatePitResponse() { - return new SuccessfulCreatePitResponseMatcher(); - } + public static Matcher isSuccessfulCreatePitResponse() { + return new SuccessfulCreatePitResponseMatcher(); + } - public static Matcher getAllResponseContainsExactlyPitWithIds(String... expectedPitIds) { - return new GetAllPitsContainsExactlyIdsResponseMatcher(expectedPitIds); - } + public static Matcher getAllResponseContainsExactlyPitWithIds(String... expectedPitIds) { + return new GetAllPitsContainsExactlyIdsResponseMatcher(expectedPitIds); + } - public static Matcher isSuccessfulDeletePitResponse() { - return new SuccessfulDeletePitResponseMatcher(); - } + public static Matcher isSuccessfulDeletePitResponse() { + return new SuccessfulDeletePitResponseMatcher(); + } - public static Matcher deleteResponseContainsExactlyPitWithIds(String... expectedPitIds) { - return new DeletePitContainsExactlyIdsResponseMatcher(expectedPitIds); - } + public static Matcher deleteResponseContainsExactlyPitWithIds(String... expectedPitIds) { + return new DeletePitContainsExactlyIdsResponseMatcher(expectedPitIds); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java index aa9cfe6864..c92924ebfe 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java @@ -21,49 +21,54 @@ class SearchHitContainsFieldWithValueMatcher extends TypeSafeDiagnosingMatcher { - private final int hitIndex; + private final int hitIndex; - private final String fieldName; + private final String fieldName; - private final T expectedValue; + private final T expectedValue; - SearchHitContainsFieldWithValueMatcher(int hitIndex, String fieldName, T expectedValue) { - this.hitIndex = hitIndex; - this.fieldName = fieldName; - this.expectedValue = expectedValue; - } + SearchHitContainsFieldWithValueMatcher(int hitIndex, String fieldName, T expectedValue) { + this.hitIndex = hitIndex; + this.fieldName = fieldName; + this.expectedValue = expectedValue; + } - @Override protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - Long numberOfHits = readTotalHits(searchResponse); - if(numberOfHits == null) { - mismatchDescription.appendText("Total number of hits is unknown."); - return false; - } - if(hitIndex >= numberOfHits) { - mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); - return false; - } - SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); - Map source = searchHit.getSourceAsMap(); - if(source == null){ - mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); - return false; - } - if(source.containsKey(fieldName) == false) { - mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); - return false; - } - Object actualValue = source.get(fieldName); - if(!expectedValue.equals(actualValue)) { - mismatchDescription.appendText("Field value is equal to ").appendValue(actualValue); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + Long numberOfHits = readTotalHits(searchResponse); + if (numberOfHits == null) { + mismatchDescription.appendText("Total number of hits is unknown."); + return false; + } + if (hitIndex >= numberOfHits) { + mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); + return false; + } + SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); + Map source = searchHit.getSourceAsMap(); + if (source == null) { + mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); + return false; + } + if (source.containsKey(fieldName) == false) { + mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); + return false; + } + Object actualValue = source.get(fieldName); + if (!expectedValue.equals(actualValue)) { + mismatchDescription.appendText("Field value is equal to ").appendValue(actualValue); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Search hit with index ").appendValue(hitIndex).appendText(" should contain field ").appendValue(fieldName) - .appendValue(" with value equal to ").appendValue(expectedValue); - } + @Override + public void describeTo(Description description) { + description.appendText("Search hit with index ") + .appendValue(hitIndex) + .appendText(" should contain field ") + .appendValue(fieldName) + .appendValue(" with value equal to ") + .appendValue(expectedValue); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java index 106f2ee943..0562acdcbb 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java @@ -22,42 +22,44 @@ class SearchHitDoesNotContainFieldMatcher extends TypeSafeDiagnosingMatcher { - private final int hitIndex; - - private final String fieldName; - - public SearchHitDoesNotContainFieldMatcher(int hitIndex, String fieldName) { - this.hitIndex = hitIndex; - this.fieldName = requireNonNull(fieldName, "Field name is required."); - } - - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - Long numberOfHits = readTotalHits(searchResponse); - if(numberOfHits == null) { - mismatchDescription.appendText("Total number of hits is unknown."); - return false; - } - if(hitIndex >= numberOfHits) { - mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); - return false; - } - SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); - Map source = searchHit.getSourceAsMap(); - if(source == null){ - mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); - return false; - } - if(source.containsKey(fieldName)) { - mismatchDescription.appendText(" document contains field ").appendValue(fieldName); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("search hit with index ").appendValue(hitIndex).appendText(" does not contain field ") - .appendValue(fieldName); - } + private final int hitIndex; + + private final String fieldName; + + public SearchHitDoesNotContainFieldMatcher(int hitIndex, String fieldName) { + this.hitIndex = hitIndex; + this.fieldName = requireNonNull(fieldName, "Field name is required."); + } + + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + Long numberOfHits = readTotalHits(searchResponse); + if (numberOfHits == null) { + mismatchDescription.appendText("Total number of hits is unknown."); + return false; + } + if (hitIndex >= numberOfHits) { + mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); + return false; + } + SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); + Map source = searchHit.getSourceAsMap(); + if (source == null) { + mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); + return false; + } + if (source.containsKey(fieldName)) { + mismatchDescription.appendText(" document contains field ").appendValue(fieldName); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("search hit with index ") + .appendValue(hitIndex) + .appendText(" does not contain field ") + .appendValue(fieldName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java index c3a7528432..d21df7a578 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java @@ -19,42 +19,46 @@ class SearchHitsContainDocumentWithIdMatcher extends TypeSafeDiagnosingMatcher { - private final int hitIndex; - private final String indexName; - private final String id; - - public SearchHitsContainDocumentWithIdMatcher(int hitIndex, String indexName, String id) { - this.hitIndex = hitIndex; - this.indexName = indexName; - this.id = id; - } - - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - Long numberOfHits = readTotalHits(searchResponse); - if(numberOfHits == null) { - mismatchDescription.appendText("Number of total hits is unknown."); - return false; - } - if(hitIndex >= numberOfHits) { - mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); - return false; - } - SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); - if(indexName.equals(searchHit.getIndex()) == false) { - mismatchDescription.appendText("document is part of another index ").appendValue(indexName); - return false; - } - if(id.equals(searchHit.getId()) == false) { - mismatchDescription.appendText("Document has another id which is ").appendValue(searchHit.getId()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Search hit with index ").appendValue(hitIndex).appendText(" should contains document which is part of index ") - .appendValue(indexName).appendValue(" and has id ").appendValue(id); - } + private final int hitIndex; + private final String indexName; + private final String id; + + public SearchHitsContainDocumentWithIdMatcher(int hitIndex, String indexName, String id) { + this.hitIndex = hitIndex; + this.indexName = indexName; + this.id = id; + } + + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + Long numberOfHits = readTotalHits(searchResponse); + if (numberOfHits == null) { + mismatchDescription.appendText("Number of total hits is unknown."); + return false; + } + if (hitIndex >= numberOfHits) { + mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); + return false; + } + SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); + if (indexName.equals(searchHit.getIndex()) == false) { + mismatchDescription.appendText("document is part of another index ").appendValue(indexName); + return false; + } + if (id.equals(searchHit.getId()) == false) { + mismatchDescription.appendText("Document has another id which is ").appendValue(searchHit.getId()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Search hit with index ") + .appendValue(hitIndex) + .appendText(" should contains document which is part of index ") + .appendValue(indexName) + .appendValue(" and has id ") + .appendValue(id); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java index 78fd20557e..28bf13e321 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java @@ -26,49 +26,51 @@ class SearchHitsContainDocumentsInAnyOrderMatcher extends TypeSafeDiagnosingMatcher { - /** - * Pair contain index name and document id - */ - private final List> documentIds; + /** + * Pair contain index name and document id + */ + private final List> documentIds; - /** - * - * @param documentIds Pair contain index name and document id - */ - public SearchHitsContainDocumentsInAnyOrderMatcher(List> documentIds) { - this.documentIds = requireNonNull(documentIds, "Document ids are required."); - } + /** + * + * @param documentIds Pair contain index name and document id + */ + public SearchHitsContainDocumentsInAnyOrderMatcher(List> documentIds) { + this.documentIds = requireNonNull(documentIds, "Document ids are required."); + } - @Override - protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { - SearchHits hits = response.getHits(); - if(hits == null) { - mismatchDescription.appendText("Search response does not contains hits (null)."); - return false; - } - SearchHit[] hitsArray = hits.getHits(); - if(hitsArray == null) { - mismatchDescription.appendText("Search hits array is null"); - return false; - } - Set> actualDocumentIds = Arrays.stream(hitsArray) - .map(result -> Pair.of(result.getIndex(), result.getId())) - .collect(Collectors.toSet()); - for(Pair desiredDocumentId : documentIds) { - if(actualDocumentIds.contains(desiredDocumentId) == false) { - mismatchDescription.appendText("search result does not contain document with id ") - .appendValue(desiredDocumentId.getKey()).appendText("/").appendValue(desiredDocumentId.getValue()); - return false; - } - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { + SearchHits hits = response.getHits(); + if (hits == null) { + mismatchDescription.appendText("Search response does not contains hits (null)."); + return false; + } + SearchHit[] hitsArray = hits.getHits(); + if (hitsArray == null) { + mismatchDescription.appendText("Search hits array is null"); + return false; + } + Set> actualDocumentIds = Arrays.stream(hitsArray) + .map(result -> Pair.of(result.getIndex(), result.getId())) + .collect(Collectors.toSet()); + for (Pair desiredDocumentId : documentIds) { + if (actualDocumentIds.contains(desiredDocumentId) == false) { + mismatchDescription.appendText("search result does not contain document with id ") + .appendValue(desiredDocumentId.getKey()) + .appendText("/") + .appendValue(desiredDocumentId.getValue()); + return false; + } + } + return true; + } - @Override - public void describeTo(Description description) { - String documentIdsString = documentIds.stream() - .map(pair -> pair.getKey() + "/" + pair.getValue()) - .collect(Collectors.joining(", ")); - description.appendText("Search response should contains following documents ").appendValue(documentIdsString); - } + @Override + public void describeTo(Description description) { + String documentIdsString = documentIds.stream() + .map(pair -> pair.getKey() + "/" + pair.getValue()) + .collect(Collectors.joining(", ")); + description.appendText("Search response should contains following documents ").appendValue(documentIdsString); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java index acb669a85e..c0a484b47c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java @@ -22,64 +22,66 @@ public class SearchResponseMatchers { - private SearchResponseMatchers() {} - - public static Matcher isSuccessfulSearchResponse() { - return new SuccessfulSearchResponseMatcher(); - } - - public static Matcher numberOfTotalHitsIsEqualTo(int expectedNumberOfHits) { - return new NumberOfTotalHitsIsEqualToMatcher(expectedNumberOfHits); - } - - public static Matcher numberOfHitsInPageIsEqualTo(int expectedNumberOfHits) { - return new NumberOfHitsInPageIsEqualToMatcher(expectedNumberOfHits); - } - - public static Matcher searchHitContainsFieldWithValue(int hitIndex, String fieldName, T expectedValue) { - return new SearchHitContainsFieldWithValueMatcher<>(hitIndex, fieldName, expectedValue); - } - - public static Matcher searchHitDoesNotContainField(int hitIndex, String fieldName) { - return new SearchHitDoesNotContainFieldMatcher(hitIndex, fieldName); - } - - - public static Matcher searchHitsContainDocumentWithId(int hitIndex, String indexName, String documentId) { - return new SearchHitsContainDocumentWithIdMatcher(hitIndex, indexName, documentId); - } - - public static Matcher restStatusIs(RestStatus expectedRestStatus) { - return new SearchResponseWithStatusCodeMatcher(expectedRestStatus); - } - - public static Matcher containNotEmptyScrollingId() { - return new ContainNotEmptyScrollingIdMatcher(); - } - - public static Matcher containAggregationWithNameAndType(String expectedAggregationName, String expectedAggregationType) { - return new ContainsAggregationWithNameAndTypeMatcher(expectedAggregationName, expectedAggregationType); - } - - /** - * Matcher checks if search result contains all expected documents - * - * @param documentIds Pair contain index name and document id - * @return matcher - */ - public static Matcher searchHitsContainDocumentsInAnyOrder(List> documentIds) { - return new SearchHitsContainDocumentsInAnyOrderMatcher(documentIds); - } - - public static Matcher searchHitsContainDocumentsInAnyOrder(Pair...documentIds) { - return new SearchHitsContainDocumentsInAnyOrderMatcher(Arrays.asList(documentIds)); - } - - static Long readTotalHits(SearchResponse searchResponse) { - return Optional.ofNullable(searchResponse) - .map(SearchResponse::getHits) - .map(SearchHits::getTotalHits) - .map(totalHits -> totalHits.value) - .orElse(null); - } + private SearchResponseMatchers() {} + + public static Matcher isSuccessfulSearchResponse() { + return new SuccessfulSearchResponseMatcher(); + } + + public static Matcher numberOfTotalHitsIsEqualTo(int expectedNumberOfHits) { + return new NumberOfTotalHitsIsEqualToMatcher(expectedNumberOfHits); + } + + public static Matcher numberOfHitsInPageIsEqualTo(int expectedNumberOfHits) { + return new NumberOfHitsInPageIsEqualToMatcher(expectedNumberOfHits); + } + + public static Matcher searchHitContainsFieldWithValue(int hitIndex, String fieldName, T expectedValue) { + return new SearchHitContainsFieldWithValueMatcher<>(hitIndex, fieldName, expectedValue); + } + + public static Matcher searchHitDoesNotContainField(int hitIndex, String fieldName) { + return new SearchHitDoesNotContainFieldMatcher(hitIndex, fieldName); + } + + public static Matcher searchHitsContainDocumentWithId(int hitIndex, String indexName, String documentId) { + return new SearchHitsContainDocumentWithIdMatcher(hitIndex, indexName, documentId); + } + + public static Matcher restStatusIs(RestStatus expectedRestStatus) { + return new SearchResponseWithStatusCodeMatcher(expectedRestStatus); + } + + public static Matcher containNotEmptyScrollingId() { + return new ContainNotEmptyScrollingIdMatcher(); + } + + public static Matcher containAggregationWithNameAndType( + String expectedAggregationName, + String expectedAggregationType + ) { + return new ContainsAggregationWithNameAndTypeMatcher(expectedAggregationName, expectedAggregationType); + } + + /** + * Matcher checks if search result contains all expected documents + * + * @param documentIds Pair contain index name and document id + * @return matcher + */ + public static Matcher searchHitsContainDocumentsInAnyOrder(List> documentIds) { + return new SearchHitsContainDocumentsInAnyOrderMatcher(documentIds); + } + + public static Matcher searchHitsContainDocumentsInAnyOrder(Pair... documentIds) { + return new SearchHitsContainDocumentsInAnyOrderMatcher(Arrays.asList(documentIds)); + } + + static Long readTotalHits(SearchResponse searchResponse) { + return Optional.ofNullable(searchResponse) + .map(SearchResponse::getHits) + .map(SearchHits::getTotalHits) + .map(totalHits -> totalHits.value) + .orElse(null); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java index 8316cc3425..ede13bcb56 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java @@ -17,23 +17,23 @@ class SearchResponseWithStatusCodeMatcher extends TypeSafeDiagnosingMatcher { - private final RestStatus expectedRestStatus; + private final RestStatus expectedRestStatus; - public SearchResponseWithStatusCodeMatcher(RestStatus expectedRestStatus) { - this.expectedRestStatus = expectedRestStatus; - } + public SearchResponseWithStatusCodeMatcher(RestStatus expectedRestStatus) { + this.expectedRestStatus = expectedRestStatus; + } - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - if(expectedRestStatus.equals(searchResponse.status()) == false) { - mismatchDescription.appendText("actual response status is ").appendValue(searchResponse.status()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + if (expectedRestStatus.equals(searchResponse.status()) == false) { + mismatchDescription.appendText("actual response status is ").appendValue(searchResponse.status()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Expected response status is ").appendValue(expectedRestStatus); - } + @Override + public void describeTo(Description description) { + description.appendText("Expected response status is ").appendValue(expectedRestStatus); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java index c2626669be..36e50143f0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java @@ -19,29 +19,31 @@ import static java.util.Objects.requireNonNull; class SnapshotInClusterDoesNotExist extends TypeSafeDiagnosingMatcher { - private final String repositoryName; - private final String snapshotName; + private final String repositoryName; + private final String snapshotName; - public SnapshotInClusterDoesNotExist(String repositoryName, String snapshotName) { - this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); - this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); - } + public SnapshotInClusterDoesNotExist(String repositoryName, String snapshotName) { + this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); + this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); - client.admin().cluster().getSnapshots(request).actionGet(); - mismatchDescription.appendText("snapshot exists"); - return false; - }catch (SnapshotMissingException e) { - return true; - } - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); + client.admin().cluster().getSnapshots(request).actionGet(); + mismatchDescription.appendText("snapshot exists"); + return false; + } catch (SnapshotMissingException e) { + return true; + } + } - @Override - public void describeTo(Description description) { - description.appendText("Snapshot ").appendValue(snapshotName).appendText(" does not exist in repository ") - .appendValue(repositoryName); - } + @Override + public void describeTo(Description description) { + description.appendText("Snapshot ") + .appendValue(snapshotName) + .appendText(" does not exist in repository ") + .appendValue(repositoryName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java index 72cc83491e..7bf4993783 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java @@ -21,27 +21,27 @@ class SuccessBulkResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - RestStatus status = response.status(); - if(RestStatus.OK.equals(status) == false){ - mismatchDescription.appendText("incorrect response status ").appendValue(status); - return false; - } - if(response.hasFailures()) { - String failureDescription = Arrays.stream(response.getItems()) - .filter(BulkItemResponse::isFailed) - .map(BulkItemResponse::getFailure) - .map(Object::toString) - .collect(Collectors.joining(",\n")); - mismatchDescription.appendText("bulk response contains failures ").appendValue(failureDescription); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + RestStatus status = response.status(); + if (RestStatus.OK.equals(status) == false) { + mismatchDescription.appendText("incorrect response status ").appendValue(status); + return false; + } + if (response.hasFailures()) { + String failureDescription = Arrays.stream(response.getItems()) + .filter(BulkItemResponse::isFailed) + .map(BulkItemResponse::getFailure) + .map(Object::toString) + .collect(Collectors.joining(",\n")); + mismatchDescription.appendText("bulk response contains failures ").appendValue(failureDescription); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("success bulk response"); - } + @Override + public void describeTo(Description description) { + description.appendText("success bulk response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java index cc2a11d82b..e27ee17ef6 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java @@ -17,21 +17,21 @@ class SuccessfulClearIndicesCacheResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(ClearIndicesCacheResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.getStatus())) { - mismatchDescription.appendText("Status is equal to ").appendValue(response.getStatus()); - return false; - } - if(response.getShardFailures().length != 0) { - mismatchDescription.appendText("Contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(ClearIndicesCacheResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.getStatus())) { + mismatchDescription.appendText("Status is equal to ").appendValue(response.getStatus()); + return false; + } + if (response.getShardFailures().length != 0) { + mismatchDescription.appendText("Contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful clear index cache response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful clear index cache response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java index beda676540..480b7845e9 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java @@ -16,21 +16,21 @@ class SuccessfulCloseIndexResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(CloseIndexResponse response, Description mismatchDescription) { - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(CloseIndexResponse response, Description mismatchDescription) { + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful close index response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful close index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java index 2a017e0ae0..810c93e034 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java @@ -18,32 +18,34 @@ class SuccessfulCreateIndexResponseMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - - SuccessfulCreateIndexResponseMatcher(String expectedIndexName) { - this.expectedIndexName = requireNonNull(expectedIndexName); - } - - @Override - protected boolean matchesSafely(CreateIndexResponse response, Description mismatchDescription) { - if (!expectedIndexName.equals(response.index())) { - mismatchDescription.appendText("Index name ").appendValue(response.index()) - .appendText(" does not match expected index name ").appendValue(expectedIndexName); - return false; - } - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Successful create index response"); - } + private final String expectedIndexName; + + SuccessfulCreateIndexResponseMatcher(String expectedIndexName) { + this.expectedIndexName = requireNonNull(expectedIndexName); + } + + @Override + protected boolean matchesSafely(CreateIndexResponse response, Description mismatchDescription) { + if (!expectedIndexName.equals(response.index())) { + mismatchDescription.appendText("Index name ") + .appendValue(response.index()) + .appendText(" does not match expected index name ") + .appendValue(expectedIndexName); + return false; + } + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Successful create index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java index 29670334cc..7f9a68064c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java @@ -17,21 +17,21 @@ class SuccessfulCreatePitResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(CreatePitResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - if(response.getShardFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(CreatePitResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + if (response.getShardFailures().length != 0) { + mismatchDescription.appendText("contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful create pit response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful create pit response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java index 0b0c0af09c..aec2e7d61a 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java @@ -18,23 +18,25 @@ class SuccessfulDeletePitResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - for(DeletePitInfo deletePitInfo : response.getDeletePitResults()) { - if (!deletePitInfo.isSuccessful()) { - mismatchDescription.appendValue("Pit: ").appendValue(deletePitInfo.getPitId()).appendText(" - delete result was not successful"); - return false; - } - } - return true; - } + @Override + protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + for (DeletePitInfo deletePitInfo : response.getDeletePitResults()) { + if (!deletePitInfo.isSuccessful()) { + mismatchDescription.appendValue("Pit: ") + .appendValue(deletePitInfo.getPitId()) + .appendText(" - delete result was not successful"); + return false; + } + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful delete pit response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful delete pit response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java index 8d1df13ea9..eb4b1fc064 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java @@ -17,21 +17,23 @@ class SuccessfulDeleteResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(DeleteResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - if(response.getShardInfo().getFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(response.getShardInfo().getFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(DeleteResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + if (response.getShardInfo().getFailures().length != 0) { + mismatchDescription.appendText("contains ") + .appendValue(response.getShardInfo().getFailures().length) + .appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful delete response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful delete response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java index 3aedb0174b..fce5d1201c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java @@ -17,21 +17,23 @@ class SuccessfulMultiGetResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { - for (MultiGetItemResponse getItemResponse : response.getResponses()) { - if (getItemResponse.isFailed()) { - mismatchDescription.appendValue("Get an item from index: ").appendValue(getItemResponse.getIndex()) - .appendText(" failed: ").appendValue(getItemResponse.getFailure().getMessage()); - return false; - } - } + @Override + protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { + for (MultiGetItemResponse getItemResponse : response.getResponses()) { + if (getItemResponse.isFailed()) { + mismatchDescription.appendValue("Get an item from index: ") + .appendValue(getItemResponse.getIndex()) + .appendText(" failed: ") + .appendValue(getItemResponse.getFailure().getMessage()); + return false; + } + } - return true; - } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful multi get response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful multi get response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java index b1dbd64c33..e601f16e8e 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java @@ -16,20 +16,20 @@ class SuccessfulMultiSearchResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { - for (MultiSearchResponse.Item itemResponse : response.getResponses()) { - if (itemResponse.isFailure()) { - mismatchDescription.appendValue("Get an item failed: ").appendValue(itemResponse.getFailureMessage()); - return false; - } - } + @Override + protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { + for (MultiSearchResponse.Item itemResponse : response.getResponses()) { + if (itemResponse.isFailure()) { + mismatchDescription.appendValue("Get an item failed: ").appendValue(itemResponse.getFailureMessage()); + return false; + } + } - return true; - } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful multi search response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful multi search response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java index 3147195474..68389979b1 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java @@ -16,21 +16,21 @@ class SuccessfulOpenIndexResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(OpenIndexResponse response, Description mismatchDescription) { - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(OpenIndexResponse response, Description mismatchDescription) { + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful open index response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful open index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java index c9b5d92b94..915a0f39bb 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java @@ -18,32 +18,34 @@ class SuccessfulResizeResponseMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - - SuccessfulResizeResponseMatcher(String expectedIndexName) { - this.expectedIndexName = requireNonNull(expectedIndexName); - } - - @Override - protected boolean matchesSafely(ResizeResponse response, Description mismatchDescription) { - if (!expectedIndexName.equals(response.index())) { - mismatchDescription.appendText("Index name ").appendValue(response.index()) - .appendText(" does not match expected index name ").appendValue(expectedIndexName); - return false; - } - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Successful create index response"); - } + private final String expectedIndexName; + + SuccessfulResizeResponseMatcher(String expectedIndexName) { + this.expectedIndexName = requireNonNull(expectedIndexName); + } + + @Override + protected boolean matchesSafely(ResizeResponse response, Description mismatchDescription) { + if (!expectedIndexName.equals(response.index())) { + mismatchDescription.appendText("Index name ") + .appendValue(response.index()) + .appendText(" does not match expected index name ") + .appendValue(expectedIndexName); + return false; + } + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Successful create index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java index 6d59780798..fe2acff9b9 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java @@ -17,21 +17,21 @@ class SuccessfulSearchResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - if(RestStatus.OK.equals(searchResponse.status()) == false) { - mismatchDescription.appendText("has status ").appendValue(searchResponse.status()).appendText(" which denotes failure."); - return false; - } - if(searchResponse.getShardFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(searchResponse.getShardFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + if (RestStatus.OK.equals(searchResponse.status()) == false) { + mismatchDescription.appendText("has status ").appendValue(searchResponse.status()).appendText(" which denotes failure."); + return false; + } + if (searchResponse.getShardFailures().length != 0) { + mismatchDescription.appendText("contains ").appendValue(searchResponse.getShardFailures().length).appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful search response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful search response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java index 35a9851055..dcff052f01 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java @@ -17,21 +17,23 @@ class SuccessfulUpdateResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(UpdateResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - if(response.getShardInfo().getFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(response.getShardInfo().getFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(UpdateResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + if (response.getShardInfo().getFailures().length != 0) { + mismatchDescription.appendText("contains ") + .appendValue(response.getShardInfo().getFailures().length) + .appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful update response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful update response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java index 9062d9bb68..ee01fabced 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java @@ -15,9 +15,9 @@ public class UpdateResponseMatchers { - private UpdateResponseMatchers() {} + private UpdateResponseMatchers() {} - public static Matcher isSuccessfulUpdateResponse() { - return new SuccessfulUpdateResponseMatcher(); - } + public static Matcher isSuccessfulUpdateResponse() { + return new SuccessfulUpdateResponseMatcher(); + } } diff --git a/src/test/java/org/opensearch/bootstrap/JarHell.java b/src/test/java/org/opensearch/bootstrap/JarHell.java index 11978a780c..3024a169bc 100644 --- a/src/test/java/org/opensearch/bootstrap/JarHell.java +++ b/src/test/java/org/opensearch/bootstrap/JarHell.java @@ -24,9 +24,16 @@ */ public class JarHell { private JarHell() {} + public static void checkJarHell(Consumer output) throws IOException, Exception {} + public static void checkJarHell(Set urls, Consumer output) throws URISyntaxException, IOException {} + public static void checkVersionFormat(String targetVersion) {} + public static void checkJavaVersion(String resource, String targetVersion) {} - public static Set parseClassPath() {return new HashSet();} + + public static Set parseClassPath() { + return new HashSet(); + } } diff --git a/src/test/java/org/opensearch/node/PluginAwareNode.java b/src/test/java/org/opensearch/node/PluginAwareNode.java index 35dcd8b699..4cd7ff9247 100644 --- a/src/test/java/org/opensearch/node/PluginAwareNode.java +++ b/src/test/java/org/opensearch/node/PluginAwareNode.java @@ -38,11 +38,14 @@ public class PluginAwareNode extends Node { @SafeVarargs public PluginAwareNode(boolean clusterManagerEligible, final Settings preparedSettings, final Class... plugins) { - super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, Collections.emptyMap(), null, () -> System.getenv("HOSTNAME")), Arrays.asList(plugins), true); + super( + InternalSettingsPreparer.prepareEnvironment(preparedSettings, Collections.emptyMap(), null, () -> System.getenv("HOSTNAME")), + Arrays.asList(plugins), + true + ); this.clusterManagerEligible = clusterManagerEligible; } - public boolean isClusterManagerEligible() { return clusterManagerEligible; }