KNOX-3222: Integrate OpenSearch REST API in Knox (#462) (#1131)
Co-authored-by: Tamas Payer <tpayer@cloudera.com>
diff --git a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscovery.java b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscovery.java
index 32941d5..12d4cf7 100644
--- a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscovery.java
+++ b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/ClouderaManagerServiceDiscovery.java
@@ -39,6 +39,7 @@
import org.apache.knox.gateway.topology.discovery.ClusterConfigurationMonitor;
import org.apache.knox.gateway.topology.discovery.ServiceDiscovery;
import org.apache.knox.gateway.topology.discovery.ServiceDiscoveryConfig;
+import org.apache.knox.gateway.topology.discovery.cm.model.opensearch.OpenSearchApiMasterServiceModelGenerator;
import org.apache.knox.gateway.topology.discovery.cm.monitor.ClouderaManagerClusterConfigurationMonitor;
import java.net.SocketException;
@@ -317,7 +318,7 @@
ServiceRoleDetails serviceRoleDetails = new ServiceRoleDetails(service, serviceConfig, role, roleConfigs);
log.discoveringServiceRole(role.getName(), role.getType());
- Set<ServiceModel> modelsForRole = generateServiceModels(client, serviceRoleDetails, coreSettingsConfig, modelGenerators);
+ Set<ServiceModel> modelsForRole = generateServiceModels(client, serviceRoleDetails, coreSettingsConfig, modelGenerators, roleConfigList);
log.discoveredServiceRole(role.getName(), role.getType());
@@ -331,11 +332,17 @@
return serviceModels;
}
- private Set<ServiceModel> generateServiceModels(DiscoveryApiClient client, ServiceRoleDetails serviceRoleDetails, ApiServiceConfig coreSettingsConfig, List<ServiceModelGenerator> modelGenerators) throws ApiException {
+ private Set<ServiceModel> generateServiceModels(DiscoveryApiClient client, ServiceRoleDetails serviceRoleDetails,
+ ApiServiceConfig coreSettingsConfig, List<ServiceModelGenerator> modelGenerators,
+ ApiRoleConfigList roleConfigList) throws ApiException {
Set<ServiceModel> serviceModels = new HashSet<>();
if (modelGenerators != null) {
for (ServiceModelGenerator serviceModelGenerator : modelGenerators) {
+ if (OpenSearchApiMasterServiceModelGenerator.shouldSkipGeneratorWhenOpenSearchMaster(serviceModelGenerator, roleConfigList)) {
+ continue;
+ }
+
ServiceModel serviceModel = generateServiceModel(client, serviceRoleDetails, coreSettingsConfig, serviceModelGenerator);
if (serviceModel != null) {
serviceModels.add(serviceModel);
@@ -348,9 +355,9 @@
private static ServiceModel generateServiceModel(DiscoveryApiClient client, ServiceRoleDetails sd,
ApiServiceConfig coreSettingsConfig, ServiceModelGenerator serviceModelGenerator) throws ApiException {
+ serviceModelGenerator.setApiClient(client);
ServiceModelGeneratorHandleResponse response = serviceModelGenerator.handles(sd.getService(), sd.getServiceConfig(), sd.getRole(), sd.getRoleConfig());
if (response.handled()) {
- serviceModelGenerator.setApiClient(client);
return serviceModelGenerator.generateService(sd.getService(), sd.getServiceConfig(), sd.getRole(), sd.getRoleConfig(), coreSettingsConfig);
} else if (!response.getConfigurationIssues().isEmpty()) {
log.serviceRoleHasConfigurationIssues(sd.getRole().getName(), String.join(";", response.getConfigurationIssues()));
diff --git a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/AbstractOpenSearchApiServiceModelGenerator.java b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/AbstractOpenSearchApiServiceModelGenerator.java
new file mode 100644
index 0000000..15a3862
--- /dev/null
+++ b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/AbstractOpenSearchApiServiceModelGenerator.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.cm.model.opensearch;
+
+import org.apache.knox.gateway.topology.discovery.cm.ServiceModel;
+
+public abstract class AbstractOpenSearchApiServiceModelGenerator extends AbstractOpenSearchServiceModelGenerator {
+ @Override
+ public ServiceModel.Type getModelType() {
+ return ServiceModel.Type.API;
+ }
+
+ @Override
+ protected String getPortConfigName() {
+ return "opensearch_http_port";
+ }
+}
diff --git a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/AbstractOpenSearchServiceModelGenerator.java b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/AbstractOpenSearchServiceModelGenerator.java
new file mode 100644
index 0000000..f573a57
--- /dev/null
+++ b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/AbstractOpenSearchServiceModelGenerator.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.cm.model.opensearch;
+
+import com.cloudera.api.swagger.client.ApiException;
+import com.cloudera.api.swagger.model.ApiConfigList;
+import com.cloudera.api.swagger.model.ApiRole;
+import com.cloudera.api.swagger.model.ApiService;
+import com.cloudera.api.swagger.model.ApiServiceConfig;
+import org.apache.knox.gateway.topology.discovery.cm.ServiceModel;
+import org.apache.knox.gateway.topology.discovery.cm.model.AbstractServiceModelGenerator;
+
+import java.util.Locale;
+
+public abstract class AbstractOpenSearchServiceModelGenerator extends AbstractServiceModelGenerator {
+ public static final String SERVICE = "OPENSEARCH";
+ public static final String SERVICE_TYPE = "OPENSEARCH";
+
+ @Override
+ public String getService() {
+ return SERVICE;
+ }
+
+ @Override
+ public String getServiceType() {
+ return SERVICE_TYPE;
+ }
+
+ protected String getSSLEnabledConfigName() {
+ return "ssl_enabled";
+ }
+
+ protected abstract String getPortConfigName();
+
+ @Override
+ public ServiceModel generateService(ApiService service, ApiServiceConfig serviceConfig, ApiRole role,
+ ApiConfigList roleConfig, ApiServiceConfig coreSettingsConfig) throws ApiException {
+ final String hostname = role.getHostRef().getHostname();
+ final String port = getRoleConfigValue(roleConfig, getPortConfigName());
+ final String sslEnabled = getRoleConfigValue(roleConfig, getSSLEnabledConfigName());
+
+ final String scheme = Boolean.parseBoolean(sslEnabled) ? "https" : "http";
+ final String url = String.format(Locale.getDefault(), "%s://%s:%s", scheme, hostname, port);
+
+ final ServiceModel model = createServiceModel(url);
+ model.addRoleProperty(getRoleType(), getPortConfigName(), port);
+ model.addRoleProperty(getRoleType(), getSSLEnabledConfigName(), sslEnabled);
+
+ return model;
+ }
+}
diff --git a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiCoordinatorServiceModelGenerator.java b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiCoordinatorServiceModelGenerator.java
new file mode 100644
index 0000000..0dc5d58
--- /dev/null
+++ b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiCoordinatorServiceModelGenerator.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.cm.model.opensearch;
+
+public class OpenSearchApiCoordinatorServiceModelGenerator extends AbstractOpenSearchApiServiceModelGenerator {
+ static final String OPENSEARCH_COORDINATOR_ROLE_TYPE = "OPENSEARCH_COORDINATOR";
+
+ @Override
+ public String getRoleType() {
+ return OPENSEARCH_COORDINATOR_ROLE_TYPE;
+ }
+}
diff --git a/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiMasterServiceModelGenerator.java b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiMasterServiceModelGenerator.java
new file mode 100644
index 0000000..90f9413
--- /dev/null
+++ b/gateway-discovery-cm/src/main/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiMasterServiceModelGenerator.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.cm.model.opensearch;
+
+import com.cloudera.api.swagger.model.ApiRoleConfigList;
+import org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator;
+
+public class OpenSearchApiMasterServiceModelGenerator extends AbstractOpenSearchApiServiceModelGenerator {
+ static final String OPENSEARCH_MASTER_ROLE_TYPE = "OPENSEARCH_MASTER";
+
+ @Override
+ public String getRoleType() {
+ return OPENSEARCH_MASTER_ROLE_TYPE;
+ }
+
+ /**
+ * If here is an OPENSEARCH_COORDINATOR role for this service o not generate service model for
+ * OPENSEARCH_MASTER role because OPENSEARCH_COORDINATOR is the preferred REST API target.
+ * @param serviceModelGenerator the actual model generator
+ * @param roles all the roles of the service
+ * @return <code>true</code> if <code>serviceModelGenerator</code> is for OpenSearch Master and there are Coordinator roles in the cluster.
+ */
+ public static boolean shouldSkipGeneratorWhenOpenSearchMaster(ServiceModelGenerator serviceModelGenerator, ApiRoleConfigList roles) {
+ if (!AbstractOpenSearchServiceModelGenerator.SERVICE_TYPE.equals(serviceModelGenerator.getServiceType())
+ || !OpenSearchApiMasterServiceModelGenerator.OPENSEARCH_MASTER_ROLE_TYPE.equals(serviceModelGenerator.getRoleType())) {
+ return false;
+ }
+ return roles.getItems().stream().anyMatch(r -> r.getRoleType().equals(OpenSearchApiCoordinatorServiceModelGenerator.OPENSEARCH_COORDINATOR_ROLE_TYPE));
+ }
+}
diff --git a/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator b/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator
index 1fef3b6..f068eb0 100644
--- a/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator
+++ b/gateway-discovery-cm/src/main/resources/META-INF/services/org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator
@@ -61,5 +61,5 @@
org.apache.knox.gateway.topology.discovery.cm.model.ozone.ReconServiceModelGenerator
org.apache.knox.gateway.topology.discovery.cm.model.ozone.SCMServiceModelGenerator
org.apache.knox.gateway.topology.discovery.cm.model.ozone.OzoneHttpfsServiceModelGenerator
-
-
+org.apache.knox.gateway.topology.discovery.cm.model.opensearch.OpenSearchApiCoordinatorServiceModelGenerator
+org.apache.knox.gateway.topology.discovery.cm.model.opensearch.OpenSearchApiMasterServiceModelGenerator
diff --git a/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/AbstractCMDiscoveryTest.java b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/AbstractCMDiscoveryTest.java
index fa2198c..e44ce19 100644
--- a/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/AbstractCMDiscoveryTest.java
+++ b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/AbstractCMDiscoveryTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.knox.gateway.topology.discovery.cm;
+import com.cloudera.api.swagger.model.ApiClusterRef;
import com.cloudera.api.swagger.model.ApiConfig;
import com.cloudera.api.swagger.model.ApiConfigList;
import com.cloudera.api.swagger.model.ApiHostRef;
@@ -30,17 +31,26 @@
public class AbstractCMDiscoveryTest {
protected static ApiService createApiServiceMock(final String serviceType) {
- return createApiServiceMock(serviceType + "-1", serviceType);
+ ApiClusterRef clusterRefMock = createApiClusterRefMock("Cluster 1");
+ return createApiServiceMock(serviceType + "-1", serviceType, clusterRefMock);
}
- protected static ApiService createApiServiceMock(final String serviceName, final String serviceType) {
+ protected static ApiService createApiServiceMock(final String serviceName, final String serviceType, final ApiClusterRef clusterRef) {
ApiService service = EasyMock.createNiceMock(ApiService.class);
EasyMock.expect(service.getName()).andReturn(serviceName).anyTimes();
EasyMock.expect(service.getType()).andReturn(serviceType).anyTimes();
+ EasyMock.expect(service.getClusterRef()).andReturn(clusterRef).anyTimes();
EasyMock.replay(service);
return service;
}
+ protected static ApiClusterRef createApiClusterRefMock(final String clusterName) {
+ ApiClusterRef clusterRef = EasyMock.createNiceMock(ApiClusterRef.class);
+ EasyMock.expect(clusterRef.getClusterName()).andReturn(clusterName).anyTimes();
+ EasyMock.replay(clusterRef);
+ return clusterRef;
+ }
+
protected static ApiServiceConfig createApiServiceConfigMock(Map<String, String> configProps) {
ApiServiceConfig serviceConfig = EasyMock.createNiceMock(ApiServiceConfig.class);
EasyMock.expect(serviceConfig.getItems()).andReturn(createMockApiConfigs(configProps)).anyTimes();
diff --git a/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiCoordinatorServiceModelGeneratorTest.java b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiCoordinatorServiceModelGeneratorTest.java
new file mode 100644
index 0000000..6f5e2d7
--- /dev/null
+++ b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiCoordinatorServiceModelGeneratorTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.cm.model.opensearch;
+
+import org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator;
+import org.apache.knox.gateway.topology.discovery.cm.model.AbstractServiceModelGeneratorTest;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class OpenSearchApiCoordinatorServiceModelGeneratorTest extends AbstractServiceModelGeneratorTest {
+
+ @Test
+ public void testServiceModelMetadata() {
+ final Map<String, String> serviceConfig = Collections.emptyMap();
+ final Map<String, String> roleConfig = new HashMap<>();
+ roleConfig.put("ssl_enabled", "true");
+ roleConfig.put("opensearch_http_port", "9202");
+
+ validateServiceModel(createServiceModel(serviceConfig, roleConfig), serviceConfig, roleConfig);
+ }
+
+ @Override
+ protected String getServiceType() {
+ return OpenSearchApiCoordinatorServiceModelGenerator.SERVICE_TYPE;
+ }
+
+ @Override
+ protected String getRoleType() {
+ return OpenSearchApiCoordinatorServiceModelGenerator.OPENSEARCH_COORDINATOR_ROLE_TYPE;
+ }
+
+ @Override
+ protected ServiceModelGenerator newGenerator() {
+ return new OpenSearchApiCoordinatorServiceModelGenerator();
+ }
+}
diff --git a/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiMasterServiceModelGeneratorTest.java b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiMasterServiceModelGeneratorTest.java
new file mode 100644
index 0000000..b33a004
--- /dev/null
+++ b/gateway-discovery-cm/src/test/java/org/apache/knox/gateway/topology/discovery/cm/model/opensearch/OpenSearchApiMasterServiceModelGeneratorTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.cm.model.opensearch;
+
+import com.cloudera.api.swagger.model.ApiRoleConfig;
+import com.cloudera.api.swagger.model.ApiRoleConfigList;
+import org.apache.knox.gateway.topology.discovery.cm.ServiceModelGenerator;
+import org.apache.knox.gateway.topology.discovery.cm.model.AbstractServiceModelGeneratorTest;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertTrue;
+
+public class OpenSearchApiMasterServiceModelGeneratorTest extends AbstractServiceModelGeneratorTest {
+
+ @Test
+ public void testServiceModelMetadata() {
+ final Map<String, String> serviceConfig = Collections.emptyMap();
+ final Map<String, String> roleConfig = new HashMap<>();
+ roleConfig.put("ssl_enabled", "true");
+ roleConfig.put("opensearch_http_port", "9200");
+
+ validateServiceModel(createServiceModel(serviceConfig, roleConfig), serviceConfig, roleConfig);
+ }
+
+ @Override
+ protected String getServiceType() {
+ return OpenSearchApiMasterServiceModelGenerator.SERVICE_TYPE;
+ }
+
+ @Override
+ protected String getRoleType() {
+ return OpenSearchApiMasterServiceModelGenerator.OPENSEARCH_MASTER_ROLE_TYPE;
+ }
+
+ @Override
+ protected ServiceModelGenerator newGenerator() {
+ return new OpenSearchApiMasterServiceModelGenerator();
+ }
+
+ @Test
+ public void testSkipGeneratorWhenOpenSearchMaster() {
+ final ApiRoleConfig masterRole = EasyMock.createNiceMock(ApiRoleConfig.class);
+ EasyMock.expect(masterRole.getRoleType()).andReturn(OpenSearchApiMasterServiceModelGenerator.OPENSEARCH_MASTER_ROLE_TYPE).anyTimes();
+ EasyMock.replay(masterRole);
+
+ final ApiRoleConfig coordinatorRole = EasyMock.createNiceMock(ApiRoleConfig.class);
+ EasyMock.expect(coordinatorRole.getRoleType()).andReturn(OpenSearchApiCoordinatorServiceModelGenerator.OPENSEARCH_COORDINATOR_ROLE_TYPE).anyTimes();
+ EasyMock.replay(coordinatorRole);
+
+ final ApiRoleConfigList serviceRoleConfigs = EasyMock.createNiceMock(ApiRoleConfigList.class);
+ EasyMock.expect(serviceRoleConfigs.getItems()).andReturn(Arrays.asList(masterRole, coordinatorRole)).anyTimes();
+ EasyMock.replay(serviceRoleConfigs);
+
+ assertTrue(OpenSearchApiMasterServiceModelGenerator.shouldSkipGeneratorWhenOpenSearchMaster(newGenerator(), serviceRoleConfigs));
+ }
+}
diff --git a/gateway-service-definitions/src/main/resources/services/opensearch/2.18.0/rewrite.xml b/gateway-service-definitions/src/main/resources/services/opensearch/2.18.0/rewrite.xml
new file mode 100644
index 0000000..31b5270
--- /dev/null
+++ b/gateway-service-definitions/src/main/resources/services/opensearch/2.18.0/rewrite.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<rules>
+ <rule dir="IN" name="OPENSEARCH/opensearch/inbound/root" pattern="*://*:*/**/opensearch/">
+ <rewrite template="{$serviceUrl[OPENSEARCH]}/"/>
+ </rule>
+ <rule dir="IN" name="OPENSEARCH/opensearch/inbound/path" pattern="*://*:*/**/opensearch/{path=**}?{**}">
+ <rewrite template="{$serviceUrl[OPENSEARCH]}/{path=**}?{**}"/>
+ </rule>
+</rules>
+
diff --git a/gateway-service-definitions/src/main/resources/services/opensearch/2.18.0/service.xml b/gateway-service-definitions/src/main/resources/services/opensearch/2.18.0/service.xml
new file mode 100644
index 0000000..f41d3db
--- /dev/null
+++ b/gateway-service-definitions/src/main/resources/services/opensearch/2.18.0/service.xml
@@ -0,0 +1,39 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<service role="OPENSEARCH" name="opensearch" version="2.18.0">
+ <metadata>
+ <type>API</type>
+ <context>/opensearch</context>
+ <shortDesc>OpenSearch REST API</shortDesc>
+ <description>OpenSearch is an open source, enterprise-grade search and observability suite.</description>
+ </metadata>
+ <routes>
+ <route path="/opensearch"/>
+ <route path="/opensearch/**"/>
+ </routes>
+ <dispatch classname="org.apache.knox.gateway.dispatch.ConfigurableDispatch"
+ ha-classname="org.apache.knox.gateway.ha.dispatch.ConfigurableHADispatch">
+ <param>
+ <name>shouldIncludePrincipalAndGroups</name>
+ <value>true</value>
+ </param>
+ <param>
+ <name>actorIdHeaderName</name>
+ <value>opendistro_security_impersonate_as</value>
+ </param>
+ </dispatch>
+</service>
diff --git a/knox-homepage-ui/home/assets/service-logos/opensearch.png b/knox-homepage-ui/home/assets/service-logos/opensearch.png
new file mode 100644
index 0000000..cea8c4e
--- /dev/null
+++ b/knox-homepage-ui/home/assets/service-logos/opensearch.png
Binary files differ