You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by zi...@apache.org on 2024/03/23 15:32:53 UTC

(streampipes) branch dev updated: feat: add streampipes go client (#2437)

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

zike pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new 7d3f3163d2 feat: add streampipes go client (#2437)
7d3f3163d2 is described below

commit 7d3f3163d232a7e11c18d1d7cce3101536740ac7
Author: wyyolo <10...@users.noreply.github.com>
AuthorDate: Sat Mar 23 23:32:49 2024 +0800

    feat: add streampipes go client (#2437)
---
 .github/workflows/go-client.yml                    |  35 ++++
 streampipes-client-go/examples/main.go             |  89 ++++++++++
 streampipes-client-go/go.mod                       |  20 +++
 .../config/streampipes_client_config.go            |  42 +++++
 .../streampipes/data_lake_measure_api.go           | 184 +++++++++++++++++++++
 streampipes-client-go/streampipes/endpoint.go      |  73 ++++++++
 .../streampipes/internal/http_headers/header.go    |  54 ++++++
 .../internal/serializer/deserializer.go            |  76 +++++++++
 .../internal/util/streampipes_api_path.go          |  39 +++++
 .../internal/util/streampipes_api_path_test.go     |  52 ++++++
 streampipes-client-go/streampipes/model/common.go  |  68 ++++++++
 .../model/data_lake/data_lake_measure.go           |  32 ++++
 .../streampipes/model/data_lake/data_series.go     |  52 ++++++
 .../streampipes/streampipes_client.go              |  68 ++++++++
 .../streampipes/utils/check_url.go                 |  25 +++
 .../streampipes/utils/check_url_test.go            |  52 ++++++
 16 files changed, 961 insertions(+)

diff --git a/.github/workflows/go-client.yml b/.github/workflows/go-client.yml
new file mode 100644
index 0000000000..d967c2e830
--- /dev/null
+++ b/.github/workflows/go-client.yml
@@ -0,0 +1,35 @@
+# 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.
+
+name : go-client
+on:
+  pull_request:
+jobs:
+  go-unit-tests:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        go-version: [ '1.21.x' ]
+        os: [ubuntu-latest, macos-latest, windows-latest]
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-go@v4
+        with:
+          go-version: ${{ matrix.go-version }}
+      - name: Run unit-tests
+        working-directory: ./streampipes-client-go
+        run: |
+          go test ./...
diff --git a/streampipes-client-go/examples/main.go b/streampipes-client-go/examples/main.go
new file mode 100644
index 0000000000..cc053b8aff
--- /dev/null
+++ b/streampipes-client-go/examples/main.go
@@ -0,0 +1,89 @@
+//
+// 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 main
+
+import (
+	"github.com/apache/streampipes/streampipes-client-go/streampipes"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/config"
+	"log"
+)
+
+/*
+	Here are some examples of using go client, including outputting the data returned by streams.
+	Only supports outputting model data
+*/
+
+func main() {
+
+	/*
+		StreamPipesClientConfig can be configured in a number of ways.
+		For example:
+
+		First:  		clientConfig := config.StreamPipesClientConfig{
+							Url: "http://localhost:8030",
+							Credential: config.StreamPipesApiKeyCredentials{
+								UserName: "<Your-User-Name>",
+								ApiKey:   "<Your-API-Key>",
+							},
+						}
+
+		The second :    clientConfig := config.NewStreamPipesClientConnectConfig("http://localhost:8030",config.NewStreamPipesApiKeyCredentials("<Your-User-Name>","<Your-API-Key>"))
+
+		The third :     clientConfig := := config.StreamPipesClientConfig{
+							Url: "http://localhost:8030",
+							Credential: config.NewStreamPipesApiKeyCredentials("<Your-User-Name>","<Your-API-Key>"),
+						}
+	*/
+
+	clientConfig := config.StreamPipesClientConfig{
+		Url: "http://localhost:8030",
+		Credential: config.StreamPipesApiKeyCredentials{
+			UserName: "<Your-User-Name>",
+			ApiKey:   "<Your-API-Key>",
+		},
+	}
+
+	streamPipesClient, err := streampipes.NewStreamPipesClient(clientConfig)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	dataSeries, err := streamPipesClient.DataLakeMeasures().GetSingleDataSeries("measureName")
+	if err != nil {
+		log.Fatal(err)
+	}
+	dataSeries.Print()
+
+	/*
+			output format:
+
+			There are 2 pieces of DataSerie in the Dataseries
+			The 1 DataSeries
+			time                   msg                   test
+			2024-02-23T13:37:09.052Z   go-client_test   2f4556
+			2024-02-23T13:37:26.044Z   go-client_test   2f4556
+			2024-02-23T13:37:29.007Z   go-client_test   2f4556
+			The 2 DataSeries
+		    time                   msg                   test
+			2024-02-23T13:38:06.052Z   go-client_test   2f4556
+			2024-02-23T13:38:35.044Z   go-client_test   2f4556
+			2024-02-23T13:38:38.007Z   go-client_test   2f4556
+
+	*/
+
+}
diff --git a/streampipes-client-go/go.mod b/streampipes-client-go/go.mod
new file mode 100644
index 0000000000..4cb7e16181
--- /dev/null
+++ b/streampipes-client-go/go.mod
@@ -0,0 +1,20 @@
+//
+// 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.
+//
+
+module github.com/apache/streampipes/streampipes-client-go
+
+go 1.21
diff --git a/streampipes-client-go/streampipes/config/streampipes_client_config.go b/streampipes-client-go/streampipes/config/streampipes_client_config.go
new file mode 100644
index 0000000000..b2006dd20e
--- /dev/null
+++ b/streampipes-client-go/streampipes/config/streampipes_client_config.go
@@ -0,0 +1,42 @@
+//
+// 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 config
+
+type StreamPipesClientConfig struct {
+	Url        string
+	Credential StreamPipesApiKeyCredentials
+}
+
+type StreamPipesApiKeyCredentials struct {
+	UserName string
+	ApiKey   string
+}
+
+func NewStreamPipesClientConnectConfig(url string, credentials StreamPipesApiKeyCredentials) StreamPipesClientConfig {
+	return StreamPipesClientConfig{
+		Url:        url,
+		Credential: credentials,
+	}
+}
+
+func NewStreamPipesApiKeyCredentials(userName string, apiKey string) StreamPipesApiKeyCredentials {
+	return StreamPipesApiKeyCredentials{
+		UserName: userName,
+		ApiKey:   apiKey,
+	}
+}
diff --git a/streampipes-client-go/streampipes/data_lake_measure_api.go b/streampipes-client-go/streampipes/data_lake_measure_api.go
new file mode 100644
index 0000000000..1a2fa9a5fb
--- /dev/null
+++ b/streampipes-client-go/streampipes/data_lake_measure_api.go
@@ -0,0 +1,184 @@
+//
+// 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 streampipes
+
+import (
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/config"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/internal/serializer"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/internal/util"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/model/data_lake"
+	"io"
+	"log"
+	"net/http"
+)
+
+// DataLakeMeasure connects to the DataLakeMeasure endpoint of streamPipes.
+// DataLakeMeasure supports GET and DELETE to delete or obtain resources
+// The specific interaction behavior is provided by the method bound to the DataLakeMeasure struct.
+type DataLakeMeasure struct {
+	endpoint
+}
+
+func NewDataLakeMeasures(clientConfig config.StreamPipesClientConfig) *DataLakeMeasure {
+	// NewDataLakeMeasure is used to return an instance of *DataLakeMeasure,
+
+	return &DataLakeMeasure{
+		endpoint{config: clientConfig},
+	}
+}
+
+// AllDataLakeMeasure retrieves all the measures from the Data Lake.
+func (d *DataLakeMeasure) AllDataLakeMeasure() ([]data_lake.DataLakeMeasure, error) {
+
+	endPointUrl := util.NewStreamPipesApiPath(d.config.Url, "streampipes-backend/api/v4/datalake/measurements", nil)
+	log.Printf("Get data from: %s", endPointUrl)
+
+	response, err := d.executeRequest("GET", endPointUrl)
+	if err != nil {
+		return nil, err
+	}
+
+	if response.StatusCode != http.StatusOK {
+		err = d.handleStatusCode(response)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	body, err := io.ReadAll(response.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	unmarshalData, err := serializer.NewDataLakeMeasuresDeserializer().Unmarshal(body)
+	if err != nil {
+		return nil, err
+	}
+	dataLakeMeasures := unmarshalData.([]data_lake.DataLakeMeasure)
+
+	return dataLakeMeasures, nil
+}
+
+// GetSingleDataLakeMeasure retrieves a specific measure from the Data Lake.
+func (d *DataLakeMeasure) GetSingleDataLakeMeasure(elementId string) (data_lake.DataLakeMeasure, error) {
+
+	endPointUrl := util.NewStreamPipesApiPath(d.config.Url, "streampipes-backend/api/v4/datalake/measure", []string{elementId})
+	log.Printf("Get data from: %s", endPointUrl)
+
+	response, err := d.executeRequest("GET", endPointUrl)
+	if err != nil {
+		return data_lake.DataLakeMeasure{}, err
+	}
+
+	if response.StatusCode != http.StatusOK {
+		err = d.handleStatusCode(response)
+		if err != nil {
+			return data_lake.DataLakeMeasure{}, err
+		}
+	}
+
+	body, err := io.ReadAll(response.Body)
+	if err != nil {
+		return data_lake.DataLakeMeasure{}, err
+	}
+
+	unmarshalData, err := serializer.NewDataLakeMeasureDeserializer().Unmarshal(body)
+	if err != nil {
+		return data_lake.DataLakeMeasure{}, err
+	}
+	dataLakeMeasure := unmarshalData.(data_lake.DataLakeMeasure)
+
+	return dataLakeMeasure, nil
+}
+
+// GetSingleDataSeries retrieves the measurement series for the specified measureId from the Data Lake.
+// Currently not supporting parameter queries.
+// The measureId can also be considered measureName.
+func (d *DataLakeMeasure) GetSingleDataSeries(measureId string) (*data_lake.DataSeries, error) {
+
+	endPointUrl := util.NewStreamPipesApiPath(d.config.Url, "streampipes-backend/api/v4/datalake/measurements", []string{measureId})
+	log.Printf("Get data from: %s", endPointUrl)
+
+	response, err := d.executeRequest("GET", endPointUrl)
+	if err != nil {
+		return nil, err
+	}
+
+	if response.StatusCode != http.StatusOK {
+		err = d.handleStatusCode(response)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	body, err := io.ReadAll(response.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	unmarshalData, err := serializer.NewDataSeriesDeserializer().Unmarshal(body)
+	if err != nil {
+		return nil, err
+	}
+	dataSeries := unmarshalData.(data_lake.DataSeries)
+
+	return &dataSeries, nil
+}
+
+// ClearDataLakeMeasureData removes data from a single measurement series with given id.
+func (d *DataLakeMeasure) ClearDataLakeMeasureData(measureId string) error {
+
+	endPointUrl := util.NewStreamPipesApiPath(d.config.Url, "streampipes-backend/api/v4/datalake/measurements", []string{measureId})
+	log.Printf("Clear data from: %s", endPointUrl)
+
+	response, err := d.executeRequest("DELETE", endPointUrl)
+	if err != nil {
+		return err
+	}
+
+	if response.StatusCode != http.StatusOK {
+		err = d.handleStatusCode(response)
+		if err != nil {
+			return err
+		}
+	}
+	log.Printf("Successfully deleted data from a single measurement sequence of %s", measureId)
+
+	return nil
+}
+
+// DeleteDataLakeMeasure  drops a single measurement series with given id from Data Lake and remove related event property.
+func (d *DataLakeMeasure) DeleteDataLakeMeasure(measureId string) error {
+
+	endPointUrl := util.NewStreamPipesApiPath(d.config.Url, "streampipes-backend/api/v4/datalake/measurements", []string{measureId, "drop"})
+	log.Printf("Delete data from: %s", endPointUrl)
+	response, err := d.executeRequest("DELETE", endPointUrl)
+	if err != nil {
+		return err
+	}
+
+	if response.StatusCode != http.StatusOK {
+		err = d.handleStatusCode(response)
+		if err != nil {
+			return err
+		}
+	}
+
+	log.Printf("Successfully dropped a single measurement series for %s from  DataLake and remove related event property", measureId)
+	return nil
+}
diff --git a/streampipes-client-go/streampipes/endpoint.go b/streampipes-client-go/streampipes/endpoint.go
new file mode 100644
index 0000000000..2e3790dc93
--- /dev/null
+++ b/streampipes-client-go/streampipes/endpoint.go
@@ -0,0 +1,73 @@
+//
+// 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 streampipes
+
+import (
+	"errors"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/config"
+	headers "github.com/apache/streampipes/streampipes-client-go/streampipes/internal/http_headers"
+	"net/http"
+)
+
+type endpoint struct {
+	config config.StreamPipesClientConfig
+}
+
+func (e *endpoint) executeRequest(method string, endPointUrl string) (*http.Response, error) {
+	req, err := http.NewRequest(method, endPointUrl, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	header := headers.NewHeaders(req)
+	header.SetApiUserAndApiKey(e.config.Credential.UserName, e.config.Credential.ApiKey)
+	header.SetAcceptJson()
+	header.SetContentTypeJson()
+
+	client := &http.Client{}
+	response, err := client.Do(header.GetReq())
+	if err != nil {
+		return nil, err
+	}
+	return response, nil
+}
+
+func (e *endpoint) handleStatusCode(resp *http.Response) error {
+
+	switch resp.StatusCode {
+	case http.StatusUnauthorized:
+		return errors.New("The streamPipes Backend returned an unauthorized error.\nplease check your ApiUser and/or Apikey to be correct.")
+	case http.StatusForbidden:
+		return errors.New("There seems to be an issue with the access rights of the given user and the resource you queried.\n" +
+			"Apparently, this user is not allowed to query the resource.\n" +
+			"Please check the user's permissions or contact your StreamPipes admin.")
+	case http.StatusNotFound:
+		return errors.New("There seems to be an issue with the Go Client calling the API inappropriately.\n" +
+			"This should not happen, but unfortunately did.\n" +
+			"If you don't mind, it would be awesome to let us know by creating an issue at https://github.com/apache/streampipes.\n")
+	case http.StatusMethodNotAllowed:
+		return errors.New("There seems to be an issue with the Go Client calling the API inappropriately.\n" +
+			"This should not happen, but unfortunately did.\n" +
+			"If you don't mind, it would be awesome to let us know by creating an issue at https://github.com/apache/streampipes.\n")
+	case http.StatusInternalServerError:
+		return errors.New("streamPipes internal error")
+	default:
+		return errors.New(resp.Status)
+	}
+
+}
diff --git a/streampipes-client-go/streampipes/internal/http_headers/header.go b/streampipes-client-go/streampipes/internal/http_headers/header.go
new file mode 100644
index 0000000000..c201078c80
--- /dev/null
+++ b/streampipes-client-go/streampipes/internal/http_headers/header.go
@@ -0,0 +1,54 @@
+//
+// 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 http_headers
+
+import (
+	"net/http"
+)
+
+type Headers struct {
+	req    *http.Request
+	header http.Header
+}
+
+func NewHeaders(req *http.Request) *Headers {
+	return &Headers{
+		req:    req,
+		header: nil,
+	}
+}
+
+func (h *Headers) SetApiUserAndApiKey(apiUser string, apiKey string) {
+	h.header = h.req.Header
+	h.header.Set("X-API-USER", apiUser)
+	h.header.Set("X-API-KEY", apiKey)
+}
+
+func (h *Headers) SetAcceptJson() {
+	h.header = h.req.Header
+	h.header.Set("Accept", "application/json")
+}
+
+func (h *Headers) SetContentTypeJson() {
+	h.header = h.req.Header
+	h.header.Set("Content-type", "application/json")
+}
+
+func (h *Headers) GetReq() *http.Request {
+	return h.req
+}
diff --git a/streampipes-client-go/streampipes/internal/serializer/deserializer.go b/streampipes-client-go/streampipes/internal/serializer/deserializer.go
new file mode 100644
index 0000000000..94946f6564
--- /dev/null
+++ b/streampipes-client-go/streampipes/internal/serializer/deserializer.go
@@ -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 serializer
+
+import (
+	"encoding/json"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/model/data_lake"
+)
+
+type Deserializer interface {
+	Unmarshal(body []byte) (interface{}, error)
+}
+
+var _ Deserializer = (*DataLakeMeasuresDeserializer)(nil)
+var _ Deserializer = (*DataSeriesDeserializer)(nil)
+var _ Deserializer = (*DataLakeMeasureDeserializer)(nil)
+
+type DataLakeMeasuresDeserializer struct{}
+
+func NewDataLakeMeasuresDeserializer() *DataLakeMeasuresDeserializer {
+	return &DataLakeMeasuresDeserializer{}
+}
+
+func (u *DataLakeMeasuresDeserializer) Unmarshal(data []byte) (interface{}, error) {
+	var dataLakeMeasures []data_lake.DataLakeMeasure
+	err := json.Unmarshal(data, &dataLakeMeasures)
+	if err != nil {
+		return nil, err
+	}
+	return dataLakeMeasures, nil
+}
+
+type DataLakeMeasureDeserializer struct{}
+
+func NewDataLakeMeasureDeserializer() *DataLakeMeasureDeserializer {
+	return &DataLakeMeasureDeserializer{}
+}
+
+func (u *DataLakeMeasureDeserializer) Unmarshal(data []byte) (interface{}, error) {
+	var dataLakeMeasure data_lake.DataLakeMeasure
+	err := json.Unmarshal(data, &dataLakeMeasure)
+	if err != nil {
+		return nil, err
+	}
+	return dataLakeMeasure, nil
+}
+
+type DataSeriesDeserializer struct{}
+
+func NewDataSeriesDeserializer() *DataSeriesDeserializer {
+	return &DataSeriesDeserializer{}
+}
+
+func (u *DataSeriesDeserializer) Unmarshal(data []byte) (interface{}, error) {
+	var dataSeries data_lake.DataSeries
+	err := json.Unmarshal(data, &dataSeries)
+	if err != nil {
+		return nil, err
+	}
+	return dataSeries, nil
+}
diff --git a/streampipes-client-go/streampipes/internal/util/streampipes_api_path.go b/streampipes-client-go/streampipes/internal/util/streampipes_api_path.go
new file mode 100644
index 0000000000..6a6fd7fcac
--- /dev/null
+++ b/streampipes-client-go/streampipes/internal/util/streampipes_api_path.go
@@ -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.
+//
+
+package util
+
+import (
+	"strings"
+)
+
+func NewStreamPipesApiPath(baseUrl string, streamPipesUrl string, parameters []string) string {
+	path := []string{baseUrl, streamPipesUrl}
+	path = append(path, parameters...)
+	return join(path)
+}
+
+func join(path []string) string {
+	if path == nil {
+		return ""
+	}
+	if len(path) == 1 {
+		return path[0]
+	}
+	url := strings.Join(path, "/")
+	return url
+}
diff --git a/streampipes-client-go/streampipes/internal/util/streampipes_api_path_test.go b/streampipes-client-go/streampipes/internal/util/streampipes_api_path_test.go
new file mode 100644
index 0000000000..c17f9de4ec
--- /dev/null
+++ b/streampipes-client-go/streampipes/internal/util/streampipes_api_path_test.go
@@ -0,0 +1,52 @@
+//
+// 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 util
+
+import "testing"
+
+func TestJoin(t *testing.T) {
+	testCases := []struct {
+		name     string
+		input    []string
+		expected string
+	}{
+		{
+			name:     "Single URL",
+			input:    []string{"http://localhost:8030"},
+			expected: "http://localhost:8030",
+		},
+		{
+			name:     "Empty slice",
+			input:    []string{},
+			expected: "",
+		},
+		{
+			name:     "Multiple URL parts",
+			input:    []string{"http://localhost:8030", "test1", "test2"},
+			expected: "http://localhost:8030/test1/test2",
+		},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			result := join(tc.input)
+			if result != tc.expected {
+				t.Errorf("Expected '%s', got '%s'", tc.expected, result)
+			}
+		})
+	}
+}
diff --git a/streampipes-client-go/streampipes/model/common.go b/streampipes-client-go/streampipes/model/common.go
new file mode 100644
index 0000000000..f0ba11637a
--- /dev/null
+++ b/streampipes-client-go/streampipes/model/common.go
@@ -0,0 +1,68 @@
+//
+// 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 model
+
+type ValueSpecification struct {
+	ElementID string  `json:"elementId,omitempty"`
+	MinValue  int     `json:"minValue,omitempty"`
+	MaxValue  int     `json:"maxValue,omitempty"`
+	Step      float64 `json:"step,omitempty"`
+}
+
+type EventProperty struct {
+	ElementID          string             `json:"elementId"`
+	Label              string             `json:"label,omitempty"`
+	Description        string             `json:"description,omitempty"`
+	RuntimeName        string             `json:"runtimeName,omitempty"`
+	Required           bool               `json:"required,omitempty"`
+	DomainProperties   []string           `json:"domainProperties,omitempty"`
+	PropertyScope      string             `json:"propertyScope,omitempty"`
+	Index              int                `json:"index"`
+	RuntimeID          string             `json:"runtimeId,omitempty"`
+	RuntimeType        string             `json:"runtimeType"`
+	MeasurementUnit    string             `json:"measurementUnit,omitempty"`
+	ValueSpecification ValueSpecification `json:"valueSpecification,omitempty"`
+}
+
+type EventProperties struct {
+	ElementID          string            `json:"elementId"`
+	Label              string            `json:"label"`
+	Description        string            `json:"description"`
+	RuntimeName        string            `json:"runtimeName"`
+	Required           bool              `json:"required"`
+	DomainProperties   []string          `json:"domainProperties"`
+	PropertyScope      string            `json:"propertyScope"`
+	Index              int               `json:"index"`
+	RuntimeID          string            `json:"runtimeId"`
+	RuntimeType        string            `json:"runtimeType,omitempty"`
+	MeasurementUnit    string            `json:"measurementUnit,omitempty"`
+	ValueSpecification string            `json:"valueSpecification,omitempty"`
+	InEventProperties  []EventProperties `json:"eventProperties,omitempty"`
+	InEventProperty    EventProperty     `json:"eventProperty,omitempty"`
+}
+
+type EventSchema struct {
+	EventProperties []EventProperties `json:"eventProperties"`
+}
+
+type DataSeries struct {
+	Total   int               `json:"total"`
+	Rows    [][]string        `json:"rows"`
+	Headers []string          `json:"http_headers"`
+	Tags    map[string]string `json:"tags"`
+}
diff --git a/streampipes-client-go/streampipes/model/data_lake/data_lake_measure.go b/streampipes-client-go/streampipes/model/data_lake/data_lake_measure.go
new file mode 100644
index 0000000000..2e1c48da45
--- /dev/null
+++ b/streampipes-client-go/streampipes/model/data_lake/data_lake_measure.go
@@ -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 data_lake
+
+import "github.com/apache/streampipes/streampipes-client-go/streampipes/model"
+
+type DataLakeMeasure struct {
+	MeasureName          string            `json:"measureName"`
+	TimestampField       string            `json:"timestampField"`
+	EventSchema          model.EventSchema `json:"eventSchema,omitempty"`
+	PipelineId           string            `json:"pipelineId,omitempty"`
+	PipelineName         string            `json:"pipelineName,omitempty"`
+	PipelineIsRunning    bool              `json:"pipelineIsRunning"`
+	SchemaVersion        string            `json:"schemaVersion,omitempty"`
+	SchemaUpdateStrategy string            `json:"schemaUpdateStrategy,omitempty"`
+	ElementId            string            `json:"elementId"`
+}
diff --git a/streampipes-client-go/streampipes/model/data_lake/data_series.go b/streampipes-client-go/streampipes/model/data_lake/data_series.go
new file mode 100644
index 0000000000..b273b42280
--- /dev/null
+++ b/streampipes-client-go/streampipes/model/data_lake/data_series.go
@@ -0,0 +1,52 @@
+//
+// 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 data_lake
+
+import (
+	"fmt"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/model"
+	"log"
+	"strings"
+)
+
+type DataSeries struct {
+	Total         int                `json:"total"`
+	Headers       []string           `json:"http_headers"`
+	AllDataSeries []model.DataSeries `json:"allDataSeries"`
+	SPQueryStatus string             `alias:"spQueryStatus" default:"OK"`
+	ForId         interface{}        `json:"forId"`
+}
+
+func (d *DataSeries) Print() {
+	if d.Total == 0 {
+		log.Println("This DataSeries has no data")
+		return
+	}
+	fmt.Printf("There are %d pieces of DataSerie in the Dataseries\n", d.Total)
+	for i := 0; i < d.Total; i++ {
+		fmt.Printf("The %d DataSeries\n", i+1)
+		headers := strings.Join(d.Headers, "                   ")
+		fmt.Printf("%s\n", headers)
+		for j := 0; j < d.AllDataSeries[i].Total; j++ {
+			singleLine := strings.Join(d.AllDataSeries[i].Rows[j], "   ")
+			fmt.Printf("%s\n",
+				singleLine,
+			)
+		}
+	}
+}
diff --git a/streampipes-client-go/streampipes/streampipes_client.go b/streampipes-client-go/streampipes/streampipes_client.go
new file mode 100644
index 0000000000..3c6ea098e1
--- /dev/null
+++ b/streampipes-client-go/streampipes/streampipes_client.go
@@ -0,0 +1,68 @@
+//
+// 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 streampipes
+
+import (
+	"errors"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/config"
+	"github.com/apache/streampipes/streampipes-client-go/streampipes/utils"
+	"net/url"
+	"strings"
+)
+
+// This is the central point of contact with StreamPipes and provides all the functionalities to interact with it.
+// The client provides so-called "API", each of which refers to the endpoint of the StreamPipes API.
+// e.g. `DataLakeMeasure` provides the actual methods to interact with StreamPipes API.
+
+type StreamPipesClient struct {
+	config config.StreamPipesClientConfig
+}
+
+// NewStreamPipesClient returns an instance of *StreamPipesClient
+// Currently, it does not support HTTPS connections or connections to port 443.
+func NewStreamPipesClient(c config.StreamPipesClientConfig) (*StreamPipesClient, error) {
+
+	if c.Credential == (config.StreamPipesApiKeyCredentials{}) {
+		return nil, errors.New("no credential entered")
+	}
+
+	if !utils.CheckUrl(c.Url) {
+		return nil, errors.New("please check if the URL is correct,Must be in the form of A://B:C," +
+			"where A is either HTTP, not case sensitive. B must be the host and C must be the port")
+	}
+
+	Url, err := url.Parse(c.Url)
+	if err != nil {
+		return nil, err
+	}
+
+	if strings.EqualFold(Url.Scheme, "https") || Url.Port() == "443" {
+		return nil, errors.New(
+			"The URL passed in is invalid and does not support HTTPS or port 443.\n ")
+	}
+
+	return &StreamPipesClient{
+		c,
+	}, nil
+
+}
+
+func (s *StreamPipesClient) DataLakeMeasures() *DataLakeMeasure {
+
+	return NewDataLakeMeasures(s.config)
+}
diff --git a/streampipes-client-go/streampipes/utils/check_url.go b/streampipes-client-go/streampipes/utils/check_url.go
new file mode 100644
index 0000000000..d3a47431a3
--- /dev/null
+++ b/streampipes-client-go/streampipes/utils/check_url.go
@@ -0,0 +1,25 @@
+//
+// 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 utils
+
+import "regexp"
+
+func CheckUrl(url string) bool {
+	re := regexp.MustCompile(`(?i)^(http|https):\/\/[^\s\/:]+:\d+$`)
+	return re.MatchString(url)
+}
diff --git a/streampipes-client-go/streampipes/utils/check_url_test.go b/streampipes-client-go/streampipes/utils/check_url_test.go
new file mode 100644
index 0000000000..adb1f551d5
--- /dev/null
+++ b/streampipes-client-go/streampipes/utils/check_url_test.go
@@ -0,0 +1,52 @@
+//
+// 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 utils
+
+import (
+	"testing"
+)
+
+func TestCheckUrl(t *testing.T) {
+	tests := []struct {
+		name     string
+		url      string
+		expected bool
+	}{
+		{name: "Valid HTTP URL", url: "http://streampipes.com:80", expected: true},
+		{name: "Valid HTTP URL", url: "http://localhost:80", expected: true},
+		{name: "Valid HTTP URL", url: "http://127.0.0.1:80", expected: true},
+		{name: "Valid HTTPS URL", url: "https://streampipes.com:443", expected: true},
+		{name: "Valid URL with port", url: "http://streampipes.com:8080", expected: true},
+		{name: "Valid URL with IPv6", url: "http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]:80", expected: false},
+		{name: "Invalid URL scheme", url: "ftp://streampipes.com:80", expected: false},
+		{name: "Invalid URL with no port", url: "http://streampipes.com", expected: false},
+		{name: "Invalid URL with space", url: "http://streampipes.com: 80", expected: false},
+		{name: "Invalid URL with special character", url: "http://streampipes.com:$80", expected: false},
+		{name: "Empty URL", url: "", expected: false},
+		{name: "Nil URL", url: "", expected: false},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			actual := CheckUrl(test.url)
+			if actual != test.expected {
+				t.Errorf("CheckUrl(%s) = %v; want %v", test.url, actual, test.expected)
+			}
+		})
+	}
+}