Skip to content

Commit

Permalink
Merge pull request #42 from Enapter/ym/panel-2.0
Browse files Browse the repository at this point in the history
Enapter commands panel v2
  • Loading branch information
guuhuu authored Jan 30, 2024
2 parents 50fc741 + ee82d1a commit b37c27e
Show file tree
Hide file tree
Showing 63 changed files with 3,442 additions and 739 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ PLUGINS ?= $(shell find . -path './*/src/plugin.json' \

.PHONY: $(PLUGINS)
$(PLUGINS):
rm --recursive --force ./$@/dist
rm -rf ./$@/dist
$(DOCKER_BUILD) \
--output ./$@/dist \
./$@

enapter-grafana-plugins.tar.gz: $(PLUGINS)
rm --force $@
rm -f $@
tar --create --gzip --file $@ $(addsuffix /dist,$^)

GRAFANA_TAG ?= enapter/grafana-plugins:dev
Expand Down
34 changes: 19 additions & 15 deletions enapter-api-datasource/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
# Changelog

## v7.1.0

- Handle device manifest queries.

## v7.0.1

- Fix resetting Enapter API URL in datasource config editor
- Fix resetting Enapter API URL in datasource config editor.

## v7.0.0

- Rename project
- Fix commands-api client URL usage
- Rename project.
- Fix commands-api client URL usage.

## v6.0.0

- Add support for executing commands
- Make labels unique only for a single query
- Add support for executing commands.
- Make labels unique only for a single query.

## v5.1.1

- Fix the link to example dashboard in README
- Fix plugin name and author
- Add plugin description
- Fix the link to example dashboard in README.
- Fix plugin name and author.
- Add plugin description.

## v5.1.0

- Extend supported platforms
- Fix the name of executable
- Extend supported platforms.
- Fix the name of executable.

## v5.0.2

- Fix timestamp formatting to avoid losing milliseconds.

## v5.0.1

- Upgrade `grafana-plugin-sdk-go`
- Upgrade `grafana-plugin-sdk-go`.

## v5.0.0

Expand All @@ -50,15 +54,15 @@

## v4.2.0

- Default aggregation to `auto`
- Default aggregation to `auto`.

## v4.1.0

- Add default granularity
- Add default granularity.

## v4.0.1

- Rename Telemetry API token to Enapter API token
- Rename Telemetry API token to Enapter API token.

## v4.0.0

Expand Down Expand Up @@ -94,7 +98,7 @@

## v1.2.6

- Smart labels
- Smart labels.

## v1.2.5

Expand Down
1 change: 1 addition & 0 deletions enapter-api-datasource/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ RUN --mount=type=cache,target=node_modules npm run build
FROM golang:1.20-alpine AS backend

RUN apk add --no-cache --virtual .build-deps \
binutils-gold \
git \
build-base \
&& go install github.com/magefile/[email protected] \
Expand Down
2 changes: 1 addition & 1 deletion enapter-api-datasource/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/Enapter/grafana-plugins
go 1.19

require (
github.com/Enapter/http-api-go-client v0.0.3
github.com/Enapter/http-api-go-client v0.0.9
github.com/bxcodec/faker/v3 v3.6.0
github.com/grafana/grafana-plugin-sdk-go v0.162.0
github.com/hashicorp/go-hclog v1.5.0
Expand Down
14 changes: 12 additions & 2 deletions enapter-api-datasource/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,20 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Enapter/http-api-go-client v0.0.2 h1:ELwet4EKNlp7YqvTUf9LBH8HS+Ii1svn/E5Zac9zELY=
github.com/Enapter/http-api-go-client v0.0.2/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/Enapter/http-api-go-client v0.0.3 h1:Q3CPYiqCCiwXaGwYEVMV/yO1x+c0ZGiPxckpYViLsgU=
github.com/Enapter/http-api-go-client v0.0.3/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/Enapter/http-api-go-client v0.0.4 h1:XTfEUy92XbwFqaOzID2R+vPZHROXtHglImELhuMnPC8=
github.com/Enapter/http-api-go-client v0.0.4/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/Enapter/http-api-go-client v0.0.5 h1:jyy5lNw8vxTMjE0tu1vgixhLWxHXESgT0YHU0kxjIVE=
github.com/Enapter/http-api-go-client v0.0.5/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/Enapter/http-api-go-client v0.0.6 h1:uUlBCF24RAvtZ+jsd1GDZoHykiKbKWtrOoqM+eJmEQk=
github.com/Enapter/http-api-go-client v0.0.6/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/Enapter/http-api-go-client v0.0.7 h1:IYu2fRwlHIfnFw3O3rfF7Fmt+TJb2HxKBdfh7o/QR0Q=
github.com/Enapter/http-api-go-client v0.0.7/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/Enapter/http-api-go-client v0.0.8 h1:VAwSLXrqrgpOK86L1gHvNWK1BowkGkrAQMHqvN7wM0Q=
github.com/Enapter/http-api-go-client v0.0.8/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/Enapter/http-api-go-client v0.0.9 h1:qN4gUv4XQDapVfKW728sCJdwntz7xjDwq/SADw0yEXk=
github.com/Enapter/http-api-go-client v0.0.9/go.mod h1:0iLidjPmLzZqqwYR1DE8Q8Ccb++ovLQVZpVPjplCF6s=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
Expand Down
2 changes: 1 addition & 1 deletion enapter-api-datasource/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "enapter-api",
"version": "7.0.1",
"version": "7.1.0",
"description": "Enapter API Grafana Datasource Plugin",
"scripts": {
"build": "grafana-toolkit plugin:build",
Expand Down
114 changes: 114 additions & 0 deletions enapter-api-datasource/pkg/assetsapi/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package assetsapi

import (
"context"
"errors"
"fmt"
"net/http"
"time"

enapterhttp "github.com/Enapter/http-api-go-client/pkg/client"

"github.com/Enapter/grafana-plugins/pkg/httperr"
)

type (
Device = enapterhttp.Device
ExpandDeviceParams = enapterhttp.ExpandDeviceParams
)

type Client interface {
DeviceByID(context.Context, DeviceByIDParams) (*Device, error)
}

type client struct {
apiURL string
token string
timeout time.Duration
}

type ClientParams struct {
APIURL string
Token string
Timeout time.Duration
}

const DefaultTimeout = 15 * time.Second

func NewClient(p ClientParams) Client {
if p.Timeout == 0 {
p.Timeout = DefaultTimeout
}

return &client{
apiURL: p.APIURL,
token: p.Token,
timeout: p.Timeout,
}
}

type DeviceByIDParams struct {
User string
DeviceID string
Expand ExpandDeviceParams
}

func (c *client) DeviceByID(
ctx context.Context, p DeviceByIDParams,
) (*Device, error) {
enapterHTTPClient, err := c.newEnapterHTTPClient(p.User)
if err != nil {
return nil, fmt.Errorf("new Enapter HTTP client: %w", err)
}

resp, err := enapterHTTPClient.Assets.DeviceByID(ctx, enapterhttp.DeviceByIDQuery{
ID: p.DeviceID,
Expand: p.Expand,
})
if err != nil {
if respErr := (enapterhttp.ResponseError{}); errors.As(err, &respErr) {
return nil, c.respErrorToMultiError(respErr)
}
return nil, fmt.Errorf("do: %w", err)
}

return &resp.Device, nil
}

func (c *client) respErrorToMultiError(respErr enapterhttp.ResponseError) error {
if len(respErr.Errors) == 0 {
return respErr
}

multiErr := new(httperr.MultiError)

for _, e := range respErr.Errors {
if len(e.Code) == 0 {
e.Code = "<empty>"
}
multiErr.Errors = append(multiErr.Errors, httperr.Error{
Code: e.Code,
Message: e.Message,
Details: e.Details,
})
}

return multiErr
}

func (c *client) newEnapterHTTPClient(user string) (*enapterhttp.Client, error) {
transport := http.DefaultTransport

if c.token != "" {
transport = enapterhttp.NewAuthTokenTransport(transport, c.token)
}

if user != "" {
transport = enapterhttp.NewAuthUserTransport(transport, user)
}

return enapterhttp.NewClientWithURL(&http.Client{
Timeout: c.timeout,
Transport: transport,
}, c.apiURL)
}
8 changes: 7 additions & 1 deletion enapter-api-datasource/pkg/plugin/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/hashicorp/go-hclog"

"github.com/Enapter/grafana-plugins/pkg/assetsapi"
"github.com/Enapter/grafana-plugins/pkg/commandsapi"
"github.com/Enapter/grafana-plugins/pkg/plugin/internal/handlers"
"github.com/Enapter/grafana-plugins/pkg/telemetryapi"
Expand Down Expand Up @@ -55,8 +56,13 @@ func newDataSource(logger hclog.Logger, settings backend.DataSourceInstanceSetti
Token: apiToken,
})

assetsAPIClient := assetsapi.NewClient(assetsapi.ClientParams{
APIURL: apiURL,
Token: apiToken,
})

queryDataHandler := handlers.NewQueryData(
logger, telemetryAPIClient, commandsAPIClient)
logger, telemetryAPIClient, commandsAPIClient, assetsAPIClient)
checkHealthHandler := handlers.NewCheckHealth(logger, telemetryAPIClient)

logger.Info("created new data source")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package handlers

import "errors"

var errUnsupportedTimeseriesDataType = errors.New("unsupported timeseries data type")
var (
errUnsupportedTimeseriesDataType = errors.New("unsupported timeseries data type")
errUnexpectedQueryType = errors.New("unexpected query type")
)

//nolint:stylecheck,revive // user-facing
var (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package handlers_test

import (
"context"

"github.com/stretchr/testify/suite"

"github.com/Enapter/grafana-plugins/pkg/assetsapi"
)

var _ assetsapi.Client = (*MockAssetsAPIClient)(nil)

type MockAssetsAPIClient struct {
suite *suite.Suite
deviceByIDHandler func(assetsapi.DeviceByIDParams) (*assetsapi.Device, error)
}

func NewMockAssetsAPIClient(s *suite.Suite) *MockAssetsAPIClient {
c := new(MockAssetsAPIClient)
c.suite = s
c.deviceByIDHandler = c.unexpectedCall
return c
}

func (c *MockAssetsAPIClient) ExpectDeviceByIDAndReturn(
wantP assetsapi.DeviceByIDParams,
device *assetsapi.Device, err error,
) {
c.deviceByIDHandler = func(haveP assetsapi.DeviceByIDParams) (
*assetsapi.Device, error,
) {
defer func() { c.deviceByIDHandler = c.unexpectedCall }()
c.suite.Require().Equal(wantP, haveP)
return device, err
}
}

func (c *MockAssetsAPIClient) DeviceByID(
_ context.Context, p assetsapi.DeviceByIDParams,
) (*assetsapi.Device, error) {
return c.deviceByIDHandler(p)
}

func (c *MockAssetsAPIClient) unexpectedCall(assetsapi.DeviceByIDParams) (
*assetsapi.Device, error,
) {
c.suite.Require().FailNow("unexpected call")
//nolint: nilnil // unreachable
return nil, nil
}

func (c *MockAssetsAPIClient) Ready(context.Context) error { return nil }
func (c *MockAssetsAPIClient) Close() {}
Loading

0 comments on commit b37c27e

Please sign in to comment.