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

Commit

Permalink
Merge pull request #228 from suzuki-shunsuke/feat/issue-227
Browse files Browse the repository at this point in the history
Support any type of dashboard widget by JSON string
  • Loading branch information
suzuki-shunsuke committed Jan 15, 2020
2 parents 44a5fb8 + ff70236 commit 835f570
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 43 deletions.
4 changes: 4 additions & 0 deletions dashboard_widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,7 @@ func (cfg *WidgetConfigUnknownType) Type() string {
func (cfg *WidgetConfigUnknownType) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &cfg.Fields)
}

func (cfg *WidgetConfigUnknownType) MarshalJSON() ([]byte, error) {
return json.Marshal(&cfg.Fields)
}
96 changes: 77 additions & 19 deletions dashboard_widget_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,31 @@ import (
"testing"

"github.com/stretchr/testify/require"
"github.com/suzuki-shunsuke/go-jsoneq/jsoneq"
"github.com/suzuki-shunsuke/go-ptr"
)

func TestWidget_MarshalJSON(t *testing.T) {
widget := &Widget{
Description: "Stream search result count",
Config: &WidgetConfigStreamSearchResultCount{
Timerange: &Timerange{
Type: "relative",
Range: 300,
data := []struct {
title string
widget *Widget
exp string
}{
{
title: "stream search result count",
widget: &Widget{
Description: "Stream search result count",
Config: &WidgetConfigStreamSearchResultCount{
Timerange: &Timerange{
Type: "relative",
Range: 300,
},
LowerIsBetter: true,
Trend: true,
StreamID: "000000000000000000000001",
},
CacheTime: ptr.PInt(10),
},
LowerIsBetter: true,
Trend: true,
StreamID: "000000000000000000000001",
},
CacheTime: ptr.PInt(10),
}
d, err := widget.MarshalJSON()
require.Nil(t, err)
b, err := jsoneq.Equal(d, []byte(`{
exp: `{
"type": "STREAM_SEARCH_RESULT_COUNT",
"description": "Stream search result count",
"config": {
Expand All @@ -38,7 +42,61 @@ func TestWidget_MarshalJSON(t *testing.T) {
"stream_id": "000000000000000000000001"
},
"cache_time": 10
}`))
require.Nil(t, err)
require.True(t, b)
}`,
},
{
title: "stacked chart",
widget: &Widget{
Description: "stacked chart",
Config: &WidgetConfigUnknownType{
T: "STACKED_CHART",
Fields: map[string]interface{}{
"interval": "hour",
"timerange": map[string]interface{}{
"type": "relative",
"range": 86400,
},
"renderer": "bar",
"interpolation": "linear",
"series": []map[string]interface{}{
{
"query": "",
"field": "AccessMask",
"statistical_function": "count",
},
},
},
},
CacheTime: ptr.PInt(10),
},
exp: `{
"type": "STACKED_CHART",
"description": "stacked chart",
"config": {
"interval": "hour",
"timerange": {
"type": "relative",
"range": 86400
},
"renderer": "bar",
"interpolation": "linear",
"series": [
{
"query": "",
"field": "AccessMask",
"statistical_function": "count"
}
]
},
"cache_time": 10
}`,
},
}
for _, d := range data {
t.Run(d.title, func(t *testing.T) {
w, err := d.widget.MarshalJSON()
require.Nil(t, err)
require.JSONEq(t, d.exp, string(w))
})
}
}
26 changes: 5 additions & 21 deletions terraform/docs/dashboard_widget.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,6 @@
* [Example](https://github.com/suzuki-shunsuke/go-graylog/blob/master/terraform/example/v0.12/dashboard.tf)
* [Source code](https://github.com/suzuki-shunsuke/go-graylog/blob/master/terraform/graylog/resource_dashboard_widget.go)

```hcl
resource "graylog_dashboard_widget" "test" {
description = "Stream search result count"
dashboard_id = "5b6586000000000000000000"
type = "STREAM_SEARCH_RESULT_COUNT"
stream_search_result_count_configuration {
timerange {
type = "relative"
range = 300
}
stream_id = "5b3983000000000000000000"
query = ""
}
cache_time = 10
}
```

## Supported types

* STREAM_SEARCH_RESULT_COUNT
Expand All @@ -29,11 +12,12 @@ resource "graylog_dashboard_widget" "test" {
* FIELD_CHART
* STATS_COUNT

## Unsupported types
## `json_configuration`

From v10.0.0, the attribute `json_configuration` is added to support any type of dashboard widget.
`json_configuration` should be JSON string.

* STACKED_CHART
* SEARCH_RESULT_COUNT
* etc
Please see the [Example](https://github.com/suzuki-shunsuke/go-graylog/blob/master/terraform/example/v0.12/dashboard.tf).

## Common required arguments

Expand Down
25 changes: 25 additions & 0 deletions terraform/example/v0.12/dashboard.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,28 @@ resource "graylog_dashboard_widget_positions" "test" {
width = 2
}
}

resource "graylog_dashboard_widget" "stacked_chart" {
description = "stacked chart"
dashboard_id = graylog_dashboard.test.id
type = "STACKED_CHART"
cache_time = 10
json_configuration = <<EOF
{
"interval": "hour",
"timerange": {
"type": "relative",
"range": 86400
},
"renderer": "bar",
"interpolation": "linear",
"series": [
{
"query": "",
"field": "AccessMask",
"statistical_function": "count"
}
]
}
EOF
}
50 changes: 47 additions & 3 deletions terraform/graylog/resource_dashboard_widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package graylog

import (
"context"
"encoding/json"
"errors"
"fmt"

"github.com/hashicorp/terraform/helper/schema"
"github.com/suzuki-shunsuke/go-jsoneq/jsoneq"
"github.com/suzuki-shunsuke/go-ptr"

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

func resourceDashboardWidget() *schema.Resource {
Expand Down Expand Up @@ -48,6 +51,13 @@ func resourceDashboardWidget() *schema.Resource {
Computed: true,
},

"json_configuration": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: schemaDiffSuppressJSONString,
ValidateFunc: wrapValidateFunc(validateFuncDashboardWidgetJSONConfiguration),
},

"quick_values_configuration": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -286,6 +296,18 @@ func resourceDashboardWidget() *schema.Resource {
}
}

func validateFuncDashboardWidgetJSONConfiguration(v interface{}, k string) error {
c, err := jsoneq.ConvertByte([]byte(v.(string)))
if err != nil {
return fmt.Errorf("'json_configuration' must be a JSON string: %w", err)
}
_, ok := c.(map[string]interface{})
if !ok {
return errors.New("'json_configuration' should be a JSON string which represents object")
}
return nil
}

func timeRangeSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Expand Down Expand Up @@ -428,7 +450,22 @@ func newDashboardWidget(d *schema.ResourceData) (*graylog.Widget, string, error)
Relative: cfg["relative"].(int),
}
default:
return nil, "", errors.New("unsupported type: " + t)
v, ok := d.GetOk("json_configuration")
if !ok {
return nil, "", fmt.Errorf("for unknown type '%s', 'json_configuration' is required", t)
}
c, err := jsoneq.ConvertByte([]byte(v.(string)))
if err != nil {
return nil, "", fmt.Errorf("failed to parse the 'json_configuration'. 'json_configuration' must be a JSON string '%s': %w", v.(string), err)
}
fields, ok := c.(map[string]interface{})
if !ok {
return nil, "", errors.New("'json_configuration' should be a JSON string which represents object")
}
config = &graylog.WidgetConfigUnknownType{
T: t,
Fields: fields,
}
}
return &graylog.Widget{
Description: d.Get("description").(string),
Expand Down Expand Up @@ -598,7 +635,14 @@ func resourceDashboardWidgetRead(d *schema.ResourceData, m interface{}) error {
return err
}
default:
return errors.New("unsupported type: " + widget.Type())
w := widget.Config.(*graylog.WidgetConfigUnknownType)
b, err := json.Marshal(w.Fields)
if err != nil {
return fmt.Errorf("failed to marshal fields: %w", err)
}
if err := d.Set("json_configuration", string(b)); err != nil {
return err
}
}
return setStrToRD(d, "creator_user_id", widget.CreatorUserID)
}
Expand Down

0 comments on commit 835f570

Please sign in to comment.