Repository: honeycombio/terraform-provider-honeycombio (go)

Issue:
Support Graph Settings for queries
These options don't appear to be supported by the API at the moment, but it would be nice to be able to generate graphs using these features (I was trying to terraform a graph that used stacked graphs)
<img width="263" alt="Screen Shot 2020-10-16 at 5 51 32 PM" src="https://user-images.githubusercontent.com/131809/96311801-4cc0fa00-0fd8-11eb-87c3-6c596921c512.png">


Pull request:
boards: add support for managing query graph settings
Closes #37 

---
- To see the specific tasks where the Asana app for GitHub is being used, see below:
  - https://app.asana.com/0/0/1202770981484114

Patch:
diff --git a/client/board.go b/client/board.go
index 4341afb..9243b35 100644
--- a/client/board.go
+++ b/client/board.go
@@ -89,6 +89,8 @@ type BoardQuery struct {
 	QueryID string `json:"query_id,omitempty"`
 	// Optional
 	QueryAnnotationID string `json:"query_annotation_id,omitempty"`
+	// Optional
+	GraphSettings BoardGraphSettings `json:"graph_settings"`
 }
 
 // BoardQueryStyle determines how a query should be displayed on the board.
@@ -101,6 +103,15 @@ const (
 	BoardQueryStyleCombo BoardQueryStyle = "combo"
 )
 
+// BoardGraphSettings represents the display settings for an individual graph in a board.
+type BoardGraphSettings struct {
+	OmitMissingValues bool `json:"omit_missing_values,omitempty"`
+	UseStackedGraphs  bool `json:"stacked_graphs,omitempty"`
+	UseLogScale       bool `json:"log_scale,omitempty"`
+	UseUTCXAxis       bool `json:"utc_xaxis,omitempty"`
+	HideMarkers       bool `json:"hide_markers,omitempty"`
+}
+
 // BoardQueryStyles returns an exhaustive list of board query styles.
 func BoardQueryStyles() []BoardQueryStyle {
 	return []BoardQueryStyle{BoardQueryStyleGraph, BoardQueryStyleTable, BoardQueryStyleCombo}
diff --git a/docs/resources/board.md b/docs/resources/board.md
index b10735d..80a8b32 100644
--- a/docs/resources/board.md
+++ b/docs/resources/board.md
@@ -85,6 +85,10 @@ resource "honeycombio_board" "overview" {
     caption             = "Latency by User"
     query_id            = honeycombio_query.latency_by_userid.id
     query_annotation_id = honeycombio_query_annotation.latency_by_userid.id
+
+    graph_settings {
+      utc_xaxis = true
+    }
   }
 }
 ```
@@ -105,6 +109,16 @@ Each board configuration may have zero or more `query` blocks, which accepts the
 * `query_annotation_id` - (Optional) The ID of the Query Annotation to associate with this query.
 * `dataset` - (Deprecated) The dataset this query is associated with.
 * `caption` - (Optional) A description of the query that will be displayed on the board. Supports markdown.
+* `graph_settings` - (Optional) A map of boolean toggles to manages the settings for this query's graph on the board.
+If a value is unspecified, it is assumed to be false.
+Currently supported toggles are:
+  * `hide_markers`
+  * `log_scale`
+  * `omit_missing_values`
+  * `stacked_graphs`
+  * `utc_xaxis`
+
+  See [Graph Settings](https://docs.honeycomb.io/working-with-your-data/graph-settings/) in the documentation for more information on any individual setting.
 * `query_style` - (Optional) How the query should be displayed within the board, either `graph` (the default), `table` or `combo`.
 
 ## Attribute Reference
diff --git a/example/board_with_annotations/main.tf b/example/board_with_annotations/main.tf
index 31051f7..1129623 100644
--- a/example/board_with_annotations/main.tf
+++ b/example/board_with_annotations/main.tf
@@ -63,5 +63,10 @@ EOT
     query_id            = honeycombio_query.latency_by_userid.id
     query_annotation_id = honeycombio_query_annotation.latency_by_userid.id
     query_style         = "graph"
+
+    graph_settings {
+      utc_xaxis    = true
+      hide_markers = true
+    }
   }
 }
diff --git a/honeycombio/resource_board.go b/honeycombio/resource_board.go
index 1e77cfc..38f080e 100644
--- a/honeycombio/resource_board.go
+++ b/honeycombio/resource_board.go
@@ -59,6 +59,49 @@ func newBoard() *schema.Resource {
 							Computed:     true,
 							ValidateFunc: validation.StringInSlice(boardQueryStyleStrings(), false),
 						},
+						"graph_settings": {
+							Type:     schema.TypeList,
+							MinItems: 1,
+							MaxItems: 1,
+							Computed: true,
+							Optional: true,
+							Description: `Manages the settings for this query's graph on the board.
+See [Graph Settings](https://docs.honeycomb.io/working-with-your-data/graph-settings/) in the documentation for more information.`,
+							Elem: &schema.Resource{
+								Schema: map[string]*schema.Schema{
+									"log_scale": {
+										Type:        schema.TypeBool,
+										Computed:    true,
+										Optional:    true,
+										Description: "Set the graph's Y axis to Log scale.",
+									},
+									"omit_missing_values": {
+										Type:        schema.TypeBool,
+										Computed:    true,
+										Optional:    true,
+										Description: "Enable interpolatation between datapoints when the interveneing time buckets have no matching events.",
+									},
+									"hide_markers": {
+										Type:        schema.TypeBool,
+										Computed:    true,
+										Optional:    true,
+										Description: "Disable the overlay of Markers on the graph.",
+									},
+									"stacked_graphs": {
+										Type:        schema.TypeBool,
+										Computed:    true,
+										Optional:    true,
+										Description: "Enable the display of groups as stacked colored area under their line graphs.",
+									},
+									"utc_xaxis": {
+										Type:        schema.TypeBool,
+										Computed:    true,
+										Optional:    true,
+										Description: "Set the graph's X axis to UTC.",
+									},
+								},
+							},
+						},
 						"dataset": {
 							Type:       schema.TypeString,
 							Optional:   true,
@@ -121,6 +164,7 @@ func resourceBoardRead(ctx context.Context, d *schema.ResourceData, meta interfa
 			"caption":             q.Caption,
 			"query_style":         q.QueryStyle,
 			"dataset":             q.Dataset,
+			"graph_settings":      flattenBoardQueryGraphSettings(q.GraphSettings),
 			"query_id":            q.QueryID,
 			"query_annotation_id": q.QueryAnnotationID,
 		}
@@ -159,15 +203,24 @@ func resourceBoardDelete(ctx context.Context, d *schema.ResourceData, meta inter
 }
 
 func expandBoard(d *schema.ResourceData) (*honeycombio.Board, error) {
+	var err error
 	var queries []honeycombio.BoardQuery
 
 	qs := d.Get("query").([]interface{})
 	for _, q := range qs {
 		m := q.(map[string]interface{})
 
+		var graphSettings honeycombio.BoardGraphSettings
+		if v, ok := m["graph_settings"]; ok {
+			graphSettings, err = expandBoardQueryGraphSettings(v)
+			if err != nil {
+				return nil, err
+			}
+		}
 		queries = append(queries, honeycombio.BoardQuery{
 			Caption:           m["caption"].(string),
 			QueryStyle:        honeycombio.BoardQueryStyle(m["query_style"].(string)),
+			GraphSettings:     graphSettings,
 			Dataset:           m["dataset"].(string),
 			QueryID:           m["query_id"].(string),
 			QueryAnnotationID: m["query_annotation_id"].(string),
@@ -188,3 +241,47 @@ func expandBoard(d *schema.ResourceData) (*honeycombio.Board, error) {
 	}
 	return board, nil
 }
+
+func expandBoardQueryGraphSettings(gs interface{}) (honeycombio.BoardGraphSettings, error) {
+	graphSettings := honeycombio.BoardGraphSettings{}
+	raw := gs.([]interface{})
+	if len(raw) == 0 {
+		return graphSettings, nil
+	}
+	if len(raw) > 1 {
+		return graphSettings, errors.New("got more than one set of graph settings?")
+	}
+	s := raw[0].(map[string]interface{})
+
+	if v, ok := s["log_scale"].(bool); ok && v {
+		graphSettings.UseLogScale = true
+	}
+	if v, ok := s["omit_missing_values"].(bool); ok && v {
+		graphSettings.OmitMissingValues = true
+	}
+	if v, ok := s["hide_markers"].(bool); ok && v {
+		graphSettings.HideMarkers = true
+	}
+	if v, ok := s["stacked_graphs"].(bool); ok && v {
+		graphSettings.UseStackedGraphs = true
+	}
+	if v, ok := s["utc_xaxis"].(bool); ok && v {
+		graphSettings.UseUTCXAxis = true
+	}
+
+	return graphSettings, nil
+}
+
+func flattenBoardQueryGraphSettings(gs honeycombio.BoardGraphSettings) []map[string]interface{} {
+	result := make([]map[string]interface{}, 0)
+
+	result = append(result, map[string]interface{}{
+		"hide_markers":        gs.HideMarkers,
+		"log_scale":           gs.UseLogScale,
+		"omit_missing_values": gs.OmitMissingValues,
+		"stacked_graphs":      gs.UseStackedGraphs,
+		"utc_xaxis":           gs.UseUTCXAxis,
+	})
+
+	return result
+}


Test patch:
diff --git a/client/board_test.go b/client/board_test.go
index 041547f..bbef1a9 100644
--- a/client/board_test.go
+++ b/client/board_test.go
@@ -37,10 +37,11 @@ func TestBoards(t *testing.T) {
 			ColumnLayout: BoardColumnStyleSingle,
 			Queries: []BoardQuery{
 				{
-					Caption:    "A sample query",
-					QueryStyle: BoardQueryStyleCombo,
-					Dataset:    dataset,
-					QueryID:    *query.ID,
+					Caption:       "A sample query",
+					QueryStyle:    BoardQueryStyleCombo,
+					Dataset:       dataset,
+					QueryID:       *query.ID,
+					GraphSettings: BoardGraphSettings{OmitMissingValues: true, UseUTCXAxis: true},
 				},
 			},
 		}
@@ -82,9 +83,10 @@ func TestBoards(t *testing.T) {
 		assert.NoError(t, err)
 		b.ColumnLayout = BoardColumnStyleMulti
 		b.Queries = append(b.Queries, BoardQuery{
-			Caption:    "A second query",
-			QueryStyle: BoardQueryStyleGraph,
-			QueryID:    *newQuery.ID,
+			Caption:       "A second query",
+			QueryStyle:    BoardQueryStyleGraph,
+			QueryID:       *newQuery.ID,
+			GraphSettings: BoardGraphSettings{UseUTCXAxis: true},
 		})
 
 		result, err := c.Boards.Update(ctx, b)
diff --git a/honeycombio/resource_board_test.go b/honeycombio/resource_board_test.go
index 52db03d..432bc2c 100644
--- a/honeycombio/resource_board_test.go
+++ b/honeycombio/resource_board_test.go
@@ -27,6 +27,7 @@ func TestAccHoneycombioBoard_basic(t *testing.T) {
 					resource.TestCheckResourceAttr("honeycombio_board.test", "query.#", "2"),
 					resource.TestCheckResourceAttr("honeycombio_board.test", "query.0.caption", "test query 0"),
 					resource.TestCheckResourceAttr("honeycombio_board.test", "query.0.dataset", dataset),
+					resource.TestCheckResourceAttr("honeycombio_board.test", "query.0.graph_settings.0.utc_xaxis", "true"),
 					resource.TestCheckResourceAttrPair("honeycombio_board.test", "query.0.query_id", "honeycombio_query.test.0", "id"),
 					resource.TestCheckResourceAttrPair("honeycombio_board.test", "query.0.query_annotation_id", "honeycombio_query_annotation.test.0", "id"),
 					resource.TestCheckResourceAttr("honeycombio_board.test", "query.1.caption", "test query 1"),
@@ -66,6 +67,10 @@ resource "honeycombio_board" "test" {
 
   query {
     query_id = honeycombio_query.test.id
+
+    graph_settings {
+      log_scale = true
+    }
   }
 }
 `, dataset),
@@ -142,6 +147,10 @@ resource "honeycombio_board" "test" {
     dataset             = "%s"
     query_id            = honeycombio_query.test[0].id
     query_annotation_id = honeycombio_query_annotation.test[0].id
+
+    graph_settings {
+      utc_xaxis = true
+    }
   }
   query {
     caption             = "test query 1"