Skip to content

Commit

Permalink
Updated Remote Client creation, working remote connections
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Widdis <[email protected]>
  • Loading branch information
dbwiddis committed Aug 9, 2024
1 parent 8e4e88a commit f7273b6
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 32 deletions.
10 changes: 6 additions & 4 deletions plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ dependencies {
implementation group: 'org.apache.commons', name: 'commons-text', version: '1.10.0'
implementation 'com.jayway.jsonpath:json-path:2.9.0'

// Java client dependencies
implementation "org.opensearch.client:opensearch-java:2.10.2"
api "org.apache.httpcomponents.client5:httpclient5:5.3.1"
api "org.apache.httpcomponents.core5:httpcore5:5.2.5"

// Dynamo dependencies
implementation("software.amazon.awssdk:sdk-core:2.25.40")
implementation("software.amazon.awssdk:aws-core:2.25.40")
Expand Down Expand Up @@ -184,13 +188,11 @@ integTest {
if (System.getProperty("tests.rest.tenantaware") != null) {
filter {
includeTestsMatching "org.opensearch.ml.rest.*TenantAwareIT"
// mock LLM run in localhost, it will not reachable for docker or remote cluster
excludeTestsMatching "org.opensearch.ml.tools.VisualizationsToolIT"
}
}

// Only rest case can run with remote cluster
if (System.getProperty("tests.rest.cluster") != null) {
if (System.getProperty("tests.rest.cluster") != null && System.getProperty("tests.rest.tenantaware") == null) {
filter {
includeTestsMatching "org.opensearch.ml.rest.*IT"
excludeTestsMatching "org.opensearch.ml.rest.*TenantAwareIT"
Expand Down Expand Up @@ -222,7 +224,7 @@ integTest {
ymlFile.withWriterAppend { writer ->
writer.write("\n# Use a remote cluster\n")
writer.write("plugins.ml_commons.remote_metadata_type: RemoteOpenSearch\n")
writer.write("plugins.ml_commons.remote_metadata_endpoint: http://127.0.0.1\n")
writer.write("plugins.ml_commons.remote_metadata_endpoint: https://127.0.0.1:9200\n")
}
} else {
throw new GradleException("opensearch.yml not found at: $ymlFile")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,9 @@ private void validateRequest4AccessControl(MLCreateConnectorInput input, User us

private void validateSecurityDisabledOrConnectorAccessControlDisabled(MLCreateConnectorInput input) {
if (input.getAccess() != null || input.getAddAllBackendRoles() != null || !CollectionUtils.isEmpty(input.getBackendRoles())) {
// TODO: Get Security Plugin installed and working
// throw new IllegalArgumentException(
// "You cannot specify connector access control parameters because the Security plugin or connector access control is disabled
// on your cluster."
// );
throw new IllegalArgumentException(
"You cannot specify connector access control parameters because the Security plugin or connector access control is disabled on your cluster."
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@
package org.opensearch.ml.sdkclient;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;

import org.apache.http.HttpHost;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.logging.log4j.util.Strings;
import org.opensearch.OpenSearchException;
Expand All @@ -22,6 +30,9 @@
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.aws.AwsSdk2Transport;
import org.opensearch.client.transport.aws.AwsSdk2TransportOptions;
import org.opensearch.client.transport.httpclient5.ApacheHttpClient5Transport;
import org.opensearch.client.transport.httpclient5.ApacheHttpClient5TransportBuilder;
import org.opensearch.client.transport.httpclient5.internal.Node;
import org.opensearch.client.transport.rest_client.RestClientTransport;
import org.opensearch.common.settings.Settings;
import org.opensearch.core.xcontent.NamedXContentRegistry;
Expand All @@ -30,6 +41,8 @@
import org.opensearch.sdk.SdkClientSettings;
import org.opensearch.sdk.client.LocalClusterIndicesClient;

import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
Expand Down Expand Up @@ -114,28 +127,38 @@ private static DynamoDbClient createDynamoDbClient(String region) {

private static OpenSearchClient createOpenSearchClient(String remoteMetadataEndpoint) {
try {
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial((chain, authType) -> true).build();
RestClient restClient = RestClient
// This HttpHost syntax works with export REMOTE_METADATA_ENDPOINT=http://127.0.0.1:9200
.builder(HttpHost.create(remoteMetadataEndpoint))
.setStrictDeprecationMode(true)
Map<String, String> env = System.getenv();
String user = env.getOrDefault("user", "admin");
String pass = env.getOrDefault("password", "admin");
// Endpoint syntax: https://127.0.0.1:9200
HttpHost[] hosts = new HttpHost[] { HttpHost.create(remoteMetadataEndpoint) };
SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(null, (chain, authType) -> true).build();
ApacheHttpClient5Transport transport = ApacheHttpClient5TransportBuilder
.builder(hosts)
.setMapper(
new JacksonJsonpMapper(
new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(new JavaTimeModule())
)
)
.setHttpClientConfigCallback(httpClientBuilder -> {
try {
return httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setSSLContext(sslContext);
} catch (Exception e) {
throw new OpenSearchException(e);
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
for (HttpHost host:hosts) {
credentialsProvider.setCredentials(new AuthScope(host), new UsernamePasswordCredentials(user, pass.toCharArray()));
}
// Disable SSL/TLS verification as our local testing clusters use self-signed certificates
final var tlsStrategy = ClientTlsStrategyBuilder
.create()
.setSslContext(sslContext)
.setHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
final var connectionManager = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(tlsStrategy).build();
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider).setConnectionManager(connectionManager);
})
.build();
ObjectMapper objectMapper = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(new JavaTimeModule());
return new OpenSearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper(objectMapper)));
return new OpenSearchClient(transport);
} catch (Exception e) {
throw new OpenSearchException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import static org.opensearch.ml.common.CommonValue.ML_CONNECTOR_INDEX;
import static org.opensearch.ml.common.CommonValue.TENANT_ID;
import static org.opensearch.ml.common.input.Constants.TENANT_ID_HEADER;
import static org.opensearch.ml.settings.MLCommonsSettings.ML_COMMONS_CONNECTOR_ACCESS_CONTROL_ENABLED;

import java.io.IOException;
import java.util.Collections;
Expand Down Expand Up @@ -75,17 +76,19 @@ public class RestMLConnectorTenantAwareIT extends MLCommonsRestTestCase {

@Before
public void setup() throws IOException {
/*
Response response = TestHelper
.makeRequest(
client(),
"PUT",
"_cluster/settings",
null,
"{\"persistent\":{\"plugins.ml_commons.model_access_control_enabled\":true}}",
"{\"persistent\":{\"" + ML_COMMONS_CONNECTOR_ACCESS_CONTROL_ENABLED.getKey() + "\":true}}",
ImmutableList.of(new BasicHeader(HttpHeaders.USER_AGENT, ""))
);
assertEquals(200, response.getStatusLine().getStatusCode());
// TODO Get secure client access with backend roles properly configured
*/
}

@Test
Expand All @@ -98,7 +101,7 @@ private void testConnectorCRUDMultitenancyEnabled(boolean multiTenancyEnabled) t
enableMultiTenancy(multiTenancyEnabled);

// Create a connector with a tenant id
setFieldsFromRequest(TestHelper.getCreateConnectorRestRequest(tenantId));
setFieldsFromRequest(getRestRequestWithHeadersAndContent(tenantId, getCreateConnectorContent()));

Response response = TestHelper.makeRequest(client(), POST, PATH + "connectors/_create", params, body, headers);
Map<String, Object> map = parseResponseToMap(response);
Expand Down Expand Up @@ -219,7 +222,7 @@ private void testConnectorCRUDMultitenancyEnabled(boolean multiTenancyEnabled) t
}

// Create a second connector using otherTenantId
setFieldsFromRequest(TestHelper.getCreateConnectorRestRequest(otherTenantId));
setFieldsFromRequest(getRestRequestWithHeadersAndContent(otherTenantId, getCreateConnectorContent()));

response = TestHelper.makeRequest(client(), POST, PATH + "connectors/_create", params, body, headers);
map = parseResponseToMap(response);
Expand Down Expand Up @@ -426,4 +429,36 @@ private static RestRequest getRestRequestWithHeadersAndContent(String tenantId,
.build();
return request;
}

private static String getCreateConnectorContent() {
return "{\n"
+ " \"name\": \"OpenAI Connector\",\n"
+ " \"description\": \"The connector to public OpenAI model service for GPT 3.5\",\n"
+ " \"version\": 1,\n"
+ " \"protocol\": \"http\",\n"
+ " \"parameters\": {\n"
+ " \"endpoint\": \"api.openai.com\",\n"
+ " \"auth\": \"API_Key\",\n"
+ " \"content_type\": \"application/json\",\n"
+ " \"max_tokens\": 7,\n"
+ " \"temperature\": 0,\n"
+ " \"model\": \"gpt-3.5-turbo-instruct\"\n"
+ " },\n"
+ " \"credential\": {\n"
+ " \"openAI_key\": \"xxxxxxxx\"\n"
+ " },\n"
+ " \"actions\": [\n"
+ " {\n"
+ " \"action_type\": \"predict\",\n"
+ " \"method\": \"POST\",\n"
+ " \"url\": \"https://${parameters.endpoint}/v1/completions\",\n"
+ " \"headers\": {\n"
+ " \"Authorization\": \"Bearer ${credential.openAI_key}\"\n"
+ " },\n"
+ " \"request_body\": \"{ \\\"model\\\": \\\"${parameters.model}\\\", \\\"prompt\\\": \\\"${parameters.prompt}\\\", \\\"max_tokens\\\": ${parameters.max_tokens}, \\\"temperature\\\": ${parameters.temperature} }\"\n"
+ " }\n"
+ " ]" // ,\n"
// + " \"access_mode\": \"public\"\n"
+ "}";
}
}

0 comments on commit f7273b6

Please sign in to comment.