* feat: unified storage migrations integration tests * chore: add comment and adjust db path name * chore: refactor test cases into interface
209 lines
5.7 KiB
Go
209 lines
5.7 KiB
Go
package migrations_test
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"testing"
|
|
|
|
authlib "github.com/grafana/authlib/types"
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
|
"github.com/grafana/grafana/pkg/tests/apis"
|
|
"github.com/stretchr/testify/require"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
)
|
|
|
|
// foldersAndDashboardsTestCase tests the "folders-dashboards" ResourceMigration
|
|
type foldersAndDashboardsTestCase struct {
|
|
parentFolderUID string
|
|
childFolderUID string
|
|
dashboardUID string
|
|
libPanelUID string
|
|
}
|
|
|
|
// newFoldersAndDashboardsTestCase creates a test case for the compound folders+dashboards migrator
|
|
func newFoldersAndDashboardsTestCase() resourceMigratorTestCase {
|
|
return &foldersAndDashboardsTestCase{
|
|
parentFolderUID: "parent-folder-uid",
|
|
childFolderUID: "child-folder-uid",
|
|
dashboardUID: "", // Will be generated during setup
|
|
libPanelUID: "", // Will be generated during setup
|
|
}
|
|
}
|
|
|
|
func (tc *foldersAndDashboardsTestCase) name() string {
|
|
return "folders-dashboards"
|
|
}
|
|
|
|
func (tc *foldersAndDashboardsTestCase) resources() []schema.GroupVersionResource {
|
|
return []schema.GroupVersionResource{
|
|
{
|
|
Group: "folder.grafana.app",
|
|
Version: "v1beta1",
|
|
Resource: "folders",
|
|
},
|
|
{
|
|
Group: "dashboard.grafana.app",
|
|
Version: "v1beta1",
|
|
Resource: "dashboards",
|
|
},
|
|
}
|
|
}
|
|
|
|
func (tc *foldersAndDashboardsTestCase) setup(t *testing.T, helper *apis.K8sTestHelper) {
|
|
t.Helper()
|
|
|
|
// Create parent folder
|
|
parent := createTestFolder(t, helper, tc.parentFolderUID, "parent-folder", "")
|
|
|
|
// Create child folder (nested under parent)
|
|
child := createTestFolder(t, helper, tc.childFolderUID, "child-folder", parent.UID)
|
|
|
|
// Create library panel in child folder
|
|
tc.libPanelUID = createTestLibraryPanel(t, helper, "Test Library Panel", child.UID)
|
|
|
|
// Create dashboard with library panel in child folder
|
|
tc.dashboardUID = createTestDashboardWithLibraryPanel(t, helper, "dashboard-with-library-panel",
|
|
tc.libPanelUID, "Test LP in dashboard", child.UID)
|
|
}
|
|
|
|
func (tc *foldersAndDashboardsTestCase) verify(t *testing.T, helper *apis.K8sTestHelper, shouldExist bool) {
|
|
t.Helper()
|
|
|
|
// Build maps of UIDs by resource type
|
|
folderUIDs := []string{tc.parentFolderUID, tc.childFolderUID}
|
|
dashboardUIDs := []string{tc.dashboardUID}
|
|
|
|
expectedFolderCount := 0
|
|
if shouldExist {
|
|
expectedFolderCount = len(folderUIDs)
|
|
}
|
|
orgID := helper.Org1.OrgID
|
|
namespace := authlib.OrgNamespaceFormatter(orgID)
|
|
|
|
// Verify folders
|
|
folderCli := helper.GetResourceClient(apis.ResourceClientArgs{
|
|
User: helper.Org1.Admin,
|
|
Namespace: namespace,
|
|
GVR: schema.GroupVersionResource{
|
|
Group: "folder.grafana.app",
|
|
Version: "v1beta1",
|
|
Resource: "folders",
|
|
},
|
|
})
|
|
verifyResourceCount(t, folderCli, expectedFolderCount)
|
|
for _, uid := range folderUIDs {
|
|
verifyResource(t, folderCli, uid, shouldExist)
|
|
}
|
|
|
|
// Verify dashboards
|
|
expectedDashboardCount := 0
|
|
if shouldExist {
|
|
expectedDashboardCount = len(dashboardUIDs)
|
|
}
|
|
dashboardCli := helper.GetResourceClient(apis.ResourceClientArgs{
|
|
User: helper.Org1.Admin,
|
|
Namespace: namespace,
|
|
GVR: schema.GroupVersionResource{
|
|
Group: "dashboard.grafana.app",
|
|
Version: "v1beta1",
|
|
Resource: "dashboards",
|
|
},
|
|
})
|
|
verifyResourceCount(t, dashboardCli, expectedDashboardCount)
|
|
for _, uid := range dashboardUIDs {
|
|
verifyResource(t, dashboardCli, uid, shouldExist)
|
|
}
|
|
}
|
|
|
|
// createTestFolder creates a folder with specified UID and optional parent
|
|
func createTestFolder(t *testing.T, helper *apis.K8sTestHelper, uid, title, parentUID string) *folder.Folder {
|
|
t.Helper()
|
|
|
|
payload := fmt.Sprintf(`{
|
|
"title": "%s",
|
|
"uid": "%s"`, title, uid)
|
|
|
|
if parentUID != "" {
|
|
payload += fmt.Sprintf(`,
|
|
"parentUid": "%s"`, parentUID)
|
|
}
|
|
|
|
payload += "}"
|
|
|
|
folderCreate := apis.DoRequest(helper, apis.RequestParams{
|
|
User: helper.Org1.Admin,
|
|
Method: http.MethodPost,
|
|
Path: "/api/folders",
|
|
Body: []byte(payload),
|
|
}, &folder.Folder{})
|
|
|
|
require.NotNil(t, folderCreate.Result)
|
|
require.Equal(t, uid, folderCreate.Result.UID)
|
|
|
|
return folderCreate.Result
|
|
}
|
|
|
|
// createTestLibraryPanel creates a library panel in a folder
|
|
func createTestLibraryPanel(t *testing.T, helper *apis.K8sTestHelper, name, folderUID string) string {
|
|
t.Helper()
|
|
|
|
libPanelPayload := fmt.Sprintf(`{
|
|
"kind": 1,
|
|
"name": "%s",
|
|
"folderUid": "%s",
|
|
"model": {
|
|
"type": "text",
|
|
"title": "%s"
|
|
}
|
|
}`, name, folderUID, name)
|
|
|
|
libCreate := apis.DoRequest(helper, apis.RequestParams{
|
|
User: helper.Org1.Admin,
|
|
Method: http.MethodPost,
|
|
Path: "/api/library-elements",
|
|
Body: []byte(libPanelPayload),
|
|
}, &map[string]interface{}{})
|
|
|
|
require.NotNil(t, libCreate.Response)
|
|
require.Equal(t, http.StatusOK, libCreate.Response.StatusCode)
|
|
|
|
libPanelUID := (*libCreate.Result)["result"].(map[string]interface{})["uid"].(string)
|
|
require.NotEmpty(t, libPanelUID)
|
|
|
|
return libPanelUID
|
|
}
|
|
|
|
// createTestDashboardWithLibraryPanel creates a dashboard that uses a library panel
|
|
func createTestDashboardWithLibraryPanel(t *testing.T, helper *apis.K8sTestHelper, dashTitle, libPanelUID, libPanelName, folderUID string) string {
|
|
t.Helper()
|
|
|
|
dashPayload := fmt.Sprintf(`{
|
|
"dashboard": {
|
|
"title": "%s",
|
|
"panels": [{
|
|
"id": 1,
|
|
"libraryPanel": {
|
|
"uid": "%s",
|
|
"name": "%s"
|
|
}
|
|
}]
|
|
},
|
|
"folderUid": "%s",
|
|
"overwrite": false
|
|
}`, dashTitle, libPanelUID, libPanelName, folderUID)
|
|
|
|
dashCreate := apis.DoRequest(helper, apis.RequestParams{
|
|
User: helper.Org1.Admin,
|
|
Method: http.MethodPost,
|
|
Path: "/api/dashboards/db",
|
|
Body: []byte(dashPayload),
|
|
}, &map[string]interface{}{})
|
|
|
|
require.NotNil(t, dashCreate.Response)
|
|
require.Equal(t, http.StatusOK, dashCreate.Response.StatusCode)
|
|
|
|
dashUID := (*dashCreate.Result)["uid"].(string)
|
|
require.NotEmpty(t, dashUID)
|
|
return dashUID
|
|
}
|