diff --git a/docs/configs/docsdev.js b/docs/configs/docsdev.js index 6c63f157df..49c05f87f5 100644 --- a/docs/configs/docsdev.js +++ b/docs/configs/docsdev.js @@ -347,6 +347,10 @@ export default { title: 'Databend', link: '/en-us/docs/dev/user_doc/guide/datasource/databend.html', }, + { + title: 'HANA', + link: '/en-us/docs/dev/user_doc/guide/datasource/hana.html', + } ], }, { @@ -1044,6 +1048,10 @@ export default { title: 'Databend', link: '/zh-cn/docs/dev/user_doc/guide/datasource/databend.html', }, + { + title: 'HANA', + link: '/zh-cn/docs/dev/user_doc/guide/datasource/hana.html', + } ], }, { diff --git a/docs/docs/en/guide/datasource/hana.md b/docs/docs/en/guide/datasource/hana.md new file mode 100644 index 0000000000..28912801f9 --- /dev/null +++ b/docs/docs/en/guide/datasource/hana.md @@ -0,0 +1,22 @@ +# HANA + +![hana](../../../../img/new_ui/dev/datasource/hana.png) + +## Datasource Parameters + +| **Datasource** | **Description** | +|----------------------------|---------------------------------------------------------| +| Datasource | Select HANA. | +| Datasource name | Enter the name of the DataSource. | +| Description | Enter a description of the DataSource. | +| IP/Host Name | Enter the HANA service IP. | +| Port | Enter the HANA service port. | +| Username | Set the username for HANA connection. | +| Password | Set the password for HANA connection. | +| Database name | Enter the database name of the HANA connection. | +| Jdbc connection parameters | Parameter settings for HANA connection, in JSON format. | + +## Native Supported + +No, read section example in [datasource-setting](../howto/datasource-setting.md) `DataSource Center` section to activate this datasource. + diff --git a/docs/docs/zh/guide/datasource/hana.md b/docs/docs/zh/guide/datasource/hana.md new file mode 100644 index 0000000000..12c17b6ffd --- /dev/null +++ b/docs/docs/zh/guide/datasource/hana.md @@ -0,0 +1,17 @@ +# HANA 数据源 + +![hana](../../../../img/new_ui/dev/datasource/hana.png) + +- 数据源:选择 HANA +- 数据源名称:输入数据源的名称 +- 描述:输入数据源的描述 +- IP 主机名:输入连接 HANA 的 IP +- 端口:输入连接 HANA 的端口 +- 用户名:设置连接 HANA 的用户名 +- 密码:设置连接 HANA 的密码 +- 数据库名:输入连接 HANA 的数据库名称 +- Jdbc 连接参数:用于 HANA 连接的参数设置,以 JSON 形式填写 + +## 是否原生支持 + +否,使用前需请参考 [数据源配置](../howto/datasource-setting.md) 中的 "数据源中心" 章节激活数据源。 diff --git a/docs/img/new_ui/dev/datasource/hana.png b/docs/img/new_ui/dev/datasource/hana.png new file mode 100644 index 0000000000..eb03058737 Binary files /dev/null and b/docs/img/new_ui/dev/datasource/hana.png differ diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/DataSourceConstants.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/DataSourceConstants.java index 9e7a378307..4c1c3e30ac 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/DataSourceConstants.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/DataSourceConstants.java @@ -42,6 +42,8 @@ public class DataSourceConstants { public static final String COM_OCEANBASE_JDBC_DRIVER = "com.oceanbase.jdbc.Driver"; public static final String NET_SNOWFLAKE_JDBC_DRIVER = "net.snowflake.client.jdbc.SnowflakeDriver"; public static final String COM_VERTICA_JDBC_DRIVER = "com.vertica.jdbc.Driver"; + public static final String COM_HANA_DB_JDBC_DRIVER = "com.sap.db.jdbc.Driver"; + /** * validation Query */ @@ -63,6 +65,8 @@ public class DataSourceConstants { public static final String KYUUBI_VALIDATION_QUERY = "select 1"; public static final String VERTICA_VALIDATION_QUERY = "select 1"; + public static final String HANA_VALIDATION_QUERY = "select 1"; + /** * jdbc url */ @@ -85,6 +89,7 @@ public class DataSourceConstants { public static final String JDBC_OCEANBASE = "jdbc:oceanbase://"; public static final String JDBC_SNOWFLAKE = "jdbc:snowflake://"; public static final String JDBC_VERTICA = "jdbc:vertica://"; + public static final String JDBC_HANA = "jdbc:sap://"; /** * database type diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannel.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannel.java new file mode 100644 index 0000000000..9952ee4316 --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannel.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.dolphinscheduler.plugin.datasource.hana; + +import org.apache.dolphinscheduler.spi.datasource.BaseConnectionParam; +import org.apache.dolphinscheduler.spi.datasource.DataSourceChannel; +import org.apache.dolphinscheduler.spi.datasource.DataSourceClient; +import org.apache.dolphinscheduler.spi.enums.DbType; + +public class HanaDataSourceChannel implements DataSourceChannel { + + @Override + public DataSourceClient createDataSourceClient(BaseConnectionParam baseConnectionParam, DbType dbType) { + return new HanaDataSourceClient(baseConnectionParam, dbType); + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelFactory.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelFactory.java new file mode 100644 index 0000000000..75aacebaff --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelFactory.java @@ -0,0 +1,37 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana; + +import org.apache.dolphinscheduler.spi.datasource.DataSourceChannel; +import org.apache.dolphinscheduler.spi.datasource.DataSourceChannelFactory; + +import com.google.auto.service.AutoService; + +@AutoService(DataSourceChannelFactory.class) +public class HanaDataSourceChannelFactory implements DataSourceChannelFactory { + + @Override + public String getName() { + return "hana"; + } + + @Override + public DataSourceChannel create() { + return new HanaDataSourceChannel(); + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceClient.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceClient.java new file mode 100644 index 0000000000..72806e42df --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceClient.java @@ -0,0 +1,30 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana; + +import org.apache.dolphinscheduler.plugin.datasource.api.client.CommonDataSourceClient; +import org.apache.dolphinscheduler.spi.datasource.BaseConnectionParam; +import org.apache.dolphinscheduler.spi.enums.DbType; + +public class HanaDataSourceClient extends CommonDataSourceClient { + + public HanaDataSourceClient(BaseConnectionParam baseConnectionParam, DbType dbType) { + super(baseConnectionParam, dbType); + } + +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaConnectionParam.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaConnectionParam.java new file mode 100644 index 0000000000..6236e71cc8 --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaConnectionParam.java @@ -0,0 +1,38 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana.param; + +import org.apache.dolphinscheduler.spi.datasource.BaseConnectionParam; + +public class HanaConnectionParam extends BaseConnectionParam { + + @Override + public String toString() { + return "HanaConnectionParam{" + + "user='" + user + '\'' + + ", password='" + password + '\'' + + ", address='" + address + '\'' + + ", database='" + database + '\'' + + ", jdbcUrl='" + jdbcUrl + '\'' + + ", driverLocation='" + driverLocation + '\'' + + ", driverClassName='" + driverClassName + '\'' + + ", validationQuery='" + validationQuery + '\'' + + ", other='" + other + '\'' + + '}'; + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceParamDTO.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceParamDTO.java new file mode 100644 index 0000000000..294450250f --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceParamDTO.java @@ -0,0 +1,43 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana.param; + +import org.apache.dolphinscheduler.plugin.datasource.api.datasource.BaseDataSourceParamDTO; +import org.apache.dolphinscheduler.spi.enums.DbType; + +public class HanaDataSourceParamDTO extends BaseDataSourceParamDTO { + + @Override + public String toString() { + return "HanaDataSourceParamDTO{" + + "name='" + name + '\'' + + ", note='" + note + '\'' + + ", host='" + host + '\'' + + ", port=" + port + + ", database='" + database + '\'' + + ", userName='" + userName + '\'' + + ", password='" + password + '\'' + + ", other='" + other + '\'' + + '}'; + } + + @Override + public DbType getType() { + return DbType.HANA; + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceProcessor.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceProcessor.java new file mode 100644 index 0000000000..5c5da73aab --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/main/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceProcessor.java @@ -0,0 +1,130 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana.param; + +import org.apache.dolphinscheduler.common.constants.Constants; +import org.apache.dolphinscheduler.common.constants.DataSourceConstants; +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.plugin.datasource.api.datasource.AbstractDataSourceProcessor; +import org.apache.dolphinscheduler.plugin.datasource.api.datasource.BaseDataSourceParamDTO; +import org.apache.dolphinscheduler.plugin.datasource.api.datasource.DataSourceProcessor; +import org.apache.dolphinscheduler.plugin.datasource.api.utils.PasswordUtils; +import org.apache.dolphinscheduler.spi.datasource.BaseConnectionParam; +import org.apache.dolphinscheduler.spi.datasource.ConnectionParam; +import org.apache.dolphinscheduler.spi.enums.DbType; + +import org.apache.commons.collections4.MapUtils; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.auto.service.AutoService; +@AutoService(DataSourceProcessor.class) +public class HanaDataSourceProcessor extends AbstractDataSourceProcessor { + + private final Logger logger = LoggerFactory.getLogger(HanaDataSourceProcessor.class); + + private static final String APPEND_PARAMS = "reconnect=true"; + @Override + public BaseDataSourceParamDTO castDatasourceParamDTO(String paramJson) { + return JSONUtils.parseObject(paramJson, HanaDataSourceParamDTO.class); + } + + @Override + public BaseDataSourceParamDTO createDatasourceParamDTO(String connectionJson) { + HanaConnectionParam connectionParams = (HanaConnectionParam) createConnectionParams(connectionJson); + HanaDataSourceParamDTO mysqlDatasourceParamDTO = new HanaDataSourceParamDTO(); + mysqlDatasourceParamDTO.setUserName(connectionParams.getUser()); + mysqlDatasourceParamDTO.setDatabase(connectionParams.getDatabase()); + String address = connectionParams.getAddress(); + String[] hostSeperator = address.split(Constants.DOUBLE_SLASH); + String[] hostPortArray = hostSeperator[hostSeperator.length - 1].split(Constants.COMMA); + mysqlDatasourceParamDTO.setPort(Integer.parseInt(hostPortArray[0].split(Constants.COLON)[1])); + mysqlDatasourceParamDTO.setHost(hostPortArray[0].split(Constants.COLON)[0]); + + return mysqlDatasourceParamDTO; + } + + @Override + public BaseConnectionParam createConnectionParams(BaseDataSourceParamDTO dataSourceParam) { + HanaDataSourceParamDTO hanaDatasourceParam = (HanaDataSourceParamDTO) dataSourceParam; + String address = String.format("%s%s:%s", DataSourceConstants.JDBC_HANA, hanaDatasourceParam.getHost(), + hanaDatasourceParam.getPort()); + String jdbcUrl = String.format("%s?currentschema=%s", address, hanaDatasourceParam.getDatabase()); + + HanaConnectionParam hanaConnectionParam = new HanaConnectionParam(); + hanaConnectionParam.setJdbcUrl(jdbcUrl); + hanaConnectionParam.setValidationQuery("select 1 from DUMMY"); + hanaConnectionParam.setDatabase(hanaDatasourceParam.getDatabase()); + hanaConnectionParam.setAddress(address); + hanaConnectionParam.setUser(hanaDatasourceParam.getUserName()); + hanaConnectionParam.setPassword(PasswordUtils.encodePassword(hanaDatasourceParam.getPassword())); + hanaConnectionParam.setDriverClassName(getDatasourceDriver()); + hanaConnectionParam.setOther(hanaDatasourceParam.getOther()); + + return hanaConnectionParam; + } + + @Override + public ConnectionParam createConnectionParams(String connectionJson) { + return JSONUtils.parseObject(connectionJson, HanaConnectionParam.class); + } + + @Override + public String getDatasourceDriver() { + return DataSourceConstants.COM_HANA_DB_JDBC_DRIVER; + } + + @Override + public String getValidationQuery() { + return DataSourceConstants.COM_HANA_DB_JDBC_DRIVER; + } + + @Override + public String getJdbcUrl(ConnectionParam connectionParam) { + HanaConnectionParam hanaConnectionParam = (HanaConnectionParam) connectionParam; + String jdbcUrl = hanaConnectionParam.getJdbcUrl(); + if (MapUtils.isNotEmpty(hanaConnectionParam.getOther())) { + return String.format("%s?%s&%s", jdbcUrl, hanaConnectionParam.getOther(), APPEND_PARAMS); + } + return String.format("%s&%s", jdbcUrl, APPEND_PARAMS); + } + + @Override + public Connection getConnection(ConnectionParam connectionParam) throws ClassNotFoundException, SQLException { + HanaConnectionParam mysqlConnectionParam = (HanaConnectionParam) connectionParam; + Class.forName(getDatasourceDriver()); + String user = mysqlConnectionParam.getUser(); + String password = PasswordUtils.decodePassword(mysqlConnectionParam.getPassword()); + return DriverManager.getConnection(getJdbcUrl(connectionParam), user, password); + } + + @Override + public DbType getDbType() { + return DbType.HANA; + } + + @Override + public DataSourceProcessor create() { + return new HanaDataSourceProcessor(); + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelFactoryTest.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelFactoryTest.java new file mode 100644 index 0000000000..089b203f50 --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelFactoryTest.java @@ -0,0 +1,32 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana; + +import org.apache.dolphinscheduler.spi.datasource.DataSourceChannel; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class HanaDataSourceChannelFactoryTest { + + @Test + public void testCreate() { + HanaDataSourceChannelFactory sourceChannelFactory = new HanaDataSourceChannelFactory(); + DataSourceChannel dataSourceChannel = sourceChannelFactory.create(); + Assertions.assertNotNull(dataSourceChannel); + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelTest.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelTest.java new file mode 100644 index 0000000000..e60e3bfc81 --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/HanaDataSourceChannelTest.java @@ -0,0 +1,38 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana; + +import org.apache.dolphinscheduler.plugin.datasource.hana.param.HanaConnectionParam; +import org.apache.dolphinscheduler.spi.enums.DbType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class HanaDataSourceChannelTest { + + @Test + public void testCreateDataSourceClient() { + HanaDataSourceChannel sourceChannel = Mockito.mock(HanaDataSourceChannel.class); + HanaDataSourceClient dataSourceClient = Mockito.mock(HanaDataSourceClient.class); + Mockito.when(sourceChannel.createDataSourceClient(Mockito.any(), Mockito.any())).thenReturn(dataSourceClient); + Assertions.assertNotNull(sourceChannel.createDataSourceClient(new HanaConnectionParam(), DbType.HANA)); + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceProcessorTest.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceProcessorTest.java new file mode 100644 index 0000000000..8f6095b3b5 --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/param/HanaDataSourceProcessorTest.java @@ -0,0 +1,105 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana.param; + +import org.apache.dolphinscheduler.common.constants.DataSourceConstants; +import org.apache.dolphinscheduler.plugin.datasource.api.utils.PasswordUtils; +import org.apache.dolphinscheduler.spi.enums.DbType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.HashMap; +import java.util.Map; + +@ExtendWith(MockitoExtension.class) +public class HanaDataSourceProcessorTest { + + private HanaDataSourceProcessor hanaDataSourceProcessor = new HanaDataSourceProcessor(); + + @Test + public void testCreateConnectionParams() { + Map props = new HashMap<>(); + HanaDataSourceParamDTO mysqlDatasourceParamDTO = new HanaDataSourceParamDTO(); + mysqlDatasourceParamDTO.setUserName("root"); + mysqlDatasourceParamDTO.setPassword("123456"); + mysqlDatasourceParamDTO.setHost("localhost"); + mysqlDatasourceParamDTO.setPort(30015); + mysqlDatasourceParamDTO.setDatabase("default"); + mysqlDatasourceParamDTO.setOther(props); + try (MockedStatic mockedPasswordUtils = Mockito.mockStatic(PasswordUtils.class)) { + Mockito.when(PasswordUtils.encodePassword(Mockito.anyString())).thenReturn("test"); + HanaConnectionParam connectionParams = (HanaConnectionParam) hanaDataSourceProcessor + .createConnectionParams(mysqlDatasourceParamDTO); + Assertions.assertEquals("jdbc:sap://localhost:30015", connectionParams.getAddress()); + Assertions.assertEquals("jdbc:sap://localhost:30015?currentschema=default", connectionParams.getJdbcUrl()); + } + } + + @Test + public void testCreateConnectionParams2() { + String connectionJson = "{\"user\":\"root\",\"password\":\"123456\",\"address\":\"jdbc:sap://localhost:30015\"" + + ",\"database\":\"default\",\"jdbcUrl\":\"jdbc:sap://localhost:30015?currentschema=default\"}"; + HanaConnectionParam connectionParams = (HanaConnectionParam) hanaDataSourceProcessor + .createConnectionParams(connectionJson); + Assertions.assertNotNull(connectionJson); + Assertions.assertEquals("root", connectionParams.getUser()); + } + + @Test + public void testGetDatasourceDriver() { + Assertions.assertEquals(DataSourceConstants.COM_HANA_DB_JDBC_DRIVER, + hanaDataSourceProcessor.getDatasourceDriver()); + } + + @Test + public void testGetJdbcUrl() { + HanaConnectionParam hanaConnectionParam = new HanaConnectionParam(); + hanaConnectionParam.setJdbcUrl("jdbc:sap://localhost:30015?currentschema=default"); + Assertions.assertEquals( + "jdbc:sap://localhost:30015?currentschema=default&reconnect=true", + hanaDataSourceProcessor.getJdbcUrl(hanaConnectionParam)); + } + + @Test + public void testGetDbType() { + Assertions.assertEquals(DbType.HANA, hanaDataSourceProcessor.getDbType()); + } + + @Test + public void testGetValidationQuery() { + Assertions.assertEquals(DataSourceConstants.HANA_VALIDATION_QUERY, + hanaDataSourceProcessor.getValidationQuery()); + } + + @Test + public void testGetDatasourceUniqueId() { + HanaConnectionParam mysqlConnectionParam = new HanaConnectionParam(); + mysqlConnectionParam.setJdbcUrl("jdbc:sap://localhost:30015?currentschema=default"); + mysqlConnectionParam.setUser("root"); + mysqlConnectionParam.setPassword("123456"); + try (MockedStatic mockedPasswordUtils = Mockito.mockStatic(PasswordUtils.class)) { + Mockito.when(PasswordUtils.encodePassword(Mockito.anyString())).thenReturn("123456"); + Assertions.assertEquals("hana@root@123456@jdbc:sap://localhost:30015?currentschema=default", + hanaDataSourceProcessor.getDatasourceUniqueId(mysqlConnectionParam, DbType.HANA)); + } + } +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/provider/JDBCDataSourceProviderTest.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/provider/JDBCDataSourceProviderTest.java new file mode 100644 index 0000000000..cea4282e75 --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/provider/JDBCDataSourceProviderTest.java @@ -0,0 +1,62 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana.provider; + +import com.zaxxer.hikari.HikariDataSource; +import org.apache.dolphinscheduler.plugin.datasource.api.provider.JDBCDataSourceProvider; +import org.apache.dolphinscheduler.plugin.datasource.hana.param.HanaConnectionParam; +import org.apache.dolphinscheduler.spi.enums.DbType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class JDBCDataSourceProviderTest { + + @Test + public void testCreateJdbcDataSource() { + try ( + MockedStatic mockedJDBCDataSourceProvider = + Mockito.mockStatic(JDBCDataSourceProvider.class)) { + HikariDataSource dataSource = Mockito.mock(HikariDataSource.class); + mockedJDBCDataSourceProvider + .when(() -> JDBCDataSourceProvider.createJdbcDataSource(Mockito.any(), Mockito.any())) + .thenReturn(dataSource); + Assertions.assertNotNull( + JDBCDataSourceProvider.createJdbcDataSource(new HanaConnectionParam(), DbType.HANA)); + } + } + + @Test + public void testCreateOneSessionJdbcDataSource() { + try ( + MockedStatic mockedJDBCDataSourceProvider = + Mockito.mockStatic(JDBCDataSourceProvider.class)) { + HikariDataSource dataSource = Mockito.mock(HikariDataSource.class); + mockedJDBCDataSourceProvider + .when(() -> JDBCDataSourceProvider.createOneSessionJdbcDataSource(Mockito.any(), Mockito.any())) + .thenReturn(dataSource); + Assertions.assertNotNull( + JDBCDataSourceProvider.createOneSessionJdbcDataSource(new HanaConnectionParam(), DbType.HANA)); + } + } + +} diff --git a/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/utils/DataSourceUtilsTest.java b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/utils/DataSourceUtilsTest.java new file mode 100644 index 0000000000..e7cf949e31 --- /dev/null +++ b/dolphinscheduler-datasource-plugin/dolphinscheduler-datasource-hana/src/test/java/org/apache/dolphinscheduler/plugin/datasource/hana/utils/DataSourceUtilsTest.java @@ -0,0 +1,147 @@ +/* + * 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.dolphinscheduler.plugin.datasource.hana.utils; + +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.common.utils.PropertyUtils; +import org.apache.dolphinscheduler.plugin.datasource.api.plugin.DataSourceClientProvider; +import org.apache.dolphinscheduler.plugin.datasource.api.utils.CommonUtils; +import org.apache.dolphinscheduler.plugin.datasource.api.utils.DataSourceUtils; +import org.apache.dolphinscheduler.plugin.datasource.api.utils.PasswordUtils; +import org.apache.dolphinscheduler.plugin.datasource.hana.param.HanaConnectionParam; +import org.apache.dolphinscheduler.plugin.datasource.hana.param.HanaDataSourceParamDTO; +import org.apache.dolphinscheduler.spi.datasource.ConnectionParam; +import org.apache.dolphinscheduler.spi.enums.DbType; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.sql.Connection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +@ExtendWith(MockitoExtension.class) +public class DataSourceUtilsTest { + + @Test + public void testCheckDatasourceParam() { + HanaDataSourceParamDTO hanaDataSourceParamDTO = new HanaDataSourceParamDTO(); + hanaDataSourceParamDTO.setHost("localhost"); + hanaDataSourceParamDTO.setDatabase("default"); + Map other = new HashMap<>(); + other.put("reconnect", "true"); + hanaDataSourceParamDTO.setOther(other); + DataSourceUtils.checkDatasourceParam(hanaDataSourceParamDTO); + Assertions.assertTrue(true); + } + + @Test + public void testBuildConnectionParams() { + HanaDataSourceParamDTO hanaDataSourceParamDTO = new HanaDataSourceParamDTO(); + hanaDataSourceParamDTO.setHost("localhost"); + hanaDataSourceParamDTO.setDatabase("default"); + hanaDataSourceParamDTO.setUserName("root"); + hanaDataSourceParamDTO.setPort(30015); + hanaDataSourceParamDTO.setPassword("123456"); + + try ( + MockedStatic mockedStaticPasswordUtils = Mockito.mockStatic(PasswordUtils.class); + MockedStatic mockedStaticCommonUtils = Mockito.mockStatic(CommonUtils.class)) { + mockedStaticPasswordUtils.when(() -> PasswordUtils.encodePassword(Mockito.anyString())) + .thenReturn("123456"); + mockedStaticCommonUtils.when(CommonUtils::getKerberosStartupState).thenReturn(false); + ConnectionParam connectionParam = DataSourceUtils.buildConnectionParams(hanaDataSourceParamDTO); + Assertions.assertNotNull(connectionParam); + } + } + + @Test + public void testBuildConnectionParams2() { + HanaDataSourceParamDTO hanaDatasourceParamDTO = new HanaDataSourceParamDTO(); + hanaDatasourceParamDTO.setHost("localhost"); + hanaDatasourceParamDTO.setDatabase("default"); + hanaDatasourceParamDTO.setUserName("root"); + hanaDatasourceParamDTO.setPort(30015); + hanaDatasourceParamDTO.setPassword("123456"); + ConnectionParam connectionParam = + DataSourceUtils.buildConnectionParams(DbType.HANA, JSONUtils.toJsonString(hanaDatasourceParamDTO)); + Assertions.assertNotNull(connectionParam); + } + + @Test + public void testGetConnection() throws ExecutionException { + try ( + MockedStatic mockedStaticPropertyUtils = Mockito.mockStatic(PropertyUtils.class); + MockedStatic mockedStaticDataSourceClientProvider = + Mockito.mockStatic(DataSourceClientProvider.class)) { + mockedStaticPropertyUtils.when(() -> PropertyUtils.getLong("kerberos.expire.time", 24L)).thenReturn(24L); + DataSourceClientProvider clientProvider = Mockito.mock(DataSourceClientProvider.class); + mockedStaticDataSourceClientProvider.when(DataSourceClientProvider::getInstance).thenReturn(clientProvider); + + Connection connection = Mockito.mock(Connection.class); + Mockito.when(clientProvider.getConnection(Mockito.any(), Mockito.any())).thenReturn(connection); + + HanaConnectionParam connectionParam = new HanaConnectionParam(); + connectionParam.setUser("root"); + connectionParam.setPassword("123456"); + connection = DataSourceClientProvider.getInstance().getConnection(DbType.HANA, connectionParam); + + Assertions.assertNotNull(connection); + } + } + + @Test + public void testGetJdbcUrl() { + HanaConnectionParam hanaConnectionParam = new HanaConnectionParam(); + hanaConnectionParam.setJdbcUrl("jdbc:sap://localhost:30015"); + String jdbcUrl = DataSourceUtils.getJdbcUrl(DbType.HANA, hanaConnectionParam); + Assertions.assertEquals( + "jdbc:sap://localhost:30015?reconnect=true", + jdbcUrl); + } + + @Test + public void testBuildDatasourceParamDTO() { + HanaConnectionParam connectionParam = new HanaConnectionParam(); + connectionParam.setJdbcUrl( + "jdbc:sap://localhost:30015?reconnect=true"); + connectionParam.setAddress("jdbc:mysql://localhost:30015"); + connectionParam.setUser("root"); + connectionParam.setPassword("123456"); + + Assertions.assertNotNull( + DataSourceUtils.buildDatasourceParamDTO(DbType.HANA, JSONUtils.toJsonString(connectionParam))); + + } + + @Test + public void testGetDatasourceProcessor() { + Assertions.assertNotNull(DataSourceUtils.getDatasourceProcessor(DbType.HANA)); + } + + @Test + public void testGetDatasourceProcessorError() { + Assertions.assertThrows(Exception.class, () -> { + DataSourceUtils.getDatasourceProcessor(null); + }); + } +} diff --git a/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/DbType.java b/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/DbType.java index 1931f64015..a937713f6b 100644 --- a/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/DbType.java +++ b/dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/DbType.java @@ -49,7 +49,8 @@ public enum DbType { KYUUBI(18, "kyuubi"), DATABEND(19, "databend"), SNOWFLAKE(20, "snowflake"), - VERTICA(21, "vertica"); + VERTICA(21, "vertica"), + HANA(22, "hana"); private static final Map DB_TYPE_MAP = Arrays.stream(DbType.values()).collect(toMap(DbType::getCode, Functions.identity())); diff --git a/dolphinscheduler-ui/src/service/modules/data-source/types.ts b/dolphinscheduler-ui/src/service/modules/data-source/types.ts index 3ee3e0b070..a493f4119a 100644 --- a/dolphinscheduler-ui/src/service/modules/data-source/types.ts +++ b/dolphinscheduler-ui/src/service/modules/data-source/types.ts @@ -36,6 +36,7 @@ type IDataBase = | 'SSH' | 'DATABEND' | 'SNOWFLAKE' + | 'HANA' type IDataBaseLabel = | 'MYSQL' diff --git a/dolphinscheduler-ui/src/views/datasource/list/use-form.ts b/dolphinscheduler-ui/src/views/datasource/list/use-form.ts index 8d370a3048..06d7ca3e0e 100644 --- a/dolphinscheduler-ui/src/views/datasource/list/use-form.ts +++ b/dolphinscheduler-ui/src/views/datasource/list/use-form.ts @@ -396,6 +396,11 @@ export const datasourceType: IDataBaseOptionKeys = { value: 'DATABEND', label: 'DATABEND', defaultPort: 8000 + }, + HANA: { + value: 'HANA', + label: 'HANA', + defaultPort: 30015 } } diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-datasource.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-datasource.ts index bec381c55b..9d6bfba71d 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-datasource.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-datasource.ts @@ -127,6 +127,11 @@ export function useDatasource( id: 21, code: 'VERTICA', disabled: false + }, + { + id: 22, + code: 'HANA', + disabled: false } ]