Skip to content

Commit 4b93ccc

Browse files
authored
feat: allow folders to be moved to nested folders and back (#2279)
* create test to check of a folders parent can be be changed Refs: #2278 Signed-off-by: patst <[email protected]>
1 parent 235e08e commit 4b93ccc

File tree

2 files changed

+127
-1
lines changed

2 files changed

+127
-1
lines changed

internal/resources/grafana/resource_folder.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ func resourceFolder() *common.Resource {
6666
"parent_folder_uid": {
6767
Type: schema.TypeString,
6868
Optional: true,
69-
ForceNew: true,
7069
Description: "The uid of the parent folder. " +
7170
"If set, the folder will be nested. " +
7271
"If not set, the folder will be created in the root folder. " +
@@ -134,6 +133,33 @@ func UpdateFolder(ctx context.Context, d *schema.ResourceData, meta interface{})
134133
return diag.Errorf("failed to get folder %s: %s", idStr, err)
135134
}
136135

136+
if d.HasChange("parent_folder_uid") {
137+
parentUID, ok := d.GetOk("parent_folder_uid")
138+
if !ok {
139+
// If the parent folder UID is not set, we can just clear it
140+
folder.ParentUID = ""
141+
} else {
142+
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
143+
parentFolder, err := GetFolderByIDorUID(client.Folders, parentUID.(string))
144+
if err != nil {
145+
return retry.RetryableError(err)
146+
}
147+
folder.ParentUID = parentFolder.UID
148+
return nil
149+
})
150+
151+
if err != nil {
152+
return diag.Errorf("failed to find parent folder '%s': %s", parentUID, err)
153+
}
154+
}
155+
body := models.MoveFolderCommand{
156+
ParentUID: folder.ParentUID,
157+
}
158+
if _, err := client.Folders.MoveFolder(folder.UID, &body); err != nil {
159+
return diag.FromErr(err)
160+
}
161+
}
162+
137163
body := models.UpdateFolderCommand{
138164
Overwrite: true,
139165
Title: d.Get("title").(string),

internal/resources/grafana/resource_folder_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,106 @@ resource grafana_folder child2 {
171171
})
172172
}
173173

174+
func TestAccFolder_ChangeParent(t *testing.T) {
175+
testutils.CheckOSSTestsEnabled(t, ">=10.3.0")
176+
177+
var parentFolder models.Folder
178+
var childFolder1 models.Folder
179+
name := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
180+
181+
resource.ParallelTest(t, resource.TestCase{
182+
ProtoV5ProviderFactories: testutils.ProtoV5ProviderFactories,
183+
CheckDestroy: resource.ComposeTestCheckFunc(
184+
folderCheckExists.destroyed(&parentFolder, nil),
185+
folderCheckExists.destroyed(&childFolder1, nil),
186+
),
187+
Steps: []resource.TestStep{
188+
{
189+
Config: fmt.Sprintf(`
190+
resource grafana_folder parent {
191+
title = "Nested Test: Parent %[1]s"
192+
}
193+
194+
resource grafana_folder child1 {
195+
title = "Nested Test: Child 1 %[1]s"
196+
uid = "%[1]s-child1"
197+
}
198+
`, name),
199+
Check: resource.ComposeTestCheckFunc(
200+
folderCheckExists.exists("grafana_folder.parent", &parentFolder),
201+
resource.TestMatchResourceAttr("grafana_folder.parent", "id", defaultOrgIDRegexp),
202+
resource.TestCheckResourceAttr("grafana_folder.parent", "title", "Nested Test: Parent "+name),
203+
resource.TestCheckResourceAttr("grafana_folder.parent", "parent_folder_uid", ""),
204+
205+
folderCheckExists.exists("grafana_folder.child1", &childFolder1),
206+
resource.TestMatchResourceAttr("grafana_folder.child1", "id", defaultOrgIDRegexp),
207+
resource.TestCheckResourceAttr("grafana_folder.child1", "title", "Nested Test: Child 1 "+name),
208+
resource.TestCheckResourceAttr("grafana_folder.child1", "parent_folder_uid", ""),
209+
),
210+
},
211+
{
212+
Config: fmt.Sprintf(`
213+
resource grafana_folder parent {
214+
title = "Nested Test: Parent %[1]s"
215+
}
216+
217+
resource grafana_folder child1 {
218+
title = "Nested Test: Child 1 %[1]s"
219+
uid = "%[1]s-child1"
220+
parent_folder_uid = grafana_folder.parent.uid
221+
}
222+
`, name),
223+
Check: resource.ComposeTestCheckFunc(
224+
folderCheckExists.exists("grafana_folder.parent", &parentFolder),
225+
resource.TestMatchResourceAttr("grafana_folder.parent", "id", defaultOrgIDRegexp),
226+
resource.TestCheckResourceAttr("grafana_folder.parent", "title", "Nested Test: Parent "+name),
227+
resource.TestCheckResourceAttr("grafana_folder.parent", "parent_folder_uid", ""),
228+
229+
folderCheckExists.exists("grafana_folder.child1", &childFolder1),
230+
resource.TestMatchResourceAttr("grafana_folder.child1", "id", defaultOrgIDRegexp),
231+
resource.TestCheckResourceAttr("grafana_folder.child1", "title", "Nested Test: Child 1 "+name),
232+
resource.TestCheckResourceAttrSet("grafana_folder.child1", "parent_folder_uid"),
233+
),
234+
},
235+
{
236+
Config: fmt.Sprintf(`
237+
resource grafana_folder parent {
238+
title = "Nested Test: Parent %[1]s"
239+
}
240+
241+
resource grafana_folder child1 {
242+
title = "Nested Test: Child 1 %[1]s"
243+
uid = "%[1]s-child1"
244+
}
245+
`, name),
246+
Check: resource.ComposeTestCheckFunc(
247+
folderCheckExists.exists("grafana_folder.parent", &parentFolder),
248+
resource.TestMatchResourceAttr("grafana_folder.parent", "id", defaultOrgIDRegexp),
249+
resource.TestCheckResourceAttr("grafana_folder.parent", "title", "Nested Test: Parent "+name),
250+
resource.TestCheckResourceAttr("grafana_folder.parent", "parent_folder_uid", ""),
251+
252+
folderCheckExists.exists("grafana_folder.child1", &childFolder1),
253+
resource.TestMatchResourceAttr("grafana_folder.child1", "id", defaultOrgIDRegexp),
254+
resource.TestCheckResourceAttr("grafana_folder.child1", "title", "Nested Test: Child 1 "+name),
255+
resource.TestCheckResourceAttr("grafana_folder.child1", "parent_folder_uid", ""),
256+
),
257+
},
258+
{
259+
ResourceName: "grafana_folder.parent",
260+
ImportState: true,
261+
ImportStateVerify: true,
262+
ImportStateVerifyIgnore: []string{"prevent_destroy_if_not_empty"},
263+
},
264+
{
265+
ResourceName: "grafana_folder.child1",
266+
ImportState: true,
267+
ImportStateVerify: true,
268+
ImportStateVerifyIgnore: []string{"prevent_destroy_if_not_empty"},
269+
},
270+
},
271+
})
272+
}
273+
174274
func TestAccFolder_PreventDeletion(t *testing.T) {
175275
testutils.CheckOSSTestsEnabled(t, ">=10.2.0") // Searching by folder UID was added in 10.2.0
176276

0 commit comments

Comments
 (0)