Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add example server #330

Merged
merged 1 commit into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/examples.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Examples

on:
pull_request:
push:
branches:
- 0.*.x
workflow_dispatch:

jobs:
Server:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./examples/server
steps:
- uses: actions/checkout@v3

- name: Setup golang environment
uses: actions/setup-go@v3
with:
go-version: '1.18.4'

- name: Install dependencies
run: go mod download

- name: Run test case
run: go test .
5 changes: 5 additions & 0 deletions examples/server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Example server

1. [download](https://go.dev/dl/) and install `go compiler`
2. Run the demo application `go run main.go`
3. Add a data source in grafana. The URL value is the address of the demo service, for example: `http://localhost:8181/api/grafana/json/`
11 changes: 11 additions & 0 deletions examples/server/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/simPod/GrafanaJsonDatasource/examples/server

go 1.18

require github.com/stretchr/testify v1.8.0

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
15 changes: 15 additions & 0 deletions examples/server/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
102 changes: 102 additions & 0 deletions examples/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package main

import (
"encoding/json"
"log"
"net/http"
)

func newHandler() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/api/grafana/json", hello)
mux.HandleFunc("/api/grafana/json/search", getSearch)
mux.HandleFunc("/api/grafana/json/options", getOptions)
return mux
}

func main() {
log.Println("grafana api: /api/grafana/json")
log.Println("listen 0.0.0.0:8081")
http.ListenAndServe(":8181", newHandler())
}

var defaultMetrics = `
[{
"text": "Lorem",
"value": "a"
},{
"text": "Ipsum",
"value": "b"
}]
`

type MetricsRequest struct {
Metric string `json:"metric"`
Payload map[string]interface{} `json:"payload"`
}

func getSearch(writer http.ResponseWriter, request *http.Request) {
var req MetricsRequest
err := json.NewDecoder(request.Body).Decode(&req)
if err != nil {
writer.WriteHeader(500)
return
}
writer.Header().Set("content-type", "application/json")
writer.Write([]byte(defaultMetrics))
}

type OptionsRequest struct {
Name string `json:"name"`
Metric string `json:"metric"`
Payload map[string]interface{} `json:"payload"`
}

func getOptions(writer http.ResponseWriter, request *http.Request) {
var req OptionsRequest
err := json.NewDecoder(request.Body).Decode(&req)
if err != nil {
writer.WriteHeader(500)
return
}
writer.Header().Set("content-type", "application/json")
switch req.Name {
case "instanceId":
writer.Write([]byte(`[{
"label": "My Database 1",
"value": "sadbip2kasdmnlo"
},{
"label": "My Database 2",
"value": "sadbip2kasdmnla"
},{
"label": "My Database 3",
"value": "sadbip2kasdmnlx"
}]`))

case "metric":
writer.Write([]byte(`[{
"label": "CPUUtilization",
"value": "CPUUtilization"
},{
"label": "DiskReadIOPS",
"value": "DiskReadIOPS"
},{
"label": "memory_freeutilization",
"value": "memory_freeutilization"
}]`))
case "namespace":
writer.Write([]byte(`[{
"label": "MongoDB",
"value": "acs_mongodb"
},{
"label": "RDS",
"value": "acs_rds"
},{
"label": "Load balancer",
"value": "acs_load_balancer"
}]`))
}
}
func hello(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("ok"))
}
64 changes: 64 additions & 0 deletions examples/server/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package main

import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/require"
)

func Test_Hello(t *testing.T) {
mux := newHandler()
server := httptest.NewServer(mux)
resp, err := http.Get(server.URL + "/api/grafana/json")
require.NoError(t, err)
require.Equal(t, resp.StatusCode, 200)
rawBody, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
require.NoError(t, err)
require.Equal(t, string(rawBody), "ok")
}

type payloadConfig struct {
Label string `json:"label"`
Name string `json:"value"`
}

type metricConfig struct {
Label string `json:"label"`
Value string `json:"value"`
Payloads []payloadConfig `json:"payloads"`
}

func Test_Metrics(t *testing.T) {
mux := newHandler()
server := httptest.NewServer(mux)
resp, err := http.Post(server.URL+"/api/grafana/json/search", "application/json", bytes.NewBuffer([]byte("{}")))
require.NoError(t, err)
require.Equal(t, resp.StatusCode, 200)
rawBody, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
require.NoError(t, err)
var metrics []metricConfig
require.NoError(t, json.Unmarshal(rawBody, &metrics))
require.Len(t, metrics, 2)
}

func Test_Options(t *testing.T) {
mux := newHandler()
server := httptest.NewServer(mux)
payload := `{"metric":"DescribeMetricList","payload":{"namespace":"acs_rds"},"name":"instanceId"}`
resp, err := http.Post(server.URL+"/api/grafana/json/options", "application/json", bytes.NewBuffer([]byte(payload)))
require.NoError(t, err)
require.Equal(t, resp.StatusCode, 200)
rawBody, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
require.NoError(t, err)
var metrics []metricConfig
require.NoError(t, json.Unmarshal(rawBody, &metrics))
require.Len(t, metrics, 3)
}