diff --git a/.go-version b/.go-version index 9141007..acbb747 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.96.0 +1.97.0 diff --git a/client/metric_dashboards.go b/client/metric_dashboards.go index 177d648..62c5ada 100644 --- a/client/metric_dashboards.go +++ b/client/metric_dashboards.go @@ -22,6 +22,7 @@ type UnifiedDashboardAttributes struct { Labels []Label `json:"labels"` TemplateVariables []TemplateVariable `json:"template_variables"` EventQueryIDs []string `json:"event_query_ids"` + WorkflowLinks []WorkflowLink `json:"workflow_links"` } type UnifiedGroup struct { @@ -53,6 +54,7 @@ type UnifiedChart struct { Text string `json:"text"` Thresholds []Threshold `json:"thresholds"` Subtitle *string `json:"subtitle,omitempty"` + WorkflowLinks []WorkflowLink `json:"workflow_links"` } type Label struct { @@ -93,6 +95,11 @@ type TemplateVariable struct { SuggestionAttributeKey string `json:"suggestion_attribute_key"` } +type WorkflowLink struct { + Name string `json:"name"` + URL string `json:"url"` +} + func getUnifiedDashboardURL(project, id string) string { path := fmt.Sprintf( "projects/%s/metric_dashboards", @@ -124,6 +131,7 @@ func (c *Client) CreateUnifiedDashboard( Labels: dashboard.Attributes.Labels, TemplateVariables: dashboard.Attributes.TemplateVariables, EventQueryIDs: dashboard.Attributes.EventQueryIDs, + WorkflowLinks: dashboard.Attributes.WorkflowLinks, }, }) diff --git a/docs/resources/dashboard.md b/docs/resources/dashboard.md index 0261009..79c0d98 100644 --- a/docs/resources/dashboard.md +++ b/docs/resources/dashboard.md @@ -71,6 +71,7 @@ resource "lightstep_dashboard" "customer_charges" { - `group` (Block Set) (see [below for nested schema](#nestedblock--group)) - `label` (Block Set) Labels can be key/value pairs or standalone values. (see [below for nested schema](#nestedblock--label)) - `template_variable` (Block Set) Variable to be used in dashboard queries for dynamically filtering telemetry data (see [below for nested schema](#nestedblock--template_variable)) +- `workflow_link` (Block List) Links to other resources (see [below for nested schema](#nestedblock--workflow_link)) ### Read-Only @@ -94,6 +95,7 @@ Optional: - `subtitle` (String) Subtitle to show beneath big number, unused in other chart types - `threshold` (Block List) (see [below for nested schema](#nestedblock--chart--threshold)) - `width` (Number) +- `workflow_link` (Block List) Links to other resources (see [below for nested schema](#nestedblock--chart--workflow_link)) - `x_pos` (Number) - `y_axis` (Block List, Max: 1, Deprecated) (see [below for nested schema](#nestedblock--chart--y_axis)) - `y_pos` (Number) @@ -158,6 +160,15 @@ Optional: - `label` (String) + +### Nested Schema for `chart.workflow_link` + +Required: + +- `name` (String) +- `url` (String) + + ### Nested Schema for `chart.y_axis` @@ -261,6 +272,7 @@ Optional: - `subtitle` (String) Subtitle to show beneath big number, unused in other chart types - `threshold` (Block List) (see [below for nested schema](#nestedblock--group--chart--threshold)) - `width` (Number) +- `workflow_link` (Block List) Links to other resources (see [below for nested schema](#nestedblock--group--chart--workflow_link)) - `x_pos` (Number) - `y_axis` (Block List, Max: 1, Deprecated) (see [below for nested schema](#nestedblock--group--chart--y_axis)) - `y_pos` (Number) @@ -325,6 +337,15 @@ Optional: - `label` (String) + +### Nested Schema for `group.chart.workflow_link` + +Required: + +- `name` (String) +- `url` (String) + + ### Nested Schema for `group.chart.y_axis` @@ -405,3 +426,12 @@ Required: - `default_values` (List of String) One or more values to set the template variable to by default (if none are provided, defaults to all possible values) - `name` (String) Unique (per dashboard) name for template variable, beginning with a letter or underscore and only containing letters, numbers, and underscores - `suggestion_attribute_key` (String) Attribute key used as source for suggested template variable values appearing in Lightstep UI + + + +### Nested Schema for `workflow_link` + +Required: + +- `name` (String) +- `url` (String) diff --git a/docs/resources/metric_dashboard.md b/docs/resources/metric_dashboard.md index d6d099c..5227177 100644 --- a/docs/resources/metric_dashboard.md +++ b/docs/resources/metric_dashboard.md @@ -94,6 +94,7 @@ resource "lightstep_metric_dashboard" "customer_charges" { - `group` (Block Set) (see [below for nested schema](#nestedblock--group)) - `label` (Block Set) Labels can be key/value pairs or standalone values. (see [below for nested schema](#nestedblock--label)) - `template_variable` (Block Set) Variable to be used in dashboard queries for dynamically filtering telemetry data (see [below for nested schema](#nestedblock--template_variable)) +- `workflow_link` (Block List) Links to other resources (see [below for nested schema](#nestedblock--workflow_link)) ### Read-Only @@ -117,6 +118,7 @@ Optional: - `subtitle` (String) Subtitle to show beneath big number, unused in other chart types - `threshold` (Block List) (see [below for nested schema](#nestedblock--chart--threshold)) - `width` (Number) +- `workflow_link` (Block List) Links to other resources (see [below for nested schema](#nestedblock--chart--workflow_link)) - `x_pos` (Number) - `y_axis` (Block List, Max: 1, Deprecated) (see [below for nested schema](#nestedblock--chart--y_axis)) - `y_pos` (Number) @@ -195,6 +197,15 @@ Optional: - `label` (String) + +### Nested Schema for `chart.workflow_link` + +Required: + +- `name` (String) +- `url` (String) + + ### Nested Schema for `chart.y_axis` @@ -298,6 +309,7 @@ Optional: - `subtitle` (String) Subtitle to show beneath big number, unused in other chart types - `threshold` (Block List) (see [below for nested schema](#nestedblock--group--chart--threshold)) - `width` (Number) +- `workflow_link` (Block List) Links to other resources (see [below for nested schema](#nestedblock--group--chart--workflow_link)) - `x_pos` (Number) - `y_axis` (Block List, Max: 1, Deprecated) (see [below for nested schema](#nestedblock--group--chart--y_axis)) - `y_pos` (Number) @@ -376,6 +388,15 @@ Optional: - `label` (String) + +### Nested Schema for `group.chart.workflow_link` + +Required: + +- `name` (String) +- `url` (String) + + ### Nested Schema for `group.chart.y_axis` @@ -456,3 +477,12 @@ Required: - `default_values` (List of String) One or more values to set the template variable to by default (if none are provided, defaults to all possible values) - `name` (String) Unique (per dashboard) name for template variable, beginning with a letter or underscore and only containing letters, numbers, and underscores - `suggestion_attribute_key` (String) Attribute key used as source for suggested template variable values appearing in Lightstep UI + + + +### Nested Schema for `workflow_link` + +Required: + +- `name` (String) +- `url` (String) diff --git a/lightstep/resource_metric_dashboard.go b/lightstep/resource_metric_dashboard.go index c42db3e..ecb13c0 100644 --- a/lightstep/resource_metric_dashboard.go +++ b/lightstep/resource_metric_dashboard.go @@ -100,6 +100,23 @@ func resourceUnifiedDashboard(chartSchemaType ChartSchemaType) *schema.Resource Elem: &schema.Schema{Type: schema.TypeString}, Description: "IDs of the event queries to display on this dashboard", }, + "workflow_link": { + Description: "Links to other resources", + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "url": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, }, } } @@ -301,6 +318,23 @@ func getChartSchema(chartSchemaType ChartSchemaType) map[string]*schema.Schema { Schema: getThresholdSchema(), }, }, + "workflow_link": { + Description: "Links to other resources", + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "url": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, }, ) } @@ -471,6 +505,9 @@ func getUnifiedDashboardAttributesFromResource(d *schema.ResourceData) (*client. eventQueriesSet := d.Get("event_query_ids").(*schema.Set) eventQueries := buildStringSlice(eventQueriesSet.List()) + workflowLinksList := d.Get("workflow_link").([]any) + workflowLinks := buildWorkflowLinks(workflowLinksList) + attributes := &client.UnifiedDashboardAttributes{ Name: d.Get("dashboard_name").(string), Description: d.Get("dashboard_description").(string), @@ -478,6 +515,7 @@ func getUnifiedDashboardAttributesFromResource(d *schema.ResourceData) (*client. Labels: labels, TemplateVariables: templateVariables, EventQueryIDs: eventQueries, + WorkflowLinks: workflowLinks, } return attributes, hasLegacyChartsIn, nil @@ -573,13 +611,17 @@ func buildCharts(chartsIn []interface{}) ([]client.UnifiedChart, error) { } for _, chart := range charts { + workflowLinksList := chart["workflow_link"].([]any) + workflowLinks := buildWorkflowLinks(workflowLinksList) + c := client.UnifiedChart{ - Title: chart["name"].(string), - Description: chart["description"].(string), - Rank: chart["rank"].(int), - Position: buildPosition(chart), - ID: chart["id"].(string), - ChartType: chart["type"].(string), + Title: chart["name"].(string), + Description: chart["description"].(string), + Rank: chart["rank"].(int), + Position: buildPosition(chart), + ID: chart["id"].(string), + ChartType: chart["type"].(string), + WorkflowLinks: workflowLinks, } queries, err := buildQueries(chart["query"].([]interface{})) @@ -688,6 +730,21 @@ func buildTemplateVariables(templateVariablesIn []interface{}) []client.Template return newTemplateVariables } +func buildWorkflowLinks(workflowLinksIn []interface{}) []client.WorkflowLink { + var newWorkflowLinks []client.WorkflowLink + for _, wfLink := range workflowLinksIn { + wfMap := wfLink.(map[string]interface{}) + name := wfMap["name"].(string) + url := wfMap["url"].(string) + + newWorkflowLinks = append(newWorkflowLinks, client.WorkflowLink{ + Name: name, + URL: url, + }) + } + return newWorkflowLinks +} + func buildStringSlice(valuesIn []interface{}) []string { vals := make([]string, 0, len(valuesIn)) for _, v := range valuesIn { @@ -770,6 +827,16 @@ func (p *resourceUnifiedDashboardImp) setResourceDataFromUnifiedDashboard(projec if err := d.Set("event_query_ids", dash.Attributes.EventQueryIDs); err != nil { return fmt.Errorf("unable to set event_query_ids resource field: %v", err) } + resourceWorkflowLinks := make([]map[string]string, 0, len(dash.Attributes.WorkflowLinks)) + for _, workflowLink := range dash.Attributes.WorkflowLinks { + resourceWorkflowLinks = append(resourceWorkflowLinks, map[string]string{ + "name": workflowLink.Name, + "url": workflowLink.URL, + }) + } + if err := d.Set("workflow_link", resourceWorkflowLinks); err != nil { + return fmt.Errorf("unable to set workflow_link resource field: %v", err) + } return nil } @@ -895,6 +962,15 @@ func assembleCharts( resource["threshold"] = getThresholdsFromResourceData(c.Thresholds) + resourceWorkflowLinks := make([]map[string]string, 0, len(c.WorkflowLinks)) + for _, workflowLink := range c.WorkflowLinks { + resourceWorkflowLinks = append(resourceWorkflowLinks, map[string]string{ + "name": workflowLink.Name, + "url": workflowLink.URL, + }) + } + resource["workflow_link"] = resourceWorkflowLinks + chartResources = append(chartResources, resource) } return chartResources, nil diff --git a/lightstep/resource_metric_dashboard_test.go b/lightstep/resource_metric_dashboard_test.go index e47381e..f34c9d0 100644 --- a/lightstep/resource_metric_dashboard_test.go +++ b/lightstep/resource_metric_dashboard_test.go @@ -866,3 +866,110 @@ func Test_extractLabels(t *testing.T) { }) } } + +func TestAccDashboardWorkflowLinks(t *testing.T) { + var dashboard client.UnifiedDashboard + + dashboardConfig := ` +resource "lightstep_dashboard" "test_workflow_links" { + project_name = "` + testProject + `" + dashboard_name = "Test workflow links dashboard" + workflow_link { + name = "test dashboard link" + url = "https://test.com" + } + + chart { + name = "test chart" + rank = 0 + type = "timeseries" + + query { + query_name = "a" + display = "line" + hidden = false + query_string = "metric cpu.utilization | delta" + } + + workflow_link { + name = "test chart link" + url = "https://testchart.com" + } + workflow_link { + name = "another test chart link" + url = "https://anothertestchart.com" + } + } +} +` + updatedDashboardConfig := ` +resource "lightstep_dashboard" "test_workflow_links" { + project_name = "` + testProject + `" + dashboard_name = "Test workflow links dashboard" + event_query_ids = [] + workflow_link { + name = "test dashboard link" + url = "https://test.com" + } + workflow_link { + name = "another test dashboard link" + url = "https://anothertest.com" + } + + chart { + name = "test chart" + rank = 0 + type = "timeseries" + + query { + query_name = "a" + display = "line" + hidden = false + query_string = "metric cpu.utilization | delta" + } + + workflow_link { + name = "another test chart link" + url = "https://anothertestchart.com" + } + } +} +` + resourceName := "lightstep_dashboard.test_workflow_links" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: dashboardConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckMetricDashboardExists(resourceName, &dashboard), + resource.TestCheckResourceAttr(resourceName, "workflow_link.#", "1"), + resource.TestCheckResourceAttr(resourceName, "workflow_link.0.name", "test dashboard link"), + resource.TestCheckResourceAttr(resourceName, "workflow_link.0.url", "https://test.com"), + resource.TestCheckResourceAttr(resourceName, "chart.#", "1"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.#", "2"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.0.name", "test chart link"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.0.url", "https://testchart.com"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.1.name", "another test chart link"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.1.url", "https://anothertestchart.com"), + ), + }, + { + Config: updatedDashboardConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckMetricDashboardExists(resourceName, &dashboard), + resource.TestCheckResourceAttr(resourceName, "workflow_link.#", "2"), + resource.TestCheckResourceAttr(resourceName, "workflow_link.0.name", "test dashboard link"), + resource.TestCheckResourceAttr(resourceName, "workflow_link.0.url", "https://test.com"), + resource.TestCheckResourceAttr(resourceName, "workflow_link.1.name", "another test dashboard link"), + resource.TestCheckResourceAttr(resourceName, "workflow_link.1.url", "https://anothertest.com"), + resource.TestCheckResourceAttr(resourceName, "chart.#", "1"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.#", "1"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.0.name", "another test chart link"), + resource.TestCheckResourceAttr(resourceName, "chart.0.workflow_link.0.url", "https://anothertestchart.com"), + ), + }, + }, + }) +}