Skip to content

Commit

Permalink
feat: add example server
Browse files Browse the repository at this point in the history
Co-authored-by: Simon Podlipsky <[email protected]>
  • Loading branch information
MicroOps-cn and simPod committed Oct 11, 2022
1 parent 90c9232 commit bcd3ea3
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 0 deletions.
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)
}

0 comments on commit bcd3ea3

Please sign in to comment.