This is an automated email from the ASF dual-hosted git repository.

smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new d99996a87 KNOX-3222: Integrate OpenSearch REST API in Knox (#462) 
(#1131)
d99996a87 is described below

commit d99996a875c7e44e0b386e47aaa03767341f25c0
Author: Tamas Payer <[email protected]>
AuthorDate: Fri Dec 12 13:13:47 2025 +0100

    KNOX-3222: Integrate OpenSearch REST API in Knox (#462) (#1131)
    
    Co-authored-by: Tamas Payer <[email protected]>
---
 .../cm/ClouderaManagerServiceDiscovery.java        |  13 +++-
 ...AbstractOpenSearchApiServiceModelGenerator.java |  31 +++++++++
 .../AbstractOpenSearchServiceModelGenerator.java   |  65 ++++++++++++++++++
 ...nSearchApiCoordinatorServiceModelGenerator.java |  26 +++++++
 .../OpenSearchApiMasterServiceModelGenerator.java  |  44 ++++++++++++
 ...way.topology.discovery.cm.ServiceModelGenerator |   4 +-
 .../discovery/cm/AbstractCMDiscoveryTest.java      |  14 +++-
 ...rchApiCoordinatorServiceModelGeneratorTest.java |  53 ++++++++++++++
 ...enSearchApiMasterServiceModelGeneratorTest.java |  76 +++++++++++++++++++++
 .../services/opensearch/2.18.0/rewrite.xml         |  26 +++++++
 .../services/opensearch/2.18.0/service.xml         |  39 +++++++++++
 .../home/assets/service-logos/opensearch.png       | Bin 0 -> 41480 bytes
 12 files changed, 384 insertions(+), 7 deletions(-)

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 32941d52a..12d4cf789 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.ClusterConfigurationMonitorService;
 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 @@ public class ClouderaManagerServiceDiscovery implements 
ServiceDiscovery, Cluste
         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 @@ public class ClouderaManagerServiceDiscovery implements 
ServiceDiscovery, Cluste
     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 @@ public class ClouderaManagerServiceDiscovery implements 
ServiceDiscovery, Cluste
 
   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 000000000..15a3862e9
--- /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 000000000..f573a5785
--- /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 000000000..0dc5d583d
--- /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 000000000..90f941383
--- /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 1fef3b616..f068eb04a 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.OzoneServiceModelGener
 
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 fa2198c5a..e44ce19de 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 @@ import java.util.Map;
 
 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 000000000..6f5e2d77a
--- /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 000000000..b33a004ca
--- /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 000000000..31b5270e7
--- /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 000000000..f41d3db19
--- /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 000000000..cea8c4e27
Binary files /dev/null and 
b/knox-homepage-ui/home/assets/service-logos/opensearch.png differ

Reply via email to