Repository: honeycombio/terraform-provider-honeycombio (language: python)

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">



Discussion / hints:
Support for managing board query graph settings just went to production. Unblocking this to be picked up shortly.

Fix patch:
diff --git a/client/board.go b/client/board.go
index 4341afbb..9243b35a 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 b10735d1..80a8b32e 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 31051f71..1129623c 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 1e77cfc2..38f080ec 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 041547f9..bbef1a9c 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 52db03d3..432bc2ce 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"