Skip to content

Commit

Permalink
Folder: Support sub-folders (nestedFolders) (#1129)
Browse files Browse the repository at this point in the history
* Folder: Support sub-folders (nestedFolders)
Closes #935
Depends on #1123
Tested with our cloud instance since the feature is not enabled by default for now

* Generate docs
  • Loading branch information
julienduchesne authored Nov 7, 2023
1 parent c284510 commit e544ebb
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/resources/folder.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ resource "grafana_folder" "test_folder_with_uid" {
### Optional

- `org_id` (String) The Organization ID. If not set, the Org ID defined in the provider block will be used.
- `parent_folder_uid` (String) The uid of the parent folder. If set, the folder will be nested. If not set, the folder will be created in the root folder.
- `prevent_destroy_if_not_empty` (Boolean) Prevent deletion of the folder if it is not empty (contains dashboards or alert rules). Defaults to `false`.
- `uid` (String) Unique identifier.

Expand Down
13 changes: 11 additions & 2 deletions internal/resources/grafana/resource_folder.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ func ResourceFolder() *schema.Resource {
Default: false,
Description: "Prevent deletion of the folder if it is not empty (contains dashboards or alert rules).",
},
"parent_folder_uid": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: "The uid of the parent folder. If set, the folder will be nested. If not set, the folder will be created in the root folder.",
},
},
}
}
Expand All @@ -71,6 +77,10 @@ func CreateFolder(ctx context.Context, d *schema.ResourceData, meta interface{})
body.UID = uid.(string)
}

if parentUID, ok := d.GetOk("parent_folder_uid"); ok {
body.ParentUID = parentUID.(string)
}

params := goapi.NewCreateFolderParams().WithBody(&body)
resp, err := client.Folders.CreateFolder(params, nil)
if err != nil {
Expand All @@ -79,8 +89,6 @@ func CreateFolder(ctx context.Context, d *schema.ResourceData, meta interface{})

folder := resp.GetPayload()
d.SetId(MakeOrgResourceID(orgID, folder.ID))
d.Set("uid", folder.UID)
d.Set("title", folder.Title)

return ReadFolder(ctx, d, meta)
}
Expand Down Expand Up @@ -121,6 +129,7 @@ func ReadFolder(ctx context.Context, d *schema.ResourceData, meta interface{}) d
d.Set("title", folder.Title)
d.Set("uid", folder.UID)
d.Set("url", metaClient.GrafanaSubpath(folder.URL))
d.Set("parent_folder_uid", folder.ParentUID)

return nil
}
Expand Down
72 changes: 72 additions & 0 deletions internal/resources/grafana/resource_folder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,78 @@ func TestAccFolder_basic(t *testing.T) {
})
}

func TestAccFolder_nested(t *testing.T) {
testutils.CheckCloudInstanceTestsEnabled(t) // TODO: Switch to OSS once nested folders are enabled by default

var parentFolder goapi.Folder
var childFolder1 goapi.Folder
var childFolder2 goapi.Folder
name := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)

resource.ParallelTest(t, resource.TestCase{
ProviderFactories: testutils.ProviderFactories,
CheckDestroy: resource.ComposeTestCheckFunc(
folderCheckExists.destroyed(&parentFolder, nil),
folderCheckExists.destroyed(&childFolder1, nil),
folderCheckExists.destroyed(&childFolder2, nil),
),
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
resource grafana_folder parent {
title = "Nested Test: Parent %[1]s"
}
resource grafana_folder child1 {
title = "Nested Test: Child 1 %[1]s"
uid = "%[1]s-child1"
parent_folder_uid = grafana_folder.parent.uid
}
resource grafana_folder child2 {
title = "Nested Test: Child 2 %[1]s"
parent_folder_uid = grafana_folder.child1.uid
}
`, name),
Check: resource.ComposeTestCheckFunc(
folderCheckExists.exists("grafana_folder.parent", &parentFolder),
resource.TestMatchResourceAttr("grafana_folder.parent", "id", defaultOrgIDRegexp),
resource.TestCheckResourceAttr("grafana_folder.parent", "title", "Nested Test: Parent "+name),
resource.TestCheckResourceAttr("grafana_folder.parent", "parent_folder_uid", ""),

folderCheckExists.exists("grafana_folder.child1", &childFolder1),
resource.TestMatchResourceAttr("grafana_folder.child1", "id", defaultOrgIDRegexp),
resource.TestCheckResourceAttr("grafana_folder.child1", "title", "Nested Test: Child 1 "+name),
resource.TestCheckResourceAttrSet("grafana_folder.child1", "parent_folder_uid"),

folderCheckExists.exists("grafana_folder.child2", &childFolder2),
resource.TestMatchResourceAttr("grafana_folder.child2", "id", defaultOrgIDRegexp),
resource.TestCheckResourceAttr("grafana_folder.child2", "title", "Nested Test: Child 2 "+name),
resource.TestCheckResourceAttr("grafana_folder.child2", "parent_folder_uid", name+"-child1"),
),
},
{
ResourceName: "grafana_folder.parent",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"prevent_destroy_if_not_empty"},
},
{
ResourceName: "grafana_folder.child1",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"prevent_destroy_if_not_empty"},
},
{
ResourceName: "grafana_folder.child2",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"prevent_destroy_if_not_empty"},
},
},
})
}

func TestAccFolder_PreventDeletion(t *testing.T) {
testutils.CheckOSSTestsEnabled(t)

Expand Down

0 comments on commit e544ebb

Please sign in to comment.