diff --git a/README.md b/README.md index d1648d69..edd93109 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,9 @@ Here are some of the major database solutions that are supported:   CeresDB +   + + GreptimeDB

diff --git a/core/datacap-server/pom.xml b/core/datacap-server/pom.xml index 8e291c88..91b2d3b9 100644 --- a/core/datacap-server/pom.xml +++ b/core/datacap-server/pom.xml @@ -320,6 +320,11 @@ datacap-http-ceresdb ${project.version} + + io.edurt.datacap + datacap-http-greptime + ${project.version} + io.edurt.datacap diff --git a/core/datacap-server/src/main/etc/conf/plugins/http/ceresdb.yaml b/core/datacap-server/src/main/etc/conf/plugins/http/ceresdb.yaml index 5938f19d..78d188e4 100644 --- a/core/datacap-server/src/main/etc/conf/plugins/http/ceresdb.yaml +++ b/core/datacap-server/src/main/etc/conf/plugins/http/ceresdb.yaml @@ -18,41 +18,3 @@ configures: max: 65535 value: 5440 message: port is a required field, please be sure to enter - -pipelines: - - executor: Seatunnel - type: SOURCE - fields: - - field: host - origin: host|port - required: true - - field: database - origin: database - required: true - - field: sql - origin: context - required: true - - field: username - origin: username - required: true - - field: password - origin: password - required: true - - executor: Seatunnel - type: SINK - fields: - - field: host - origin: host|port - required: true - - field: database - origin: database - required: true - - field: sql - origin: context - required: true - - field: username - origin: username - required: true - - field: password - origin: password - required: true diff --git a/core/datacap-server/src/main/etc/conf/plugins/http/greptimedb.yaml b/core/datacap-server/src/main/etc/conf/plugins/http/greptimedb.yaml new file mode 100644 index 00000000..873eeb48 --- /dev/null +++ b/core/datacap-server/src/main/etc/conf/plugins/http/greptimedb.yaml @@ -0,0 +1,20 @@ +name: GreptimeDB +supportTime: '2023-04-14' + +configures: + - field: name + type: String + required: true + message: name is a required field, please be sure to enter + - field: host + type: String + required: true + value: 127.0.0.1 + message: host is a required field, please be sure to enter + - field: port + type: Number + required: true + min: 1 + max: 65535 + value: 4000 + message: port is a required field, please be sure to enter diff --git a/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/HttpConfigure.java b/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/HttpConfigure.java index 3056b42b..5bac7054 100644 --- a/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/HttpConfigure.java +++ b/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/HttpConfigure.java @@ -25,5 +25,6 @@ public class HttpConfigure private Boolean autoConnected = Boolean.FALSE; private Map params; private String jsonBody; + private boolean isDecoded = false; private MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); } diff --git a/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/http/HttpClient.java b/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/http/HttpClient.java index b8b90f91..99b05d61 100644 --- a/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/http/HttpClient.java +++ b/core/datacap-spi/src/main/java/io/edurt/datacap/spi/connection/http/HttpClient.java @@ -4,6 +4,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.edurt.datacap.spi.connection.HttpConfigure; import io.edurt.datacap.spi.connection.HttpConnection; import okhttp3.ConnectionPool; +import okhttp3.FormBody; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -13,6 +14,7 @@ import org.apache.commons.lang3.ObjectUtils; import java.io.IOException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; @SuppressFBWarnings(value = {"NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"}, justification = "I prefer to suppress these FindBugs warnings") @@ -55,6 +57,9 @@ public class HttpClient case GET: return this.get(); case POST: + if (configure.isDecoded()) { + return this.postEncoder(); + } return this.post(); default: return null; @@ -93,6 +98,24 @@ public class HttpClient return execute(request); } + private String postEncoder() + { + AtomicReference key = new AtomicReference<>(); + AtomicReference value = new AtomicReference<>(); + configure.getParams().forEach((originKey, originValue) -> { + key.set(originKey); + value.set(originValue); + }); + RequestBody body = new FormBody.Builder() + .add(key.get(), value.get()) + .build(); + Request request = new Request.Builder() + .url(httpConnection.formatJdbcUrl()) + .method(HttpMethod.POST.name(), body) + .build(); + return execute(request); + } + private String execute(Request request) { String responseBody = null; diff --git a/core/datacap-web/console-fe/public/static/images/plugin/GreptimeDB.png b/core/datacap-web/console-fe/public/static/images/plugin/GreptimeDB.png new file mode 100644 index 00000000..c5111698 Binary files /dev/null and b/core/datacap-web/console-fe/public/static/images/plugin/GreptimeDB.png differ diff --git a/docs/docs/assets/plugin/greptimedb.png b/docs/docs/assets/plugin/greptimedb.png new file mode 100644 index 00000000..3551294d Binary files /dev/null and b/docs/docs/assets/plugin/greptimedb.png differ diff --git a/docs/docs/index.md b/docs/docs/index.md index 3e6bfaca..97600531 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -184,6 +184,9 @@ Datacap is fast, lightweight, intuitive system.   CeresDB +   + + GreptimeDB

diff --git a/docs/docs/index.zh.md b/docs/docs/index.zh.md index 75204e6e..b9140a9e 100644 --- a/docs/docs/index.zh.md +++ b/docs/docs/index.zh.md @@ -184,6 +184,9 @@ Datacap 是快速、轻量级、直观的系统。   CeresDB +   + + GreptimeDB

diff --git a/docs/docs/reference/connectors/http/greptimedb.md b/docs/docs/reference/connectors/http/greptimedb.md new file mode 100644 index 00000000..36641ca7 --- /dev/null +++ b/docs/docs/reference/connectors/http/greptimedb.md @@ -0,0 +1,44 @@ +--- +title: GreptimeDB +status: new +--- + + + +#### What is GreptimeDB ? + +An open-source, cloud-native, distributed time-series database with PromQL/SQL/Python supported. + +#### Environment + +!!! note + + If you need to use this data source, you need to upgrade the DataCap service to >= `1.9.x` + +Support Time: `2023-04-14` + +#### Configure + +--- + +!!! note + + If your GreptimeDB service version requires other special configurations, please refer to modifying the configuration file and restarting the DataCap service. + +=== "Configure" + + | Field | Required | Default Value | + |:------:|:---------------------------------:|:-------------:| + | `Name` | :material-check-circle: { .red } | - | + | `Host` | :material-check-circle: { .red } | `127.0.0.1` | + | `Port` | :material-check-circle: { .red } | `4000` | + +#### Version (Validation) + +--- + +!!! warning + + The online service has not been tested yet, if you have detailed test results, please submit [issues](https://github.com/EdurtIO/datacap/issues/new/choose) to us + +- [x] 0.x diff --git a/docs/docs/reference/connectors/http/greptimedb.zh.md b/docs/docs/reference/connectors/http/greptimedb.zh.md new file mode 100644 index 00000000..7a161765 --- /dev/null +++ b/docs/docs/reference/connectors/http/greptimedb.zh.md @@ -0,0 +1,44 @@ +--- +title: GreptimeDB +status: new +--- + + + +#### 什么是 GreptimeDB ? + +一个开源、云原生、分布式时间序列数据库,支持PromQL/SQL/Python。 + +#### 环境 + +!!! note + + 如果你需要使用这个数据源, 您需要将 DataCap 服务升级到 >= `1.9.x` + +支持时间: `2023-04-14` + +#### 配置 + +--- + +!!! note + + 如果您的 GreptimeDB 服务版本需要其他特殊配置,请参考修改配置文件并重启 DataCap 服务。 + +=== "配置" + + | Field | Required | Default Value | + |:------:|:---------------------------------:|:-------------:| + | `Name` | :material-check-circle: { .red } | - | + | `Host` | :material-check-circle: { .red } | `127.0.0.1` | + | `Port` | :material-check-circle: { .red } | `5440` | + +#### 版本(验证) + +--- + +!!! warning + + 服务版本尚未测试,如果您有详细的测试并发现错误,请提交 [issues](https://github.com/EdurtIO/datacap/issues/new/choose) + +- [x] 0.x diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e52e22d0..d32ced23 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -165,6 +165,7 @@ nav: - Zookeeper: reference/connectors/native/zookeeper.md - Redis: reference/connectors/native/redis.md - Http: + - GreptimeDB: reference/connectors/http/greptimedb.md - CeresDB: reference/connectors/http/ceresdb.md - ClickHouse: reference/connectors/http/clickhouse.md - Developer guide: diff --git a/plugin/datacap-http-greptime/pom.xml b/plugin/datacap-http-greptime/pom.xml new file mode 100644 index 00000000..2683227e --- /dev/null +++ b/plugin/datacap-http-greptime/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + io.edurt.datacap + datacap + 1.9.0-SNAPSHOT + ../../pom.xml + + + datacap-http-greptime + DataCap - GreptimeDB + + + http-greptime + + + + + io.edurt.datacap + datacap-spi + provided + + + io.edurt.datacap + datacap-common + + + commons-beanutils + commons-beanutils + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-simple + test + + + org.testcontainers + testcontainers + test + + + + + + + maven-assembly-plugin + ${assembly-plugin.version} + + ${plugin.name} + + ../../configure/assembly/assembly-plugin.xml + + ../../dist/plugins/${plugin.name} + + + + make-assembly + package + + single + + + + + + + + diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBAdapter.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBAdapter.java new file mode 100644 index 00000000..08da625f --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBAdapter.java @@ -0,0 +1,91 @@ +package io.edurt.datacap.plugin.http.greptime; + +import com.google.common.collect.Maps; +import io.edurt.datacap.plugin.http.greptime.response.GreptimeDBResponse; +import io.edurt.datacap.plugin.http.greptime.response.record.Records; +import io.edurt.datacap.spi.adapter.HttpAdapter; +import io.edurt.datacap.spi.connection.HttpConfigure; +import io.edurt.datacap.spi.connection.HttpConnection; +import io.edurt.datacap.spi.connection.http.HttpClient; +import io.edurt.datacap.spi.connection.http.HttpMethod; +import io.edurt.datacap.spi.json.JSON; +import io.edurt.datacap.spi.model.Response; +import io.edurt.datacap.spi.model.Time; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang3.ObjectUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Slf4j +public class GreptimeDBAdapter + extends HttpAdapter +{ + public GreptimeDBAdapter(HttpConnection connection) + { + super(connection); + } + + @Override + public Response handlerExecute(String content) + { + Time processorTime = new Time(); + processorTime.setStart(new Date().getTime()); + Response response = this.httpConnection.getResponse(); + HttpConfigure configure = new HttpConfigure(); + if (response.getIsConnected()) { + List headers = new ArrayList<>(); + List types = new ArrayList<>(); + List columns = new ArrayList<>(); + try { + BeanUtils.copyProperties(configure, this.httpConnection.getConfigure()); + configure.setAutoConnected(Boolean.FALSE); + configure.setRetry(0); + configure.setMethod(HttpMethod.POST); + configure.setPath("v1/sql"); + Map parameters = Maps.newHashMap(); + parameters.put("sql", content); + configure.setParams(parameters); + configure.setDecoded(true); + HttpConnection httpConnection = new HttpConnection(configure, new Response()); + HttpClient httpClient = HttpClient.getInstance(configure, httpConnection); + String body = httpClient.execute(); + GreptimeDBResponse requestResponse = JSON.objectmapper.readValue(body, GreptimeDBResponse.class); + if (requestResponse.getCode() == 0 || ObjectUtils.isNotEmpty(requestResponse.getOutput())) { + response.setIsSuccessful(true); + Records records = requestResponse.getOutput().get(0).getRecords(); + if (ObjectUtils.isNotEmpty(records.getSchema())) { + records.getSchema() + .getColumnSchemas() + .forEach(schema -> { + headers.add(schema.getName()); + types.add(schema.getDataType()); + }); + } + records.getRows() + .forEach(record -> columns.add(handlerFormatter(configure.getFormat(), headers, record))); + } + else { + response.setIsSuccessful(Boolean.FALSE); + response.setMessage(requestResponse.getError()); + } + } + catch (Exception ex) { + log.error("Execute content failed content {} exception ", content, ex); + response.setIsSuccessful(Boolean.FALSE); + response.setMessage(ex.getMessage()); + } + finally { + response.setHeaders(headers); + response.setTypes(types); + response.setColumns(columns); + } + } + processorTime.setEnd(new Date().getTime()); + response.setProcessor(processorTime); + return response; + } +} diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPlugin.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPlugin.java new file mode 100644 index 00000000..b6c6c678 --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPlugin.java @@ -0,0 +1,81 @@ +package io.edurt.datacap.plugin.http.greptime; + +import io.edurt.datacap.spi.Plugin; +import io.edurt.datacap.spi.PluginType; +import io.edurt.datacap.spi.connection.HttpConfigure; +import io.edurt.datacap.spi.connection.HttpConnection; +import io.edurt.datacap.spi.model.Configure; +import io.edurt.datacap.spi.model.Response; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang3.ObjectUtils; + +@Slf4j +public class GreptimeDBPlugin + implements Plugin +{ + private HttpConfigure configure; + private HttpConnection connection; + private Response response; + + @Override + public String validator() + { + return "SELECT 1"; + } + + @Override + public String name() + { + return "GreptimeDB"; + } + + @Override + public String description() + { + return "Integrate GreptimeDB data sources"; + } + + @Override + public PluginType type() + { + return PluginType.HTTP; + } + + @Override + public void connect(Configure configure) + { + try { + this.response = new Response(); + this.configure = new HttpConfigure(); + BeanUtils.copyProperties(this.configure, configure); + this.connection = new HttpConnection(this.configure, this.response); + } + catch (Exception ex) { + this.response.setIsConnected(Boolean.FALSE); + this.response.setMessage(ex.getMessage()); + } + } + + @Override + public Response execute(String content) + { + if (ObjectUtils.isNotEmpty(this.connection)) { + log.info("Execute greptimedb plugin logic started"); + this.response = this.connection.getResponse(); + GreptimeDBAdapter processor = new GreptimeDBAdapter(this.connection); + this.response = processor.handlerExecute(content); + log.info("Execute greptimedb plugin logic end"); + } + this.destroy(); + return this.response; + } + + @Override + public void destroy() + { + if (ObjectUtils.isNotEmpty(this.connection)) { + this.connection.destroy(); + } + } +} diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginModule.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginModule.java new file mode 100644 index 00000000..13ff2035 --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginModule.java @@ -0,0 +1,38 @@ +package io.edurt.datacap.plugin.http.greptime; + +import com.google.inject.multibindings.Multibinder; +import io.edurt.datacap.spi.AbstractPluginModule; +import io.edurt.datacap.spi.Plugin; +import io.edurt.datacap.spi.PluginModule; +import io.edurt.datacap.spi.PluginType; + +public class GreptimeDBPluginModule + extends AbstractPluginModule + implements PluginModule +{ + @Override + public String getName() + { + return "GreptimeDB"; + } + + @Override + public PluginType getType() + { + return PluginType.HTTP; + } + + @Override + public AbstractPluginModule get() + { + return this; + } + + protected void configure() + { + Multibinder module = Multibinder.newSetBinder(this.binder(), String.class); + module.addBinding().toInstance(this.getClass().getSimpleName()); + Multibinder plugin = Multibinder.newSetBinder(this.binder(), Plugin.class); + plugin.addBinding().to(GreptimeDBPlugin.class); + } +} diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/GreptimeDBResponse.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/GreptimeDBResponse.java new file mode 100644 index 00000000..2eb1a2f1 --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/GreptimeDBResponse.java @@ -0,0 +1,22 @@ +package io.edurt.datacap.plugin.http.greptime.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.edurt.datacap.plugin.http.greptime.response.record.Output; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.List; + +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class GreptimeDBResponse +{ + private int code; + private String error; + private List output; +} diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/ColumnSchema.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/ColumnSchema.java new file mode 100644 index 00000000..c1b02358 --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/ColumnSchema.java @@ -0,0 +1,20 @@ +package io.edurt.datacap.plugin.http.greptime.response.record; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class ColumnSchema +{ + private String name; + @JsonProperty(value = "data_type") + private String dataType; +} diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Output.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Output.java new file mode 100644 index 00000000..ba9576ed --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Output.java @@ -0,0 +1,17 @@ +package io.edurt.datacap.plugin.http.greptime.response.record; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class Output +{ + public Records records; +} diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Records.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Records.java new file mode 100644 index 00000000..b0e734f3 --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Records.java @@ -0,0 +1,20 @@ +package io.edurt.datacap.plugin.http.greptime.response.record; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.List; + +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class Records +{ + public Schema schema; + public List> rows; +} diff --git a/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Schema.java b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Schema.java new file mode 100644 index 00000000..8d0da9f9 --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/java/io/edurt/datacap/plugin/http/greptime/response/record/Schema.java @@ -0,0 +1,21 @@ +package io.edurt.datacap.plugin.http.greptime.response.record; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.util.ArrayList; + +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class Schema +{ + @JsonProperty(value = "column_schemas") + public ArrayList columnSchemas; +} diff --git a/plugin/datacap-http-greptime/src/main/resources/META-INF/services/io.edurt.datacap.spi.PluginModule b/plugin/datacap-http-greptime/src/main/resources/META-INF/services/io.edurt.datacap.spi.PluginModule new file mode 100644 index 00000000..fc544bdd --- /dev/null +++ b/plugin/datacap-http-greptime/src/main/resources/META-INF/services/io.edurt.datacap.spi.PluginModule @@ -0,0 +1 @@ +io.edurt.datacap.plugin.http.greptime.GreptimeDBPluginModule diff --git a/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBContainer.java b/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBContainer.java new file mode 100644 index 00000000..d73568e3 --- /dev/null +++ b/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBContainer.java @@ -0,0 +1,56 @@ +package io.edurt.datacap.plugin.http.greptime; + +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.DockerImageName; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; + +public class GreptimeDBContainer + extends GenericContainer +{ + private static final DockerImageName DEFAULT_IMAGE_NAME = + DockerImageName.parse("greptime/greptimedb"); + + public static final int PORT = 4001; + public static final int HTTP_PORT = 4000; + + public GreptimeDBContainer() + { + super(DEFAULT_IMAGE_NAME); + withExposedPorts(PORT, HTTP_PORT); + } + + public GreptimeDBContainer(final DockerImageName dockerImageName) + { + super(dockerImageName); + dockerImageName.assertCompatibleWith(dockerImageName); + withExposedPorts(PORT, HTTP_PORT); + } + + public String getLinuxLocalIp() + { + String ip = ""; + try { + Enumeration networkInterfaces = + NetworkInterface.getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) { + NetworkInterface networkInterface = networkInterfaces.nextElement(); + Enumeration inetAddresses = networkInterface.getInetAddresses(); + while (inetAddresses.hasMoreElements()) { + InetAddress inetAddress = inetAddresses.nextElement(); + if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) { + ip = inetAddress.getHostAddress(); + } + } + } + } + catch (SocketException ex) { + ex.printStackTrace(); + } + return ip; + } +} diff --git a/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginModuleTest.java b/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginModuleTest.java new file mode 100644 index 00000000..1d49fc32 --- /dev/null +++ b/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginModuleTest.java @@ -0,0 +1,30 @@ +package io.edurt.datacap.plugin.http.greptime; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import io.edurt.datacap.spi.Plugin; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Set; + +public class GreptimeDBPluginModuleTest +{ + private Injector injector; + + @Before + public void before() + { + this.injector = Guice.createInjector(new GreptimeDBPluginModule()); + } + + @Test + public void test() + { + Set plugins = injector.getInstance(Key.get(new TypeLiteral>() {})); + Assert.assertTrue(plugins.size() > 0); + } +} \ No newline at end of file diff --git a/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginTest.java b/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginTest.java new file mode 100644 index 00000000..53663323 --- /dev/null +++ b/plugin/datacap-http-greptime/src/test/java/io/edurt/datacap/plugin/http/greptime/GreptimeDBPluginTest.java @@ -0,0 +1,76 @@ +package io.edurt.datacap.plugin.http.greptime; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.TypeLiteral; +import io.edurt.datacap.spi.Plugin; +import io.edurt.datacap.spi.model.Configure; +import io.edurt.datacap.spi.model.Response; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.testcontainers.containers.Network; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.lifecycle.Startables; + +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +@Slf4j +public class GreptimeDBPluginTest +{ + private static final String HOST = "greptimeDBCluster"; + private Network network; + private GreptimeDBContainer container; + + private Injector injector; + private Configure configure; + + @Before + public void before() + { + network = Network.newNetwork(); + container = new GreptimeDBContainer() + .withNetwork(network) + .withNetworkAliases(HOST) + .withExposedPorts(GreptimeDBContainer.HTTP_PORT) + .withCommand("standalone", "start", + "--http-addr", "0.0.0.0:4000") + .waitingFor(Wait.forHttp("/dashboard")); + Startables.deepStart(Stream.of(container)).join(); + log.info("GreptimeDB container started"); + + injector = Guice.createInjector(new GreptimeDBPluginModule()); + configure = new Configure(); + configure.setHost("localhost"); + configure.setPort(container.getMappedPort(GreptimeDBContainer.HTTP_PORT)); + configure.setDatabase(Optional.of("default")); + } + + @Test + public void test() + { + Set plugins = injector.getInstance(Key.get(new TypeLiteral>() {})); + Optional pluginOptional = plugins.stream() + .filter(v -> v.name().equalsIgnoreCase("GreptimeDB")) + .findFirst(); + if (pluginOptional.isPresent()) { + Plugin plugin = pluginOptional.get(); + plugin.connect(configure); + String sql = "SELECT * FROM numbers LIMIT 5"; + Response response = plugin.execute(sql); + log.info("================ plugin executed information ================="); + if (!response.getIsSuccessful()) { + log.error("Message: {}", response.getMessage()); + } + else { + response.getColumns().forEach(column -> log.info(column.toString())); + } + Assert.assertTrue(response.getIsSuccessful()); + plugin.destroy(); + } + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8afba342..c51e361d 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ plugin/datacap-http-cratedb plugin/datacap-http-clickhouse plugin/datacap-http-ceresdb + plugin/datacap-http-greptime plugin/datacap-jdbc-clickhouse plugin/datacap-jdbc-cratedb plugin/datacap-jdbc-db2