From d42b9d26d975dccc6ca2f9f1b7f40a59a691c273 Mon Sep 17 00:00:00 2001 From: klisiecka Date: Tue, 10 Dec 2024 10:07:26 +0100 Subject: [PATCH 1/7] update signalfx-go package version --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 439154eb..761925df 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 github.com/mitchellh/go-homedir v1.1.0 - github.com/signalfx/signalfx-go v1.43.0 + github.com/signalfx/signalfx-go v1.44.0 github.com/stretchr/testify v1.9.0 go.uber.org/multierr v1.11.0 ) diff --git a/go.sum b/go.sum index 5b8f600a..74c8966f 100644 --- a/go.sum +++ b/go.sum @@ -140,6 +140,8 @@ github.com/signalfx/signalfx-go v1.42.0 h1:NWSxf6GHYSL6yq+cKrAk2/+Gn/m/ok7YksBd4 github.com/signalfx/signalfx-go v1.42.0/go.mod h1:I30umyhRTu8mPpEtMzEbG0z9wOYjkUKTp9U0gFxFsmk= github.com/signalfx/signalfx-go v1.43.0 h1:Wp/XkyETzRyFvtuCGTN039hYwVgwIPfkBciqs19hqv4= github.com/signalfx/signalfx-go v1.43.0/go.mod h1:I30umyhRTu8mPpEtMzEbG0z9wOYjkUKTp9U0gFxFsmk= +github.com/signalfx/signalfx-go v1.44.0 h1:BkLtohTJkq3mr1Yl1OzCWK+e2DZRqZ0M0zD9Gs+c41Q= +github.com/signalfx/signalfx-go v1.44.0/go.mod h1:I30umyhRTu8mPpEtMzEbG0z9wOYjkUKTp9U0gFxFsmk= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 2740e6bc343062aae54ba77111e6019f3aee3eb6 Mon Sep 17 00:00:00 2001 From: klisiecka Date: Tue, 10 Dec 2024 11:17:36 +0100 Subject: [PATCH 2/7] add dashboard validation --- signalfx/resource_signalfx_dashboard.go | 43 +++++++++++++++++-------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/signalfx/resource_signalfx_dashboard.go b/signalfx/resource_signalfx_dashboard.go index 4b59b774..57adcbee 100644 --- a/signalfx/resource_signalfx_dashboard.go +++ b/signalfx/resource_signalfx_dashboard.go @@ -455,21 +455,28 @@ func dashboardResource() *schema.Resource { }, }, - Create: dashboardCreate, - Read: dashboardRead, - Update: dashboardUpdate, - Delete: dashboardDelete, - Exists: dashboardExists, + CustomizeDiff: dashboardValidate, + Create: dashboardCreate, + Read: dashboardRead, + Update: dashboardUpdate, + Delete: dashboardDelete, + Exists: dashboardExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, } } +// getPayloadDashboard is called with objects: *schema.ResourceDiff or *schema.ResourceData - that's why we need this interface +type DashboardResource interface { + Get(key string) interface{} + GetOk(key string) (interface{}, bool) +} + /* Use Resource object to construct json payload in order to create a dashboard */ -func getPayloadDashboard(d *schema.ResourceData) (*dashboard.CreateUpdateDashboardRequest, error) { +func getPayloadDashboard(d DashboardResource) (*dashboard.CreateUpdateDashboardRequest, error) { cudr := &dashboard.CreateUpdateDashboardRequest{ Name: d.Get("name").(string), @@ -567,7 +574,7 @@ func getPayloadDashboard(d *schema.ResourceData) (*dashboard.CreateUpdateDashboa return cudr, nil } -func getDashPermissions(d *schema.ResourceData) *dashboard.ObjectPermissions { +func getDashPermissions(d DashboardResource) *dashboard.ObjectPermissions { permissions := &dashboard.ObjectPermissions{} if val, ok := d.GetOk("permissions"); ok { p := val.([]interface{})[0].(map[string]interface{}) @@ -598,7 +605,7 @@ func getDashPermissionsAcl(set *schema.Set) []*dashboard.AclEntry { return nil } -func getDashboardTime(d *schema.ResourceData) *dashboard.ChartsFiltersTime { +func getDashboardTime(d DashboardResource) *dashboard.ChartsFiltersTime { var timeFilter *dashboard.ChartsFiltersTime if val, ok := d.GetOk("time_range"); ok { timeFilter = &dashboard.ChartsFiltersTime{ @@ -618,7 +625,7 @@ func getDashboardTime(d *schema.ResourceData) *dashboard.ChartsFiltersTime { return timeFilter } -func getDashboardCharts(d *schema.ResourceData) []*dashboard.DashboardChart { +func getDashboardCharts(d DashboardResource) []*dashboard.DashboardChart { charts := d.Get("chart").(*schema.Set).List() chartsList := make([]*dashboard.DashboardChart, len(charts)) for i, chart := range charts { @@ -636,7 +643,7 @@ func getDashboardCharts(d *schema.ResourceData) []*dashboard.DashboardChart { return chartsList } -func getDashboardColumns(d *schema.ResourceData) []*dashboard.DashboardChart { +func getDashboardColumns(d DashboardResource) []*dashboard.DashboardChart { columns := d.Get("column").([]interface{}) charts := make([]*dashboard.DashboardChart, 0) for _, column := range columns { @@ -660,7 +667,7 @@ func getDashboardColumns(d *schema.ResourceData) []*dashboard.DashboardChart { return charts } -func getDashboardGrids(d *schema.ResourceData) []*dashboard.DashboardChart { +func getDashboardGrids(d DashboardResource) []*dashboard.DashboardChart { grids := d.Get("grid").([]interface{}) charts := make([]*dashboard.DashboardChart, 0) // We must keep track of the row outside the loop as there might be many @@ -692,7 +699,7 @@ func getDashboardGrids(d *schema.ResourceData) []*dashboard.DashboardChart { return charts } -func getDashboardVariables(d *schema.ResourceData) []*dashboard.ChartsWebUiFilter { +func getDashboardVariables(d DashboardResource) []*dashboard.ChartsWebUiFilter { variables := d.Get("variable").(*schema.Set).List() varsList := make([]*dashboard.ChartsWebUiFilter, len(variables)) for i, variable := range variables { @@ -785,7 +792,7 @@ func getDashboardEventOverlayFilters(sources []interface{}) []*dashboard.EventOv return sourcesList } -func getDashboardFilters(d *schema.ResourceData) []*dashboard.ChartsSingleFilter { +func getDashboardFilters(d DashboardResource) []*dashboard.ChartsSingleFilter { filters := d.Get("filter").(*schema.Set).List() filterList := make([]*dashboard.ChartsSingleFilter, len(filters)) for i, filter := range filters { @@ -812,6 +819,16 @@ func getDashboardFilters(d *schema.ResourceData) []*dashboard.ChartsSingleFilter return filterList } +func dashboardValidate(ctx context.Context, dashboardObject *schema.ResourceDiff, config interface{}) error { + payloadDashboard, err := getPayloadDashboard(dashboardObject) + + if err != nil { + return err + } + + return config.(*signalfxConfig).Client.ValidateDashboard(ctx, payloadDashboard) +} + func dashboardCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) payload, err := getPayloadDashboard(d) From 90c4266bbcebaa86058c8ca1f4ac41fdfeef67b0 Mon Sep 17 00:00:00 2001 From: klisiecka Date: Tue, 10 Dec 2024 13:03:59 +0100 Subject: [PATCH 3/7] DashboardResource renamed to suit dashboard groups and charts --- signalfx/resource_signalfx_dashboard.go | 22 ++++++++-------------- signalfx/util.go | 6 ++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/signalfx/resource_signalfx_dashboard.go b/signalfx/resource_signalfx_dashboard.go index 57adcbee..ce0c41d8 100644 --- a/signalfx/resource_signalfx_dashboard.go +++ b/signalfx/resource_signalfx_dashboard.go @@ -467,16 +467,10 @@ func dashboardResource() *schema.Resource { } } -// getPayloadDashboard is called with objects: *schema.ResourceDiff or *schema.ResourceData - that's why we need this interface -type DashboardResource interface { - Get(key string) interface{} - GetOk(key string) (interface{}, bool) -} - /* Use Resource object to construct json payload in order to create a dashboard */ -func getPayloadDashboard(d DashboardResource) (*dashboard.CreateUpdateDashboardRequest, error) { +func getPayloadDashboard(d ResourceDataAccess) (*dashboard.CreateUpdateDashboardRequest, error) { cudr := &dashboard.CreateUpdateDashboardRequest{ Name: d.Get("name").(string), @@ -574,7 +568,7 @@ func getPayloadDashboard(d DashboardResource) (*dashboard.CreateUpdateDashboardR return cudr, nil } -func getDashPermissions(d DashboardResource) *dashboard.ObjectPermissions { +func getDashPermissions(d ResourceDataAccess) *dashboard.ObjectPermissions { permissions := &dashboard.ObjectPermissions{} if val, ok := d.GetOk("permissions"); ok { p := val.([]interface{})[0].(map[string]interface{}) @@ -605,7 +599,7 @@ func getDashPermissionsAcl(set *schema.Set) []*dashboard.AclEntry { return nil } -func getDashboardTime(d DashboardResource) *dashboard.ChartsFiltersTime { +func getDashboardTime(d ResourceDataAccess) *dashboard.ChartsFiltersTime { var timeFilter *dashboard.ChartsFiltersTime if val, ok := d.GetOk("time_range"); ok { timeFilter = &dashboard.ChartsFiltersTime{ @@ -625,7 +619,7 @@ func getDashboardTime(d DashboardResource) *dashboard.ChartsFiltersTime { return timeFilter } -func getDashboardCharts(d DashboardResource) []*dashboard.DashboardChart { +func getDashboardCharts(d ResourceDataAccess) []*dashboard.DashboardChart { charts := d.Get("chart").(*schema.Set).List() chartsList := make([]*dashboard.DashboardChart, len(charts)) for i, chart := range charts { @@ -643,7 +637,7 @@ func getDashboardCharts(d DashboardResource) []*dashboard.DashboardChart { return chartsList } -func getDashboardColumns(d DashboardResource) []*dashboard.DashboardChart { +func getDashboardColumns(d ResourceDataAccess) []*dashboard.DashboardChart { columns := d.Get("column").([]interface{}) charts := make([]*dashboard.DashboardChart, 0) for _, column := range columns { @@ -667,7 +661,7 @@ func getDashboardColumns(d DashboardResource) []*dashboard.DashboardChart { return charts } -func getDashboardGrids(d DashboardResource) []*dashboard.DashboardChart { +func getDashboardGrids(d ResourceDataAccess) []*dashboard.DashboardChart { grids := d.Get("grid").([]interface{}) charts := make([]*dashboard.DashboardChart, 0) // We must keep track of the row outside the loop as there might be many @@ -699,7 +693,7 @@ func getDashboardGrids(d DashboardResource) []*dashboard.DashboardChart { return charts } -func getDashboardVariables(d DashboardResource) []*dashboard.ChartsWebUiFilter { +func getDashboardVariables(d ResourceDataAccess) []*dashboard.ChartsWebUiFilter { variables := d.Get("variable").(*schema.Set).List() varsList := make([]*dashboard.ChartsWebUiFilter, len(variables)) for i, variable := range variables { @@ -792,7 +786,7 @@ func getDashboardEventOverlayFilters(sources []interface{}) []*dashboard.EventOv return sourcesList } -func getDashboardFilters(d DashboardResource) []*dashboard.ChartsSingleFilter { +func getDashboardFilters(d ResourceDataAccess) []*dashboard.ChartsSingleFilter { filters := d.Get("filter").(*schema.Set).List() filterList := make([]*dashboard.ChartsSingleFilter, len(filters)) for i, filter := range filters { diff --git a/signalfx/util.go b/signalfx/util.go index 566c66f1..4df62173 100644 --- a/signalfx/util.go +++ b/signalfx/util.go @@ -50,6 +50,12 @@ var ChartColorsSlice = []chartColor{ {"lime_green", "#6bd37e"}, } +// getPayload for viz objects is called withs: *schema.ResourceDiff or *schema.ResourceData - that's why we need this interface +type ResourceDataAccess interface { + Get(key string) interface{} + GetOk(key string) (interface{}, bool) +} + func buildAppURL(appURL string, fragment string) (string, error) { // Include a trailing slash, as without this Go doesn't add one for the fragment and that seems to be a required part of the url u, err := url.Parse(appURL + "/") From be5f46cf690ce412e03643716c4f13c5d02d4b41 Mon Sep 17 00:00:00 2001 From: klisiecka Date: Tue, 17 Dec 2024 12:56:51 +0100 Subject: [PATCH 4/7] add dashboard group validation --- signalfx/resource_signalfx_dashboard_group.go | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/signalfx/resource_signalfx_dashboard_group.go b/signalfx/resource_signalfx_dashboard_group.go index 50f1c921..82e3cb55 100644 --- a/signalfx/resource_signalfx_dashboard_group.go +++ b/signalfx/resource_signalfx_dashboard_group.go @@ -199,11 +199,12 @@ func dashboardGroupResource() *schema.Resource { }, }, - Create: dashboardgroupCreate, - Read: dashboardgroupRead, - Update: dashboardgroupUpdate, - Delete: dashboardgroupDelete, - Exists: dashboardgroupExists, + CustomizeDiff: dashboardgroupValidate, + Create: dashboardgroupCreate, + Read: dashboardgroupRead, + Update: dashboardgroupUpdate, + Delete: dashboardgroupDelete, + Exists: dashboardgroupExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -225,7 +226,7 @@ func dashboardgroupExists(d *schema.ResourceData, meta interface{}) (bool, error /* Use Resource object to construct json payload in order to create a dasboard group */ -func getPayloadDashboardGroup(d *schema.ResourceData) *dashboard_group.CreateUpdateDashboardGroupRequest { +func getPayloadDashboardGroup(d ResourceDataAccess) *dashboard_group.CreateUpdateDashboardGroupRequest { cudgr := &dashboard_group.CreateUpdateDashboardGroupRequest{ Name: d.Get("name").(string), Description: d.Get("description").(string), @@ -393,7 +394,7 @@ func getPayloadDashboardGroup(d *schema.ResourceData) *dashboard_group.CreateUpd return cudgr } -func getPermissions(d *schema.ResourceData) *dashboard_group.ObjectPermissions { +func getPermissions(d ResourceDataAccess) *dashboard_group.ObjectPermissions { permissions := &dashboard_group.ObjectPermissions{} if val := getPermissionsAcl(d); len(val) > 0 { permissions.Acl = val @@ -401,7 +402,7 @@ func getPermissions(d *schema.ResourceData) *dashboard_group.ObjectPermissions { return permissions } -func getPermissionsAcl(d *schema.ResourceData) []*dashboard_group.AclEntry { +func getPermissionsAcl(d ResourceDataAccess) []*dashboard_group.AclEntry { acl := d.Get("permissions").(*schema.Set).List() aclList := make([]*dashboard_group.AclEntry, len(acl)) for i, entry := range acl { @@ -417,6 +418,10 @@ func getPermissionsAcl(d *schema.ResourceData) []*dashboard_group.AclEntry { return aclList } +func dashboardgroupValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return config.(*signalfxConfig).Client.ValidateDashboardGroup(ctx, getPayloadDashboardGroup(d)) +} + func dashboardgroupCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) payload := getPayloadDashboardGroup(d) From 5b3f063051798a8e390e0cba11c2c1f2463725bd Mon Sep 17 00:00:00 2001 From: klisiecka Date: Fri, 10 Jan 2025 09:32:15 +0100 Subject: [PATCH 5/7] add charts validation --- .../resource_signalfx_event_feed_chart.go | 29 ++++++++++----- signalfx/resource_signalfx_heatmap_chart.go | 21 +++++++---- signalfx/resource_signalfx_list_chart.go | 19 ++++++---- .../resource_signalfx_single_value_chart.go | 31 +++++++++++----- signalfx/resource_signalfx_table_chart.go | 19 ++++++---- signalfx/resource_signalfx_text_chart.go | 29 ++++++++++----- signalfx/resource_signalfx_time_chart.go | 37 ++++++++++++------- signalfx/util.go | 16 ++++++-- 8 files changed, 135 insertions(+), 66 deletions(-) diff --git a/signalfx/resource_signalfx_event_feed_chart.go b/signalfx/resource_signalfx_event_feed_chart.go index 535197d2..653eecb7 100644 --- a/signalfx/resource_signalfx_event_feed_chart.go +++ b/signalfx/resource_signalfx_event_feed_chart.go @@ -57,11 +57,12 @@ func eventFeedChartResource() *schema.Resource { }, }, - Create: eventFeedChartCreate, - Read: eventFeedChartRead, - Update: eventFeedChartUpdate, - Delete: eventFeedChartDelete, - Exists: chartExists, + CustomizeDiff: eventfeedchartValidate, + Create: eventFeedChartCreate, + Read: eventFeedChartRead, + Update: eventFeedChartUpdate, + Delete: eventFeedChartDelete, + Exists: chartExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -71,7 +72,7 @@ func eventFeedChartResource() *schema.Resource { /* Use Resource object to construct json payload in order to create an event feed chart */ -func getPayloadEventFeedChart(d *schema.ResourceData) *chart.CreateUpdateChartRequest { +func getPayloadEventFeedChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) { var timeOptions *chart.TimeDisplayOptions if val, ok := d.GetOk("time_range"); ok { r := int64(val.(int) * 1000) @@ -100,12 +101,19 @@ func getPayloadEventFeedChart(d *schema.ResourceData) *chart.CreateUpdateChartRe Time: timeOptions, Type: "Event", }, - } + }, nil +} + +func eventfeedchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return chartValidate(ctx, d, config, getPayloadEventFeedChart) } func eventFeedChartCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadEventFeedChart(d) + payload, err := getPayloadEventFeedChart(d) + if err != nil { + return err + } debugOutput, _ := json.Marshal(payload) log.Printf("[DEBUG] SignalFx: Create Event Feed Chart Payload: %s", string(debugOutput)) @@ -186,7 +194,10 @@ func eventFeedChartRead(d *schema.ResourceData, meta interface{}) error { func eventFeedChartUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadEventFeedChart(d) + payload, err := getPayloadEventFeedChart(d) + if err != nil { + return err + } debugOutput, _ := json.Marshal(payload) log.Printf("[DEBUG] SignalFx: Update Event Feed Chart Payload: %s", string(debugOutput)) diff --git a/signalfx/resource_signalfx_heatmap_chart.go b/signalfx/resource_signalfx_heatmap_chart.go index 83476c6e..b962d78f 100644 --- a/signalfx/resource_signalfx_heatmap_chart.go +++ b/signalfx/resource_signalfx_heatmap_chart.go @@ -171,11 +171,12 @@ func heatmapChartResource() *schema.Resource { }, }, - Create: heatmapchartCreate, - Read: heatmapchartRead, - Update: heatmapchartUpdate, - Delete: heatmapchartDelete, - Exists: chartExists, + CustomizeDiff: heatmapchartValidate, + Create: heatmapchartCreate, + Read: heatmapchartRead, + Update: heatmapchartUpdate, + Delete: heatmapchartDelete, + Exists: chartExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -185,7 +186,7 @@ func heatmapChartResource() *schema.Resource { /* Use Resource object to construct json payload in order to create an Heatmap chart */ -func getPayloadHeatmapChart(d *schema.ResourceData) (*chart.CreateUpdateChartRequest, error) { +func getPayloadHeatmapChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) { payload := &chart.CreateUpdateChartRequest{ Name: d.Get("name").(string), Description: d.Get("description").(string), @@ -201,7 +202,7 @@ func getPayloadHeatmapChart(d *schema.ResourceData) (*chart.CreateUpdateChartReq return payload, nil } -func getHeatmapColorRangeOptions(d *schema.ResourceData) *chart.HeatmapColorRangeOptions { +func getHeatmapColorRangeOptions(d ResourceDataAccess) *chart.HeatmapColorRangeOptions { colorRange := d.Get("color_range").(*schema.Set).List() var item *chart.HeatmapColorRangeOptions @@ -230,7 +231,7 @@ func getHeatmapColorRangeOptions(d *schema.ResourceData) *chart.HeatmapColorRang return item } -func getHeatmapOptionsChart(d *schema.ResourceData) (*chart.Options, error) { +func getHeatmapOptionsChart(d ResourceDataAccess) (*chart.Options, error) { options := &chart.Options{ Type: "Heatmap", } @@ -306,6 +307,10 @@ func getHeatmapOptionsChart(d *schema.ResourceData) (*chart.Options, error) { return options, nil } +func heatmapchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return chartValidate(ctx, d, config, getPayloadHeatmapChart) +} + func heatmapchartCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) payload, err := getPayloadHeatmapChart(d) diff --git a/signalfx/resource_signalfx_list_chart.go b/signalfx/resource_signalfx_list_chart.go index c0bb25c2..fcd5db46 100644 --- a/signalfx/resource_signalfx_list_chart.go +++ b/signalfx/resource_signalfx_list_chart.go @@ -233,11 +233,12 @@ func listChartResource() *schema.Resource { }, }, - Create: listchartCreate, - Read: listchartRead, - Update: listchartUpdate, - Delete: listchartDelete, - Exists: chartExists, + CustomizeDiff: listchartValidate, + Create: listchartCreate, + Read: listchartRead, + Update: listchartUpdate, + Delete: listchartDelete, + Exists: chartExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -247,7 +248,7 @@ func listChartResource() *schema.Resource { /* Use Resource object to construct json payload in order to create a list chart */ -func getPayloadListChart(d *schema.ResourceData) (*chart.CreateUpdateChartRequest, error) { +func getPayloadListChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) { payload := &chart.CreateUpdateChartRequest{ Name: d.Get("name").(string), Description: d.Get("description").(string), @@ -278,7 +279,7 @@ func getPayloadListChart(d *schema.ResourceData) (*chart.CreateUpdateChartReques return payload, nil } -func getListChartOptions(d *schema.ResourceData) (*chart.Options, error) { +func getListChartOptions(d ResourceDataAccess) (*chart.Options, error) { options := &chart.Options{ Type: "List", } @@ -365,6 +366,10 @@ func getListChartOptions(d *schema.ResourceData) (*chart.Options, error) { return options, nil } +func listchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return chartValidate(ctx, d, config, getPayloadListChart) +} + func listchartCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) payload, err := getPayloadListChart(d) diff --git a/signalfx/resource_signalfx_single_value_chart.go b/signalfx/resource_signalfx_single_value_chart.go index 10faa774..40dd3edd 100644 --- a/signalfx/resource_signalfx_single_value_chart.go +++ b/signalfx/resource_signalfx_single_value_chart.go @@ -179,11 +179,12 @@ func singleValueChartResource() *schema.Resource { }, }, - Create: singlevaluechartCreate, - Read: singlevaluechartRead, - Update: singlevaluechartUpdate, - Delete: singlevaluechartDelete, - Exists: chartExists, + CustomizeDiff: singlevaluechartValidate, + Create: singlevaluechartCreate, + Read: singlevaluechartRead, + Update: singlevaluechartUpdate, + Delete: singlevaluechartDelete, + Exists: chartExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -193,7 +194,7 @@ func singleValueChartResource() *schema.Resource { /* Use Resource object to construct json payload in order to create a single value chart */ -func getPayloadSingleValueChart(d *schema.ResourceData) *chart.CreateUpdateChartRequest { +func getPayloadSingleValueChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) { payload := &chart.CreateUpdateChartRequest{ Name: d.Get("name").(string), Description: d.Get("description").(string), @@ -206,10 +207,10 @@ func getPayloadSingleValueChart(d *schema.ResourceData) *chart.CreateUpdateChart } payload.Options = viz - return payload + return payload, nil } -func getSingleValueChartOptions(d *schema.ResourceData) *chart.Options { +func getSingleValueChartOptions(d ResourceDataAccess) *chart.Options { options := &chart.Options{ Type: "SingleValue", } @@ -268,9 +269,16 @@ func getSingleValueChartOptions(d *schema.ResourceData) *chart.Options { return options } +func singlevaluechartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return chartValidate(ctx, d, config, getPayloadSingleValueChart) +} + func singlevaluechartCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadSingleValueChart(d) + payload, err := getPayloadSingleValueChart(d) + if err != nil { + return err + } debugOutput, _ := json.Marshal(payload) log.Printf("[DEBUG] SignalFx: Create Single Value Chart Payload: %s", string(debugOutput)) @@ -423,7 +431,10 @@ func singlevaluechartRead(d *schema.ResourceData, meta interface{}) error { func singlevaluechartUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadSingleValueChart(d) + payload, err := getPayloadSingleValueChart(d) + if err != nil { + return err + } debugOutput, _ := json.Marshal(payload) log.Printf("[DEBUG] SignalFx: Update Single Value Chart Payload: %s", string(debugOutput)) diff --git a/signalfx/resource_signalfx_table_chart.go b/signalfx/resource_signalfx_table_chart.go index 42223d3b..d2b7d6be 100644 --- a/signalfx/resource_signalfx_table_chart.go +++ b/signalfx/resource_signalfx_table_chart.go @@ -131,11 +131,12 @@ func tableChartResource() *schema.Resource { }, }, - Create: tablechartCreate, - Read: tablechartRead, - Update: tablechartUpdate, - Delete: tablechartDelete, - Exists: chartExists, + CustomizeDiff: tablechartValidate, + Create: tablechartCreate, + Read: tablechartRead, + Update: tablechartUpdate, + Delete: tablechartDelete, + Exists: chartExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -145,7 +146,7 @@ func tableChartResource() *schema.Resource { /* Use Resource object to construct json payload in order to create an Table chart */ -func getPayloadTableChart(d *schema.ResourceData) (*chart.CreateUpdateChartRequest, error) { +func getPayloadTableChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) { payload := &chart.CreateUpdateChartRequest{ Name: d.Get("name").(string), Description: d.Get("description").(string), @@ -166,7 +167,7 @@ func getPayloadTableChart(d *schema.ResourceData) (*chart.CreateUpdateChartReque return payload, nil } -func getTableOptionsChart(d *schema.ResourceData) (*chart.Options, error) { +func getTableOptionsChart(d ResourceDataAccess) (*chart.Options, error) { options := &chart.Options{ Type: "TableChart", } @@ -222,6 +223,10 @@ func getTableOptionsChart(d *schema.ResourceData) (*chart.Options, error) { return options, nil } +func tablechartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return chartValidate(ctx, d, config, getPayloadTableChart) +} + func tablechartCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) payload, err := getPayloadTableChart(d) diff --git a/signalfx/resource_signalfx_text_chart.go b/signalfx/resource_signalfx_text_chart.go index 33430505..36f7624e 100644 --- a/signalfx/resource_signalfx_text_chart.go +++ b/signalfx/resource_signalfx_text_chart.go @@ -37,11 +37,12 @@ func textChartResource() *schema.Resource { }, }, - Create: textchartCreate, - Read: textchartRead, - Update: textchartUpdate, - Delete: textchartDelete, - Exists: chartExists, + CustomizeDiff: textchartValidate, + Create: textchartCreate, + Read: textchartRead, + Update: textchartUpdate, + Delete: textchartDelete, + Exists: chartExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -51,7 +52,7 @@ func textChartResource() *schema.Resource { /* Use Resource object to construct json payload in order to create a text chart */ -func getPayloadTextChart(d *schema.ResourceData) *chart.CreateUpdateChartRequest { +func getPayloadTextChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) { return &chart.CreateUpdateChartRequest{ Name: d.Get("name").(string), Description: d.Get("description").(string), @@ -59,12 +60,19 @@ func getPayloadTextChart(d *schema.ResourceData) *chart.CreateUpdateChartRequest Type: "Text", Markdown: d.Get("markdown").(string), }, - } + }, nil +} + +func textchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return chartValidate(ctx, d, config, getPayloadTextChart) } func textchartCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadTextChart(d) + payload, err := getPayloadTextChart(d) + if err != nil { + return err + } debugOutput, _ := json.Marshal(payload) log.Printf("[DEBUG] SignalFx: Create Text Chart Payload: %s", string(debugOutput)) @@ -122,7 +130,10 @@ func textchartRead(d *schema.ResourceData, meta interface{}) error { func textchartUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadTextChart(d) + payload, err := getPayloadTextChart(d) + if err != nil { + return err + } debugOutput, _ := json.Marshal(payload) log.Printf("[DEBUG] SignalFx: Update Text Chart Payload: %s", string(debugOutput)) diff --git a/signalfx/resource_signalfx_time_chart.go b/signalfx/resource_signalfx_time_chart.go index b7922af9..39f31b25 100644 --- a/signalfx/resource_signalfx_time_chart.go +++ b/signalfx/resource_signalfx_time_chart.go @@ -502,11 +502,12 @@ func timeChartResource() *schema.Resource { }, }, - Create: timechartCreate, - Read: timechartRead, - Update: timechartUpdate, - Delete: timechartDelete, - Exists: chartExists, + CustomizeDiff: timechartValidate, + Create: timechartCreate, + Read: timechartRead, + Update: timechartUpdate, + Delete: timechartDelete, + Exists: chartExists, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -516,7 +517,7 @@ func timeChartResource() *schema.Resource { /* Use Resource object to construct json payload in order to create a time chart */ -func getPayloadTimeChart(d *schema.ResourceData) *chart.CreateUpdateChartRequest { +func getPayloadTimeChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) { var tags []string if val, ok := d.GetOk("tags"); ok { tags := []string{} @@ -567,10 +568,10 @@ func getPayloadTimeChart(d *schema.ResourceData) *chart.CreateUpdateChartRequest } payload.Options = viz - return payload + return payload, nil } -func getPerSignalVizOptions(d *schema.ResourceData, includePaletteIndex bool) []*chart.PublishLabelOptions { +func getPerSignalVizOptions(d ResourceDataAccess, includePaletteIndex bool) []*chart.PublishLabelOptions { viz := d.Get("viz_options").(*schema.Set).List() vizList := make([]*chart.PublishLabelOptions, len(viz)) for i, v := range viz { @@ -612,7 +613,7 @@ func getPerSignalVizOptions(d *schema.ResourceData, includePaletteIndex bool) [] return vizList } -func getPerEventOptions(d *schema.ResourceData) []*chart.EventPublishLabelOptions { +func getPerEventOptions(d ResourceDataAccess) []*chart.EventPublishLabelOptions { eos := d.Get("event_options").(*schema.Set).List() eventList := make([]*chart.EventPublishLabelOptions, len(eos)) for i, ev := range eos { @@ -635,7 +636,7 @@ func getPerEventOptions(d *schema.ResourceData) []*chart.EventPublishLabelOption return eventList } -func getAxesOptions(d *schema.ResourceData) []*chart.Axes { +func getAxesOptions(d ResourceDataAccess) []*chart.Axes { axesListopts := make([]*chart.Axes, 2) if tfAxisOpts, ok := d.GetOk("axis_right"); ok { tfRightAxisOpts := tfAxisOpts.(*schema.Set).List()[0] @@ -681,7 +682,7 @@ func getSingleAxisOptions(axisOpt map[string]interface{}) *chart.Axes { return axis } -func getTimeChartOptions(d *schema.ResourceData) *chart.Options { +func getTimeChartOptions(d ResourceDataAccess) *chart.Options { options := &chart.Options{ Stacked: d.Get("stacked").(bool), Type: "TimeSeriesChart", @@ -782,9 +783,16 @@ func getTimeChartOptions(d *schema.ResourceData) *chart.Options { return options } +func timechartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { + return chartValidate(ctx, d, config, getPayloadTimeChart) +} + func timechartCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadTimeChart(d) + payload, err := getPayloadTimeChart(d) + if err != nil { + return err + } debugOutput, _ := json.Marshal(payload) log.Printf("[DEBUG] SignalFx: Create Time Chart Payload: %s", string(debugOutput)) @@ -1111,7 +1119,10 @@ func publishLabelOptionsToMap(options *chart.PublishLabelOptions) (map[string]in func timechartUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*signalfxConfig) - payload := getPayloadTimeChart(d) + payload, err := getPayloadTimeChart(d) + if err != nil { + return err + } c, err := config.Client.UpdateChart(context.TODO(), d.Id(), payload) if err != nil { diff --git a/signalfx/util.go b/signalfx/util.go index 4df62173..b495fa51 100644 --- a/signalfx/util.go +++ b/signalfx/util.go @@ -56,6 +56,16 @@ type ResourceDataAccess interface { GetOk(key string) (interface{}, bool) } +func chartValidate(ctx context.Context, chartResource *schema.ResourceDiff, config interface{}, getPayload func(ResourceDataAccess) (*chart.CreateUpdateChartRequest, error)) error { + payload, err := getPayload(chartResource) + + if err != nil { + return err + } + + return config.(*signalfxConfig).Client.ValidateChart(ctx, payload) +} + func buildAppURL(appURL string, fragment string) (string, error) { // Include a trailing slash, as without this Go doesn't add one for the fragment and that seems to be a required part of the url u, err := url.Parse(appURL + "/") @@ -141,7 +151,7 @@ func getNameFromChartColorsByIndex(index int) (string, error) { /* Get Color Scale Options */ -func getColorScaleOptions(d *schema.ResourceData) []*chart.SecondaryVisualization { +func getColorScaleOptions(d ResourceDataAccess) []*chart.SecondaryVisualization { colorScale := d.Get("color_scale").(*schema.Set).List() return getColorScaleOptionsFromSlice(colorScale) } @@ -186,7 +196,7 @@ func getColorScaleOptionsFromSlice(colorScale []interface{}) []*chart.SecondaryV /* Util method to get Legend Chart Options. */ -func getLegendOptions(d *schema.ResourceData) *chart.DataTableOptions { +func getLegendOptions(d ResourceDataAccess) *chart.DataTableOptions { var options *chart.DataTableOptions if properties, ok := d.GetOk("legend_fields_to_hide"); ok { properties := properties.(*schema.Set).List() @@ -217,7 +227,7 @@ func getLegendOptions(d *schema.ResourceData) *chart.DataTableOptions { /* Util method to get Legend Chart Options for fields */ -func getLegendFieldOptions(d *schema.ResourceData) *chart.DataTableOptions { +func getLegendFieldOptions(d ResourceDataAccess) *chart.DataTableOptions { if fields, ok := d.GetOk("legend_options_fields"); ok { fields := fields.([]interface{}) if len(fields) > 0 { From 25a0ddd871721a0e89cc60da7ecdc3ac07202c61 Mon Sep 17 00:00:00 2001 From: klisiecka Date: Fri, 17 Jan 2025 14:30:59 +0100 Subject: [PATCH 6/7] tests added --- .../resource_signalfx_dashboard_group_test.go | 23 +++++++++++++++++++ signalfx/resource_signalfx_dashboard_test.go | 21 +++++++++++++++++ ...resource_signalfx_event_feed_chart_test.go | 21 +++++++++++++++++ .../resource_signalfx_heatmap_chart_test.go | 21 +++++++++++++++++ signalfx/resource_signalfx_list_chart_test.go | 21 +++++++++++++++++ ...source_signalfx_single_value_chart_test.go | 21 +++++++++++++++++ .../resource_signalfx_table_chart_test.go | 21 +++++++++++++++++ signalfx/resource_signalfx_text_chart_test.go | 21 +++++++++++++++++ signalfx/resource_signalfx_time_chart_test.go | 21 +++++++++++++++++ 9 files changed, 191 insertions(+) diff --git a/signalfx/resource_signalfx_dashboard_group_test.go b/signalfx/resource_signalfx_dashboard_group_test.go index 7c9d9b59..a410444e 100644 --- a/signalfx/resource_signalfx_dashboard_group_test.go +++ b/signalfx/resource_signalfx_dashboard_group_test.go @@ -4,6 +4,7 @@ package signalfx import ( + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -98,6 +99,28 @@ resource "signalfx_dashboard_group" "new_dashboard_group_2" { } ` +const invalidDashboardGroup = ` +resource "signalfx_dashboard_group" "invalid_dashboard_group" { + name = "Invalid dashboard" + dashboard { + dashboard_id = "" + } +} +` + +func TestAccValidateDashboardGroup(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccDashboardGroupDestroy, + Steps: []resource.TestStep{ + { + Config: invalidDashboardGroup, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateDashboardGroup(t *testing.T) { resource.Test(t, resource.TestCase{ Providers: testAccProviders, diff --git a/signalfx/resource_signalfx_dashboard_test.go b/signalfx/resource_signalfx_dashboard_test.go index 4e0524d2..f3f2f36f 100644 --- a/signalfx/resource_signalfx_dashboard_test.go +++ b/signalfx/resource_signalfx_dashboard_test.go @@ -5,6 +5,7 @@ package signalfx import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -41,6 +42,26 @@ resource "signalfx_dashboard" "mydashboardX0" { } ` +const invalidDashboard = ` +resource "signalfx_dashboard" "invalid_dashboard" { + name = "" + dashboard_group = "" +} +` + +func TestAccValidateDashboard(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccDashboardGroupDestroy, + Steps: []resource.TestStep{ + { + Config: invalidDashboard, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestValidateChartsResolutionAllowed(t *testing.T) { for _, value := range []string{"default", "low", "high", "highest"} { _, errors := validateChartsResolution(value, "charts_resolution") diff --git a/signalfx/resource_signalfx_event_feed_chart_test.go b/signalfx/resource_signalfx_event_feed_chart_test.go index 7f0d6e85..3f8849c5 100644 --- a/signalfx/resource_signalfx_event_feed_chart_test.go +++ b/signalfx/resource_signalfx_event_feed_chart_test.go @@ -6,6 +6,7 @@ package signalfx import ( "context" "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -32,6 +33,26 @@ resource "signalfx_event_feed_chart" "mychartEVX" { } ` +const invalidEventFeedChart = ` +resource "signalfx_event_feed_chart" "mychartEVX"{ + name = "" + program_text = "A = events(eventType='Fart Testing').publish(label='A')" +} +` + +func TestAccValidateEventFeedChart(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccEventFeedChartDestroy, + Steps: []resource.TestStep{ + { + Config: invalidEventFeedChart, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateUpdateEventFeedChart(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/signalfx/resource_signalfx_heatmap_chart_test.go b/signalfx/resource_signalfx_heatmap_chart_test.go index 9e5c2e11..294996bc 100644 --- a/signalfx/resource_signalfx_heatmap_chart_test.go +++ b/signalfx/resource_signalfx_heatmap_chart_test.go @@ -6,6 +6,7 @@ package signalfx import ( "context" "fmt" + "regexp" "testing" "github.com/stretchr/testify/assert" @@ -54,6 +55,26 @@ resource "signalfx_heatmap_chart" "mychartHX" { } ` +const invalidHeatmapChart = ` +resource "signalfx_heatmap_chart" "mychartHX"{ + name = "" + program_text = "A = data('cpu.total.idle').publish(label='CPU Idle')" +} +` + +func TestAccValidateHeatmapChart(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccHeatmapChartDestroy, + Steps: []resource.TestStep{ + { + Config: invalidHeatmapChart, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateUpdateHeatmapChart(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/signalfx/resource_signalfx_list_chart_test.go b/signalfx/resource_signalfx_list_chart_test.go index 9a4f1c48..13647136 100644 --- a/signalfx/resource_signalfx_list_chart_test.go +++ b/signalfx/resource_signalfx_list_chart_test.go @@ -6,6 +6,7 @@ package signalfx import ( "context" "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -104,6 +105,26 @@ resource "signalfx_list_chart" "mychartLX" { } ` +const invalidListChart = ` +resource "signalfx_list_chart" "mychartLX"{ + name = "" + program_text = "A = data('demo.lb.hosts').publish(label='A')" +} +` + +func TestAccValidateListChart(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccListChartDestroy, + Steps: []resource.TestStep{ + { + Config: invalidListChart, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateUpdateListChart(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/signalfx/resource_signalfx_single_value_chart_test.go b/signalfx/resource_signalfx_single_value_chart_test.go index 18ca5e22..e9e7a424 100644 --- a/signalfx/resource_signalfx_single_value_chart_test.go +++ b/signalfx/resource_signalfx_single_value_chart_test.go @@ -6,6 +6,7 @@ package signalfx import ( "context" "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -92,6 +93,26 @@ resource "signalfx_single_value_chart" "mychartSVX" { } ` +const invalidSingleValueChart = ` +resource "signalfx_single_value_chart" "mychartSVX"{ + name = "" + program_text = "A = data('cpu.total.idle').publish(label='CPU Idle')" +} +` + +func TestAccValidateSingleValueChart(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccSingleValueChartDestroy, + Steps: []resource.TestStep{ + { + Config: invalidSingleValueChart, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateUpdateSingleValueChart(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/signalfx/resource_signalfx_table_chart_test.go b/signalfx/resource_signalfx_table_chart_test.go index 954eee8c..b099e1d5 100644 --- a/signalfx/resource_signalfx_table_chart_test.go +++ b/signalfx/resource_signalfx_table_chart_test.go @@ -6,6 +6,7 @@ package signalfx import ( "context" "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -54,6 +55,26 @@ resource "signalfx_table_chart" "mychartTB" { } ` +const invalidTableChartChart = ` +resource "signalfx_table_chart" "mychartTB"{ + name = "" + program_text = "A = data('cpu.usage.total').publish(label='Updated CPU Total')" +} +` + +func TestAccValidateTableChartChart(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccTableChartDestroy, + Steps: []resource.TestStep{ + { + Config: invalidTableChartChart, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateUpdateTableChart(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/signalfx/resource_signalfx_text_chart_test.go b/signalfx/resource_signalfx_text_chart_test.go index a1b66927..a2d97e3a 100644 --- a/signalfx/resource_signalfx_text_chart_test.go +++ b/signalfx/resource_signalfx_text_chart_test.go @@ -6,6 +6,7 @@ package signalfx import ( "context" "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -28,6 +29,26 @@ resource "signalfx_text_chart" "mychartTX" { } ` +const invalidTextChartChart = ` +resource "signalfx_text_chart" "mychartTX"{ + name = "" + markdown = "**chart markdown**" +} +` + +func TestAccValidateTextChartChart(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccTextChartDestroy, + Steps: []resource.TestStep{ + { + Config: invalidTextChartChart, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateUpdateTextChart(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/signalfx/resource_signalfx_time_chart_test.go b/signalfx/resource_signalfx_time_chart_test.go index 22bb04b6..30da5627 100644 --- a/signalfx/resource_signalfx_time_chart_test.go +++ b/signalfx/resource_signalfx_time_chart_test.go @@ -6,6 +6,7 @@ package signalfx import ( "context" "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -216,6 +217,26 @@ resource "signalfx_time_chart" "mychartXY" { } ` +const invalidTimeChartChart = ` +resource "signalfx_time_chart" "mychartXY"{ + name = "" + program_text = "A = data('cpu.total.idle').publish(label='CPU Idle')" +} +` + +func TestAccValidateTimeChartChart(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccTimeChartDestroy, + Steps: []resource.TestStep{ + { + Config: invalidTimeChartChart, + ExpectError: regexp.MustCompile("status code 400"), + }, + }, + }) +} + func TestAccCreateUpdateTimeChart(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, From 948d068c52fa148b214426ac48e87418b01a8d78 Mon Sep 17 00:00:00 2001 From: klisiecka Date: Fri, 17 Jan 2025 15:54:27 +0100 Subject: [PATCH 7/7] changes after review --- signalfx/resource_data_access.go | 14 +++++++++++++ signalfx/resource_signalfx_dashboard.go | 8 +++++-- signalfx/resource_signalfx_dashboard_group.go | 8 +++++-- .../resource_signalfx_event_feed_chart.go | 4 ++-- signalfx/resource_signalfx_heatmap_chart.go | 4 ++-- signalfx/resource_signalfx_list_chart.go | 4 ++-- .../resource_signalfx_single_value_chart.go | 4 ++-- signalfx/resource_signalfx_table_chart.go | 4 ++-- signalfx/resource_signalfx_text_chart.go | 4 ++-- signalfx/resource_signalfx_time_chart.go | 4 ++-- signalfx/util.go | 21 ++++++++++++------- 11 files changed, 53 insertions(+), 26 deletions(-) create mode 100644 signalfx/resource_data_access.go diff --git a/signalfx/resource_data_access.go b/signalfx/resource_data_access.go new file mode 100644 index 00000000..7e13061a --- /dev/null +++ b/signalfx/resource_data_access.go @@ -0,0 +1,14 @@ +// Copyright Splunk, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package signalfx + +// ResourceDataAccess is an interface designed to abstract access to resource data. +// It is implemented by both *schema.ResourceDiff and *schema.ResourceData types, +// allowing functions to operate on them interchangeably. +// +// This interface provides methods to retrieve resource properties based on a key. +type ResourceDataAccess interface { + Get(key string) interface{} + GetOk(key string) (interface{}, bool) +} diff --git a/signalfx/resource_signalfx_dashboard.go b/signalfx/resource_signalfx_dashboard.go index ce0c41d8..c80c3090 100644 --- a/signalfx/resource_signalfx_dashboard.go +++ b/signalfx/resource_signalfx_dashboard.go @@ -813,14 +813,18 @@ func getDashboardFilters(d ResourceDataAccess) []*dashboard.ChartsSingleFilter { return filterList } -func dashboardValidate(ctx context.Context, dashboardObject *schema.ResourceDiff, config interface{}) error { +func dashboardValidate(ctx context.Context, dashboardObject *schema.ResourceDiff, meta any) error { payloadDashboard, err := getPayloadDashboard(dashboardObject) if err != nil { return err } - return config.(*signalfxConfig).Client.ValidateDashboard(ctx, payloadDashboard) + if config, ok := meta.(*signalfxConfig); ok { + return config.Client.ValidateDashboard(ctx, payloadDashboard) + } else { + return fmt.Errorf("invalid type assertion: expected *signalfxConfig, got %T", meta) + } } func dashboardCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_dashboard_group.go b/signalfx/resource_signalfx_dashboard_group.go index 82e3cb55..858f3e30 100644 --- a/signalfx/resource_signalfx_dashboard_group.go +++ b/signalfx/resource_signalfx_dashboard_group.go @@ -418,8 +418,12 @@ func getPermissionsAcl(d ResourceDataAccess) []*dashboard_group.AclEntry { return aclList } -func dashboardgroupValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return config.(*signalfxConfig).Client.ValidateDashboardGroup(ctx, getPayloadDashboardGroup(d)) +func dashboardgroupValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + if config, ok := meta.(*signalfxConfig); ok { + return config.Client.ValidateDashboardGroup(ctx, getPayloadDashboardGroup(d)) + } else { + return fmt.Errorf("invalid type assertion: expected *signalfxConfig, got %T", meta) + } } func dashboardgroupCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_event_feed_chart.go b/signalfx/resource_signalfx_event_feed_chart.go index 653eecb7..f32245c7 100644 --- a/signalfx/resource_signalfx_event_feed_chart.go +++ b/signalfx/resource_signalfx_event_feed_chart.go @@ -104,8 +104,8 @@ func getPayloadEventFeedChart(d ResourceDataAccess) (*chart.CreateUpdateChartReq }, nil } -func eventfeedchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return chartValidate(ctx, d, config, getPayloadEventFeedChart) +func eventfeedchartValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + return ChartValidatorFunc(getPayloadEventFeedChart).Validate(ctx, d, meta) } func eventFeedChartCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_heatmap_chart.go b/signalfx/resource_signalfx_heatmap_chart.go index b962d78f..ac5e110a 100644 --- a/signalfx/resource_signalfx_heatmap_chart.go +++ b/signalfx/resource_signalfx_heatmap_chart.go @@ -307,8 +307,8 @@ func getHeatmapOptionsChart(d ResourceDataAccess) (*chart.Options, error) { return options, nil } -func heatmapchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return chartValidate(ctx, d, config, getPayloadHeatmapChart) +func heatmapchartValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + return ChartValidatorFunc(getPayloadHeatmapChart).Validate(ctx, d, meta) } func heatmapchartCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_list_chart.go b/signalfx/resource_signalfx_list_chart.go index fcd5db46..d89c3c1e 100644 --- a/signalfx/resource_signalfx_list_chart.go +++ b/signalfx/resource_signalfx_list_chart.go @@ -366,8 +366,8 @@ func getListChartOptions(d ResourceDataAccess) (*chart.Options, error) { return options, nil } -func listchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return chartValidate(ctx, d, config, getPayloadListChart) +func listchartValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + return ChartValidatorFunc(getPayloadListChart).Validate(ctx, d, meta) } func listchartCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_single_value_chart.go b/signalfx/resource_signalfx_single_value_chart.go index 40dd3edd..fcc5d081 100644 --- a/signalfx/resource_signalfx_single_value_chart.go +++ b/signalfx/resource_signalfx_single_value_chart.go @@ -269,8 +269,8 @@ func getSingleValueChartOptions(d ResourceDataAccess) *chart.Options { return options } -func singlevaluechartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return chartValidate(ctx, d, config, getPayloadSingleValueChart) +func singlevaluechartValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + return ChartValidatorFunc(getPayloadSingleValueChart).Validate(ctx, d, meta) } func singlevaluechartCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_table_chart.go b/signalfx/resource_signalfx_table_chart.go index d2b7d6be..c570b0e0 100644 --- a/signalfx/resource_signalfx_table_chart.go +++ b/signalfx/resource_signalfx_table_chart.go @@ -223,8 +223,8 @@ func getTableOptionsChart(d ResourceDataAccess) (*chart.Options, error) { return options, nil } -func tablechartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return chartValidate(ctx, d, config, getPayloadTableChart) +func tablechartValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + return ChartValidatorFunc(getPayloadTableChart).Validate(ctx, d, meta) } func tablechartCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_text_chart.go b/signalfx/resource_signalfx_text_chart.go index 36f7624e..07863d99 100644 --- a/signalfx/resource_signalfx_text_chart.go +++ b/signalfx/resource_signalfx_text_chart.go @@ -63,8 +63,8 @@ func getPayloadTextChart(d ResourceDataAccess) (*chart.CreateUpdateChartRequest, }, nil } -func textchartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return chartValidate(ctx, d, config, getPayloadTextChart) +func textchartValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + return ChartValidatorFunc(getPayloadTextChart).Validate(ctx, d, meta) } func textchartCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/resource_signalfx_time_chart.go b/signalfx/resource_signalfx_time_chart.go index 39f31b25..7c9d152a 100644 --- a/signalfx/resource_signalfx_time_chart.go +++ b/signalfx/resource_signalfx_time_chart.go @@ -783,8 +783,8 @@ func getTimeChartOptions(d ResourceDataAccess) *chart.Options { return options } -func timechartValidate(ctx context.Context, d *schema.ResourceDiff, config interface{}) error { - return chartValidate(ctx, d, config, getPayloadTimeChart) +func timechartValidate(ctx context.Context, d *schema.ResourceDiff, meta any) error { + return ChartValidatorFunc(getPayloadTimeChart).Validate(ctx, d, meta) } func timechartCreate(d *schema.ResourceData, meta interface{}) error { diff --git a/signalfx/util.go b/signalfx/util.go index b495fa51..001cbe1c 100644 --- a/signalfx/util.go +++ b/signalfx/util.go @@ -5,6 +5,7 @@ package signalfx import ( "context" + "errors" "fmt" "math" "net/url" @@ -50,20 +51,24 @@ var ChartColorsSlice = []chartColor{ {"lime_green", "#6bd37e"}, } -// getPayload for viz objects is called withs: *schema.ResourceDiff or *schema.ResourceData - that's why we need this interface -type ResourceDataAccess interface { - Get(key string) interface{} - GetOk(key string) (interface{}, bool) -} +type ChartValidatorFunc func(ResourceDataAccess) (*chart.CreateUpdateChartRequest, error) + +func (fn ChartValidatorFunc) Validate(ctx context.Context, chartResource *schema.ResourceDiff, meta any) error { + if fn == nil { + return errors.New("no data parser provided") + } -func chartValidate(ctx context.Context, chartResource *schema.ResourceDiff, config interface{}, getPayload func(ResourceDataAccess) (*chart.CreateUpdateChartRequest, error)) error { - payload, err := getPayload(chartResource) + payload, err := fn(chartResource) if err != nil { return err } - return config.(*signalfxConfig).Client.ValidateChart(ctx, payload) + if config, ok := meta.(*signalfxConfig); ok { + return config.Client.ValidateChart(ctx, payload) + } else { + return fmt.Errorf("invalid type assertion: expected *signalfxConfig, got %T", meta) + } } func buildAppURL(appURL string, fragment string) (string, error) {