Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Commit

Permalink
feat: support Views API
Browse files Browse the repository at this point in the history
issue: #182
  • Loading branch information
suzuki-shunsuke committed Apr 16, 2020
1 parent a26bd26 commit 39c98af
Show file tree
Hide file tree
Showing 8 changed files with 618 additions and 0 deletions.
16 changes: 16 additions & 0 deletions client/endpoint/view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package endpoint

// Views returns a View API's endpoint url.
func (ep *Endpoints) Views() string {
return ep.views
}

// View returns a View API's endpoint url.
func (ep *Endpoints) View(id string) string {
return ep.views + "/" + id
}

// ViewDefault returns a View API's endpoint url.
func (ep *Endpoints) ViewDefault(id string) string {
return ep.views + "/" + id + "/default"
}
76 changes: 76 additions & 0 deletions client/view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package client

import (
"context"
"errors"

"github.com/suzuki-shunsuke/go-graylog"
)

// GetViews returns all views.
func (client *Client) GetViews(
ctx context.Context,
) (*graylog.Views, *ErrorInfo, error) {
viewsBody := &graylog.Views{}
ei, err := client.callGet(
ctx, client.Endpoints().Views(), nil, viewsBody)
return viewsBody, ei, err
}

// GetView returns a given view.
func (client *Client) GetView(
ctx context.Context, id string,
) (*graylog.View, *ErrorInfo, error) {
if id == "" {
return nil, nil, errors.New("id is empty")
}
view := &graylog.View{}
ei, err := client.callGet(ctx, client.Endpoints().View(id), nil, view)
return view, ei, err
}

// CreateView creates a view.
func (client *Client) CreateView(
ctx context.Context, view *graylog.View,
) (*ErrorInfo, error) {
// required: title search_id state
// allowed: state, search_id, owner, summary, title, created_at, id, description, requires, properties, dashboard_state
if view == nil {
return nil, errors.New("view is nil")
}
ret := map[string]string{}
ei, err := client.callPost(ctx, client.Endpoints().Views(), view, &ret)
if err != nil {
return ei, err
}
if id, ok := ret["view_id"]; ok {
view.ID = id
return ei, nil
}
return ei, errors.New(`response doesn't have the field "view_id"`)
}

// UpdateView updates a view.
func (client *Client) UpdateView(
ctx context.Context, view *graylog.View,
) (*ErrorInfo, error) {
if view == nil {
return nil, errors.New("view is nil")
}
if view.ID == "" {
return nil, errors.New("id is empty")
}
body := *view
body.ID = ""
return client.callPut(ctx, client.Endpoints().View(view.ID), &body, view)
}

// DeleteView deletes a view.
func (client *Client) DeleteView(
ctx context.Context, id string,
) (*ErrorInfo, error) {
if id == "" {
return nil, errors.New("id is empty")
}
return client.callDelete(ctx, client.Endpoints().View(id), nil, nil)
}
58 changes: 58 additions & 0 deletions client/view_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package client

import (
"context"
"io/ioutil"
"net/http"
"testing"

"github.com/stretchr/testify/require"
"github.com/suzuki-shunsuke/flute/flute"

"github.com/suzuki-shunsuke/go-graylog/testdata"
)

func TestClient_GetViews(t *testing.T) {
ctx := context.Background()

cl, err := NewClient("http://example.com/api", "admin", "admin")
require.Nil(t, err)

buf, err := ioutil.ReadFile("../testdata/views.json")
require.Nil(t, err)
bodyStr := string(buf)

cl.SetHTTPClient(&http.Client{
Transport: &flute.Transport{
T: t,
Services: []flute.Service{
{
Endpoint: "http://example.com",
Routes: []flute.Route{
{
Tester: &flute.Tester{
Method: "GET",
Path: "/api/views",
PartOfHeader: http.Header{
"Content-Type": []string{"application/json"},
"X-Requested-By": []string{"go-graylog"},
"Authorization": nil,
},
},
Response: &flute.Response{
Base: http.Response{
StatusCode: 200,
},
BodyString: bodyStr,
},
},
},
},
},
},
})

views, _, err := cl.GetViews(ctx)
require.Nil(t, err)
require.Equal(t, testdata.Views, views)
}
9 changes: 9 additions & 0 deletions cmd/generate-testdata/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ var (
"stream_alert_conditions": StreamAlertConditions{},
"outputs": Outputs{},
"stdout_output": Output{},
"views": Views{},
}
)

Expand Down Expand Up @@ -199,6 +200,10 @@ type (
EventDefinition struct {
data graylog.EventDefinition
}

Views struct {
data graylog.Views
}
)

func (users Users) dump(input string) error {
Expand Down Expand Up @@ -292,3 +297,7 @@ func (definitions EventDefinitions) dump(input string) error {
func (definition EventDefinition) dump(input string) error {
return dump(input, &definition.data)
}

func (v Views) dump(input string) error {
return dump(input, &v.data)
}
2 changes: 2 additions & 0 deletions graylog/client/endpoint/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Endpoints struct {
ldapGroupRoleMapping string
connectStreamsToPipeline string
connectPipelinesToStream string
views string
apiVersion string
}

Expand Down Expand Up @@ -96,6 +97,7 @@ func newEndpoints(endpoint, version string) (*Endpoints, error) {
users: endpoint + "/users",
grokPatterns: endpoint + "/system/grok",
grokPatternsTest: endpoint + "/system/grok/test",
views: endpoint + "/views",
apiVersion: version,
}, nil
}
121 changes: 121 additions & 0 deletions testdata/views.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package testdata

import (
"github.com/suzuki-shunsuke/go-graylog"
)

var (
Views = &graylog.Views{
Total: 1,
Page: 1,
PerPage: 50,
Count: 0,
Views: []graylog.View{
{
ID: "5d9529c175d97f58f953927a",
Title: "test",
Summary: "",
Description: "",
SearchID: "5d9529b275d97f58f9539275",
State: map[string]graylog.ViewState{
"6971d00a-e605-43fb-b873-e4bca773d286": {
SelectedFields: []string{
"source",
"message",
},
Titles: map[string]map[string]string{
"widget": {
"038b9bca-4884-496f-b1ba-bc345ad4069e": "Message Count",
"c8986792-07e0-41fa-aded-cd19c96f2789": "All Messages",
},
},
Widgets: []graylog.ViewWidget{
{
ID: "038b9bca-4884-496f-b1ba-bc345ad4069e",
Config: graylog.AggregationViewWidgetConfig{
RowPivots: []graylog.ViewWidgetRowPivot{
{
Field: "timestamp",
Type: "time",
Config: graylog.ViewWidgetRowPivotConfig{
Interval: graylog.ViewWidgetRowPivotInterval{
Type: "auto",
},
},
},
},
Series: []graylog.ViewWidgetSeries{
{
Config: graylog.ViewWidgetSeriesConfig{},
Function: "count()",
},
},
Visualization: "bar",
Rollup: true,
},
},
{
ID: "c8986792-07e0-41fa-aded-cd19c96f2789",
Config: graylog.MessagesViewWidgetConfig{
Fields: []string{
"timestamp",
"source",
},
ShowMessageRow: true,
},
},
{
ID: "41c694c8-093c-4d67-be42-06390e1c61ba",
Config: graylog.AggregationViewWidgetConfig{
RowPivots: []graylog.ViewWidgetRowPivot{},
Series: []graylog.ViewWidgetSeries{
{
Config: graylog.ViewWidgetSeriesConfig{},
Function: "count()",
},
},
Visualization: "numeric",
Rollup: true,
},
},
},
WidgetMapping: map[string][]string{
"038b9bca-4884-496f-b1ba-bc345ad4069e": {
"9b8a4a7f-9f6e-4032-afa6-e25fe24bab40",
},
"41c694c8-093c-4d67-be42-06390e1c61ba": {
"81419b6e-4d6d-4739-8883-5d34e5267091",
},
"c8986792-07e0-41fa-aded-cd19c96f2789": {
"07599874-f01e-46ae-84c4-cf724e7b0524",
},
},
Positions: map[string]graylog.ViewWidgetPosition{
"038b9bca-4884-496f-b1ba-bc345ad4069e": {
Width: "Infinity",
Col: 1,
Row: 5,
Height: 2,
},
"41c694c8-093c-4d67-be42-06390e1c61ba": {
Width: 4,
Col: 1,
Row: 1,
Height: 4,
},
"c8986792-07e0-41fa-aded-cd19c96f2789": {
Width: "Infinity",
Col: 1,
Row: 7,
Height: 6,
},
},
},
},
DashboardState: graylog.DashboardState{},
Owner: "admin",
CreatedAt: "2019-10-02T22:49:53.181Z",
},
},
}
)
Loading

0 comments on commit 39c98af

Please sign in to comment.