mirror of
https://github.com/grafana/grafana.git
synced 2026-08-09 12:48:18 -05:00
Provisioning: move repository integration tests to its own package (#120183)
* chore: move provisioning repository integ test own package * chore: fix mixing variable in test
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tests/testsuite"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testsuite.Run(m)
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package provisioning
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
+65
-36
@@ -1,4 +1,4 @@
|
||||
package provisioning
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -38,6 +38,35 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util/testutil"
|
||||
)
|
||||
|
||||
//nolint:gosec // Test RSA private key (generated for testing purposes only)
|
||||
const testPrivateKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEoQIBAAKCAQBn1MuM5hIfH6d3TNStI1ofWv/gcjQ4joi9cFijEwVLuPYkF1nD
|
||||
KkSbaMGFUWiOTaB/H9fxmd/V2u04NlBY3av6m5T/sHfVSiEWAEUblh3cA34HVCmD
|
||||
cqyyVty5HLGJJlSs2C7W2x7yUc9ImzyDBsyjpKOXuojJ9wN9a17D2cYU5WkXjoDC
|
||||
4BHid61jn9WBTtPZXSgOdirwahNzxZQSIP7DA9T8yiZwIWPp5YesgsAPyQLCFPgM
|
||||
s77xz/CEUnEYQ35zI/k/mQrwKdQ/ZP8xLwQohUID0BIxE7G5quL069RuuCZWZkoF
|
||||
oPiZbp7HSryz1+19jD3rFT7eHGUYvAyCnXmXAgMBAAECggEADSs4Bc7ITZo+Kytb
|
||||
bfol3AQ2n8jcRrANN7mgBE7NRSVYUouDnvUlbnCC2t3QXPwLdxQa11GkygLSQ2bg
|
||||
GeVDgq1o4GUJTcvxFlFCcpU/hEANI/DQsxNAQ/4wUGoLOlHaO3HPvwBblHA70gGe
|
||||
Ux/xpG+lMAFAiB0EHEwZ4M0mClBEOQv3NzaFTWuBHtIMS8eid7M1q5qz9+rCgZSL
|
||||
KBBHo0OvUbajG4CWl8SM6LUYapASGg+U17E+4xA3npwpIdsk+CbtX+vvX324n4kn
|
||||
0EkrJqCjv8M1KiCKAP+UxwP00ywxOg4PN+x+dHI/I7xBvEKe/x6BltVSdGA+PlUK
|
||||
02wagQKBgQDF7gdQLFIagPH7X7dBP6qEGxj/Ck9Qdz3S1gotPkVeq+1/UtQijYZ1
|
||||
j44up/0yB2B9P4kW091n+iWcyfoU5UwBua9dHvCZP3QH05LR1ZscUHxLGjDPBASt
|
||||
l2xSq0hqqNWBspb1M0eCY0Yxi65iDkj3xsI2iN35BEb1FlWdR5KGvwKBgQCGS0ce
|
||||
wASWbZIPU2UoKGOQkIJU6QmLy0KZbfYkpyfE8IxGttYVEQ8puNvDDNZWHNf+LP85
|
||||
c8iV6SfnWiLmu1XkG2YmJFBCCAWgJ8Mq2XQD8E+a/xcaW3NqlcC5+I2czX367j3r
|
||||
69wZSxRbzR+DCfOiIkrekJImwN183ZYy2cBbKQKBgFj86IrSMmO6H5Ft+j06u5ZD
|
||||
fJyF7Rz3T3NwSgkHWzbyQ4ggHEIgsRg/36P4YSzSBj6phyAdRwkNfUWdxXMJmH+a
|
||||
FU7frzqnPaqbJAJ1cBRt10QI1XLtkpDdaJVObvONTtjOC3LYiEkGCzQRYeiyFXpZ
|
||||
AU51gJ8JnkFotjtNR4KPAoGAehVREDlLcl0lnN0ZZspgyPk2Im6/iOA9KTH3xBZZ
|
||||
ZwWu4FIyiHA7spgk4Ep5R0ttZ9oMI3SIcw/EgONGOy8uw/HMiPwWIhEc3B2JpRiO
|
||||
CU6bb7JalFFyuQBudiHoyxVcY5PVovWF31CLr3DoJr4TR9+Y5H/U/XnzYCIo+w1N
|
||||
exECgYBFAGKYTIeGAvhIvD5TphLpbCyeVLBIq5hRyrdRY+6Iwqdr5PGvLPKwin5+
|
||||
+4CDhWPW4spq8MYPCRiMrvRSctKt/7FhVGL2vE/0VY3TcLk14qLC+2+0lnPVgnYn
|
||||
u5/wOyuHp1cIBnjeN41/pluOWFBHI9xLW3ExLtmYMiecJ8VdRA==
|
||||
-----END RSA PRIVATE KEY-----`
|
||||
|
||||
func TestIntegrationProvisioning_CreatingAndGetting(t *testing.T) {
|
||||
testutil.SkipIntegrationTestInShortMode(t)
|
||||
|
||||
@@ -46,8 +75,8 @@ func TestIntegrationProvisioning_CreatingAndGetting(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
inputFiles := []string{
|
||||
"testdata/github-readonly.json.tmpl",
|
||||
"testdata/local-readonly.json.tmpl",
|
||||
"../testdata/github-readonly.json.tmpl",
|
||||
"../testdata/local-readonly.json.tmpl",
|
||||
}
|
||||
|
||||
for _, inputFilePath := range inputFiles {
|
||||
@@ -300,7 +329,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
{
|
||||
name: "should succeed with valid local repository",
|
||||
repo: func() *unstructured.Unstructured {
|
||||
return helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{
|
||||
return helper.RenderObject(t, "../testdata/local-readonly.json.tmpl", map[string]any{
|
||||
"Name": "valid-repo",
|
||||
"SyncEnabled": true,
|
||||
})
|
||||
@@ -309,7 +338,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
{
|
||||
name: "should error if mutually exclusive finalizers are set",
|
||||
repo: func() *unstructured.Unstructured {
|
||||
localTmp := helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{
|
||||
localTmp := helper.RenderObject(t, "../testdata/local-readonly.json.tmpl", map[string]any{
|
||||
"Name": "repo-with-invalid-finalizers",
|
||||
"SyncEnabled": true,
|
||||
})
|
||||
@@ -328,7 +357,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
{
|
||||
name: "should error if unknown finalizer is set",
|
||||
repo: func() *unstructured.Unstructured {
|
||||
localTmp := helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{
|
||||
localTmp := helper.RenderObject(t, "../testdata/local-readonly.json.tmpl", map[string]any{
|
||||
"Name": "repo-with-unknown-finalizer",
|
||||
"SyncEnabled": true,
|
||||
})
|
||||
@@ -487,7 +516,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
for i, test := range pathTests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
repoName := fmt.Sprintf("git-path-test-%d", i+1)
|
||||
gitRepo := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
gitRepo := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": repoName,
|
||||
"URL": baseURL,
|
||||
"Path": test.path,
|
||||
@@ -519,7 +548,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
baseURL := "https://github.com/grafana/test-repo-path-sync-disabled"
|
||||
|
||||
// Create an initial repo with sync disabled and a specific path
|
||||
firstRepo := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
firstRepo := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": "git-sync-disabled-1",
|
||||
"URL": baseURL,
|
||||
"Path": "demo/nested",
|
||||
@@ -531,7 +560,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
|
||||
// Create a second repo pointing to same URL with a child path and sync disabled.
|
||||
// This simulates the wizard onboarding flow where sync is not yet enabled.
|
||||
secondRepo := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
secondRepo := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": "git-sync-disabled-2",
|
||||
"URL": baseURL,
|
||||
"Path": "demo/nested/child",
|
||||
@@ -542,7 +571,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
require.NoError(t, err, "Second repository with child path should succeed when sync is disabled")
|
||||
|
||||
// Create a third repo with the same path (duplicate) and sync disabled
|
||||
thirdRepo := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
thirdRepo := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": "git-sync-disabled-3",
|
||||
"URL": baseURL,
|
||||
"Path": "demo/nested",
|
||||
@@ -553,7 +582,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
require.NoError(t, err, "Third repository with duplicate path should succeed when sync is disabled")
|
||||
|
||||
// Create a fourth repo with empty path (root) and sync disabled - wizard step 1 scenario
|
||||
fourthRepo := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
fourthRepo := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": "git-sync-disabled-4",
|
||||
"URL": baseURL,
|
||||
"Path": "",
|
||||
@@ -569,7 +598,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
baseURL := "https://github.com/grafana/test-repo-enable-sync-conflict"
|
||||
|
||||
// Create an initial repo with sync enabled and a specific path
|
||||
firstRepo := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
firstRepo := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": "git-enable-sync-1",
|
||||
"URL": baseURL,
|
||||
"Path": "demo/nested",
|
||||
@@ -580,7 +609,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
require.NoError(t, err, "First repository should be created successfully")
|
||||
|
||||
// Create second repo with conflicting child path but sync disabled (should succeed)
|
||||
secondRepo := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
secondRepo := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": "git-enable-sync-2",
|
||||
"URL": baseURL,
|
||||
"Path": "demo/nested/child",
|
||||
@@ -598,7 +627,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("should update sync interval", func(t *testing.T) {
|
||||
r := helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{
|
||||
r := helper.RenderObject(t, "../testdata/local-readonly.json.tmpl", map[string]any{
|
||||
"Name": "valid-repo-testinterval",
|
||||
"SyncEnabled": true,
|
||||
"SyncIntervalSeconds": 5,
|
||||
@@ -611,7 +640,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("should automatically add finalizers during creation", func(t *testing.T) {
|
||||
r := helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{
|
||||
r := helper.RenderObject(t, "../testdata/local-readonly.json.tmpl", map[string]any{
|
||||
"Name": "repo-auto-finalizers",
|
||||
"SyncEnabled": false,
|
||||
})
|
||||
@@ -631,7 +660,7 @@ func TestIntegrationProvisioning_RepositoryValidation(t *testing.T) {
|
||||
|
||||
t.Run("should re-add finalizers when removed during update", func(t *testing.T) {
|
||||
// Create a repository with finalizers
|
||||
r := helper.RenderObject(t, "testdata/local-readonly.json.tmpl", map[string]any{
|
||||
r := helper.RenderObject(t, "../testdata/local-readonly.json.tmpl", map[string]any{
|
||||
"Name": "repo-update-finalizers",
|
||||
"SyncEnabled": false,
|
||||
})
|
||||
@@ -672,9 +701,9 @@ func TestIntegrationProvisioning_FailInvalidSchema(t *testing.T) {
|
||||
|
||||
const repo = "invalid-schema-tmp"
|
||||
// Set up the repository and the file to import.
|
||||
helper.CopyToProvisioningPath(t, "testdata/invalid-dashboard-schema.json", "invalid-dashboard-schema.json")
|
||||
helper.CopyToProvisioningPath(t, "../testdata/invalid-dashboard-schema.json", "invalid-dashboard-schema.json")
|
||||
|
||||
localTmp := helper.RenderObject(t, "testdata/local-write.json.tmpl", map[string]any{
|
||||
localTmp := helper.RenderObject(t, "../testdata/local-write.json.tmpl", map[string]any{
|
||||
"Name": repo,
|
||||
"SyncEnabled": true,
|
||||
})
|
||||
@@ -729,9 +758,9 @@ func TestIntegrationProvisioning_CreatingGitHubRepository(t *testing.T) {
|
||||
// treeEntryDir("grafana", "subtree"),
|
||||
// },
|
||||
// "subtree": {
|
||||
// treeEntry("dashboard.json", helper.LoadFile("testdata/all-panels.json")),
|
||||
// treeEntry("dashboard.json", helper.LoadFile("../testdata/all-panels.json")),
|
||||
// treeEntryDir("subdir", "subtree2"),
|
||||
// treeEntry("subdir/dashboard2.yaml", helper.LoadFile("testdata/text-options.json")),
|
||||
// treeEntry("subdir/dashboard2.yaml", helper.LoadFile("../testdata/text-options.json")),
|
||||
// },
|
||||
// })),
|
||||
|
||||
@@ -744,7 +773,7 @@ func TestIntegrationProvisioning_CreatingGitHubRepository(t *testing.T) {
|
||||
const repo = "github-create-test"
|
||||
testRepo := common.TestRepo{
|
||||
Name: repo,
|
||||
Template: "testdata/github-readonly.json.tmpl",
|
||||
Template: "../testdata/github-readonly.json.tmpl",
|
||||
Target: "folder",
|
||||
ExpectedDashboards: 3,
|
||||
ExpectedFolders: 3, // Folder sync creates an additional folder for the repository itself
|
||||
@@ -807,7 +836,7 @@ func TestIntegrationProvisioning_CreatingGitHubRepository(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// Create repository directly without health checks since we're only testing URL cleanup
|
||||
input := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
input := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": test.name,
|
||||
"URL": test.input,
|
||||
"SyncTarget": "folder",
|
||||
@@ -837,7 +866,7 @@ func TestIntegrationProvisioning_ReadOnlyRepositoryNoWebhook(t *testing.T) {
|
||||
|
||||
t.Run("repository with no workflows should not create a webhook", func(t *testing.T) {
|
||||
repoName := "readonly-no-webhook"
|
||||
input := helper.RenderObject(t, "testdata/github-readonly.json.tmpl", map[string]any{
|
||||
input := helper.RenderObject(t, "../testdata/github-readonly.json.tmpl", map[string]any{
|
||||
"Name": repoName,
|
||||
"SyncEnabled": false,
|
||||
})
|
||||
@@ -1128,7 +1157,7 @@ func TestIntegrationProvisioning_RepositoryLimits(t *testing.T) {
|
||||
helper.CreateRepo(t, originalRepo)
|
||||
|
||||
t.Run("folder sync is rejected when instance sync exists", func(t *testing.T) {
|
||||
folderRepo := helper.RenderObject(t, "testdata/local-write.json.tmpl", map[string]any{
|
||||
folderRepo := helper.RenderObject(t, "../testdata/local-write.json.tmpl", map[string]any{
|
||||
"Name": "folder-blocked-by-instance",
|
||||
"SyncEnabled": true,
|
||||
"SyncTarget": "folder",
|
||||
@@ -1174,7 +1203,7 @@ func TestIntegrationProvisioning_RepositoryLimits(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("instance sync rejected when any other repository exists", func(t *testing.T) {
|
||||
instanceRepo := helper.RenderObject(t, "testdata/local-write.json.tmpl", map[string]any{
|
||||
instanceRepo := helper.RenderObject(t, "../testdata/local-write.json.tmpl", map[string]any{
|
||||
"Name": "instance-repo-blocked",
|
||||
"SyncEnabled": true,
|
||||
"SyncTarget": "instance",
|
||||
@@ -1223,7 +1252,7 @@ func TestIntegrationProvisioning_RepositoryLimits(t *testing.T) {
|
||||
|
||||
// Try to create the 11th repository - should fail due to limit
|
||||
eleventhRepoName := "limit-test-repo-11"
|
||||
eleventhRepo := helper.RenderObject(t, "testdata/local-write.json.tmpl", map[string]any{
|
||||
eleventhRepo := helper.RenderObject(t, "../testdata/local-write.json.tmpl", map[string]any{
|
||||
"Name": eleventhRepoName,
|
||||
"SyncEnabled": true,
|
||||
"SyncTarget": "folder",
|
||||
@@ -1266,7 +1295,7 @@ func TestIntegrationProvisioning_RunLocalRepository(t *testing.T) {
|
||||
Resource("repositories").
|
||||
Name(repo).
|
||||
SubResource("files", targetPath).
|
||||
Body(helper.LoadFile("testdata/all-panels.json")).
|
||||
Body(helper.LoadFile("../testdata/all-panels.json")).
|
||||
SetHeader("Content-Type", "application/json").
|
||||
Do(ctx).StatusCode(&code)
|
||||
require.Equal(t, http.StatusNotFound, code)
|
||||
@@ -1278,7 +1307,7 @@ func TestIntegrationProvisioning_RunLocalRepository(t *testing.T) {
|
||||
Resource("repositories").
|
||||
Name(repo).
|
||||
SubResource("files", targetPath).
|
||||
Body(helper.LoadFile("testdata/all-panels.json")).
|
||||
Body(helper.LoadFile("../testdata/all-panels.json")).
|
||||
SetHeader("Content-Type", "application/json").
|
||||
Do(ctx).StatusCode(&code)
|
||||
require.NoError(t, result.Error(), "expecting to be able to create file")
|
||||
@@ -1353,7 +1382,7 @@ func TestIntegrationProvisioning_RunLocalRepository(t *testing.T) {
|
||||
Resource("repositories").
|
||||
Name(repo).
|
||||
SubResource("files", "test", "..", "..", "all-panels.json"). // UNSAFE PATH
|
||||
Body(helper.LoadFile("testdata/all-panels.json")).
|
||||
Body(helper.LoadFile("../testdata/all-panels.json")).
|
||||
SetHeader("Content-Type", "application/json").
|
||||
Do(ctx)
|
||||
require.Error(t, result.Error(), "invalid path should return error")
|
||||
@@ -1441,7 +1470,7 @@ func TestIntegrationProvisioning_ImportAllPanelsFromLocalRepository(t *testing.T
|
||||
testRepo := common.TestRepo{
|
||||
Name: repo,
|
||||
Target: "folder",
|
||||
Copies: map[string]string{"testdata/all-panels.json": "all-panels.json"},
|
||||
Copies: map[string]string{"../testdata/all-panels.json": "all-panels.json"},
|
||||
ExpectedDashboards: 1,
|
||||
ExpectedFolders: 1, // folder sync creates a folder
|
||||
}
|
||||
@@ -1500,7 +1529,7 @@ func TestIntegrationProvisioning_DeleteRepositoryAndReleaseResources(t *testing.
|
||||
const repo = "gh-repo"
|
||||
testRepo := common.TestRepo{
|
||||
Name: repo,
|
||||
Template: "testdata/github-readonly.json.tmpl",
|
||||
Template: "../testdata/github-readonly.json.tmpl",
|
||||
Target: "folder",
|
||||
ExpectedDashboards: 3,
|
||||
ExpectedFolders: 3,
|
||||
@@ -1757,7 +1786,7 @@ func TestIntegrationProvisioning_RefsPermissions(t *testing.T) {
|
||||
const repo = "refs-permissions-test"
|
||||
testRepo := common.TestRepo{
|
||||
Name: repo,
|
||||
Template: "testdata/github-readonly.json.tmpl",
|
||||
Template: "../testdata/github-readonly.json.tmpl",
|
||||
Target: "folder",
|
||||
ExpectedDashboards: 3,
|
||||
ExpectedFolders: 3, // Repository creates folders
|
||||
@@ -1821,7 +1850,7 @@ func TestIntegrationProvisioning_EmptyPath(t *testing.T) {
|
||||
const repo = "empty-path-test"
|
||||
testRepo := common.TestRepo{
|
||||
Name: repo,
|
||||
Template: "testdata/github-empty-path.json.tmpl",
|
||||
Template: "../testdata/github-empty-path.json.tmpl",
|
||||
Target: "folder",
|
||||
Values: map[string]any{
|
||||
"SyncEnabled": true,
|
||||
@@ -1849,7 +1878,7 @@ func TestIntegrationProvisioning_EmptyPath(t *testing.T) {
|
||||
// Step 1: Create first repository with empty path - syncs successfully
|
||||
testRepo1 := common.TestRepo{
|
||||
Name: repo1,
|
||||
Template: "testdata/github-empty-path.json.tmpl",
|
||||
Template: "../testdata/github-empty-path.json.tmpl",
|
||||
Target: "folder",
|
||||
Values: map[string]any{
|
||||
"SyncEnabled": true,
|
||||
@@ -1864,7 +1893,7 @@ func TestIntegrationProvisioning_EmptyPath(t *testing.T) {
|
||||
// but sync should warn because dashboards are owned by repo1
|
||||
testRepo2 := common.TestRepo{
|
||||
Name: repo2,
|
||||
Template: "testdata/github-empty-path.json.tmpl",
|
||||
Template: "../testdata/github-empty-path.json.tmpl",
|
||||
Target: "folder",
|
||||
Values: map[string]any{
|
||||
"SyncEnabled": true,
|
||||
@@ -2833,7 +2862,7 @@ func TestIntegrationProvisioning_FolderTitleUpdatesOnSync(t *testing.T) {
|
||||
helper.CreateRepo(t, common.TestRepo{
|
||||
Name: repoName,
|
||||
Target: "folder",
|
||||
Copies: map[string]string{"testdata/all-panels.json": "all-panels.json"},
|
||||
Copies: map[string]string{"../testdata/all-panels.json": "all-panels.json"},
|
||||
ExpectedDashboards: 1,
|
||||
ExpectedFolders: 1,
|
||||
Values: map[string]any{
|
||||
Reference in New Issue
Block a user