From 4eaa5db1e9472343ae860734c848d88a0ea16a23 Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Thu, 27 Apr 2023 09:19:47 -0400 Subject: [PATCH 1/2] Dashboard: Support folder UID as reference Currently, the dashboard resource only supports numeric folder IDs However, in a context where someone is managing the dashboard but not the folder, it's much easier to use a UID In this PR, I add UID support to the `folder` field. Numeric ID support remains the same --- .../grafana_dashboard/_acc_folder.tf | 20 +++++----- .../grafana_dashboard/_acc_folder_uid_ref.tf | 14 +++++++ go.mod | 2 +- go.sum | 4 +- .../resources/grafana/resource_dashboard.go | 34 ++++++++-------- .../grafana/resource_dashboard_test.go | 39 ++++++++++++++++--- 6 files changed, 77 insertions(+), 36 deletions(-) create mode 100644 examples/resources/grafana_dashboard/_acc_folder_uid_ref.tf diff --git a/examples/resources/grafana_dashboard/_acc_folder.tf b/examples/resources/grafana_dashboard/_acc_folder.tf index 95bc163dd..5d9ba9751 100644 --- a/examples/resources/grafana_dashboard/_acc_folder.tf +++ b/examples/resources/grafana_dashboard/_acc_folder.tf @@ -1,15 +1,15 @@ resource "grafana_folder" "test_folder" { - title = "Terraform Folder Test Folder" + title = "Terraform Folder Folder ID Test" + uid = "folder-dashboard-id-test" } resource "grafana_dashboard" "test_folder" { - folder = grafana_folder.test_folder.id - config_json = < 0 { + + // If the folder was originally set to a numeric ID, we read the folder ID + // Othwerwise, we read the folder UID + if common.IDRegexp.MatchString(d.Get("folder").(string)) && dashboard.Meta.Folder > 0 { d.Set("folder", strconv.FormatInt(dashboard.FolderID, 10)) } else { - d.Set("folder", "") + d.Set("folder", dashboard.Meta.FolderUID) } configJSONBytes, err := json.Marshal(dashboard.Model) @@ -288,20 +289,17 @@ func DeleteDashboard(ctx context.Context, d *schema.ResourceData, meta interface } func makeDashboard(d *schema.ResourceData) (gapi.Dashboard, error) { - var parsedFolder int64 = 0 - var err error - if folderStr := d.Get("folder").(string); folderStr != "" { - parsedFolder, err = strconv.ParseInt(d.Get("folder").(string), 10, 64) - if err != nil { - return gapi.Dashboard{}, fmt.Errorf("error parsing folder: %s", err) - } - } - dashboard := gapi.Dashboard{ - FolderID: parsedFolder, Overwrite: d.Get("overwrite").(bool), Message: d.Get("message").(string), } + + if folderInt, err := strconv.ParseInt(d.Get("folder").(string), 10, 64); err == nil { + dashboard.FolderID = folderInt + } else { + dashboard.FolderUID = d.Get("folder").(string) + } + configJSON := d.Get("config_json").(string) dashboardJSON, err := UnmarshalDashboardConfigJSON(configJSON) if err != nil { diff --git a/internal/resources/grafana/resource_dashboard_test.go b/internal/resources/grafana/resource_dashboard_test.go index 65c67ba30..74fa8a554 100644 --- a/internal/resources/grafana/resource_dashboard_test.go +++ b/internal/resources/grafana/resource_dashboard_test.go @@ -174,17 +174,46 @@ func TestAccDashboard_folder(t *testing.T) { testAccDashboardCheckExists("grafana_dashboard.test_folder", &dashboard), testAccFolderCheckExists("grafana_folder.test_folder", &folder), testAccDashboardCheckExistsInFolder(&dashboard, &folder), - resource.TestCheckResourceAttr("grafana_dashboard.test_folder", "id", "0:folder"), // : - resource.TestCheckResourceAttr("grafana_dashboard.test_folder", "uid", "folder"), - resource.TestMatchResourceAttr( - "grafana_dashboard.test_folder", "folder", common.IDRegexp, - ), + resource.TestCheckResourceAttr("grafana_dashboard.test_folder", "id", "0:folder-dashboard-test-ref-with-id"), // : + resource.TestCheckResourceAttr("grafana_dashboard.test_folder", "uid", "folder-dashboard-test-ref-with-id"), + resource.TestMatchResourceAttr("grafana_dashboard.test_folder", "folder", common.IDRegexp), ), }, }, }) } +func TestAccDashboard_folder_uid(t *testing.T) { + testutils.CheckOSSTestsEnabled(t) + testutils.CheckOSSTestsSemver(t, ">=8.0.0") // UID in folders were added in v8 + + var dashboard gapi.Dashboard + var folder gapi.Folder + + resource.ParallelTest(t, resource.TestCase{ + ProviderFactories: testutils.ProviderFactories, + CheckDestroy: testAccDashboardFolderCheckDestroy(&dashboard, &folder), + Steps: []resource.TestStep{ + { + Config: testutils.TestAccExample(t, "resources/grafana_dashboard/_acc_folder_uid_ref.tf"), + Check: resource.ComposeTestCheckFunc( + testAccFolderCheckExists("grafana_folder.test_folder", &folder), + testAccDashboardCheckExists("grafana_dashboard.test_folder", &dashboard), + testAccDashboardCheckExistsInFolder(&dashboard, &folder), + resource.TestCheckResourceAttr("grafana_dashboard.test_folder", "id", "0:folder-dashboard-test-ref-with-uid"), // : + resource.TestCheckResourceAttr("grafana_dashboard.test_folder", "uid", "folder-dashboard-test-ref-with-uid"), + resource.TestCheckResourceAttr("grafana_dashboard.test_folder", "folder", "folder-dashboard-uid-test"), + ), + }, + { + ImportState: true, + ResourceName: "grafana_dashboard.test_folder", + ImportStateVerify: true, + }, + }, + }) +} + func TestAccDashboard_inOrg(t *testing.T) { testutils.CheckOSSTestsEnabled(t) From b1ae8628af3da6c96ea0e5387f2ae26d414f8fd4 Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Thu, 27 Apr 2023 09:32:52 -0400 Subject: [PATCH 2/2] go generate --- docs/resources/dashboard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/resources/dashboard.md b/docs/resources/dashboard.md index ab370a3cb..4e99588b6 100644 --- a/docs/resources/dashboard.md +++ b/docs/resources/dashboard.md @@ -31,7 +31,7 @@ resource "grafana_dashboard" "metrics" { ### Optional -- `folder` (String) The id of the folder to save the dashboard in. This attribute is a string to reflect the type of the folder's id. +- `folder` (String) The id or UID of the folder to save the dashboard in. - `message` (String) Set a commit message for the version history. - `org_id` (String) The Organization ID. If not set, the Org ID defined in the provider block will be used. - `overwrite` (Boolean) Set to true if you want to overwrite existing dashboard with newer version, same dashboard title in folder or same dashboard uid.