Dashboards: Add apiVersion to dashboard table (#100845)

This commit is contained in:
Ryan McKinley
2025-03-04 07:47:45 +03:00
committed by GitHub
parent 8a341ebcce
commit c1b48cc488
84 changed files with 1074 additions and 2392 deletions
@@ -9,12 +9,18 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tests/apis"
"github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/grafana/grafana/pkg/tests/testsuite"
dashboardV0 "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
dashboardV1 "github.com/grafana/grafana/pkg/apis/dashboard/v1alpha1"
dashboardV2 "github.com/grafana/grafana/pkg/apis/dashboard/v2alpha1"
)
func TestMain(m *testing.M) {
@@ -40,6 +46,8 @@ func runDashboardTest(t *testing.T, helper *apis.K8sTestHelper, gvr schema.Group
},
}
obj.SetGenerateName("aa")
obj.SetAPIVersion(gvr.GroupVersion().String())
obj.SetKind("Dashboard")
obj, err = client.Resource.Create(ctx, obj, metav1.CreateOptions{})
require.NoError(t, err)
created := obj.GetName()
@@ -241,3 +249,93 @@ func TestIntegrationDashboardsAppV1Alpha1(t *testing.T) {
runDashboardTest(t, helper, gvr)
})
}
func TestIntegrationLegacySupport(t *testing.T) {
ctx := context.Background()
helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
EnableFeatureToggles: []string{
// NOTE: when using this feature toggle, the read is always v0!
// featuremgmt.FlagKubernetesClientDashboardsFolders
},
})
clientV0 := helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Admin,
GVR: dashboardV0.DashboardResourceInfo.GroupVersionResource(),
})
obj, err := clientV0.Resource.Create(ctx,
helper.LoadYAMLOrJSONFile("testdata/dashboard-test-v0.yaml"),
metav1.CreateOptions{},
)
require.NoError(t, err)
require.Equal(t, "test-v0", obj.GetName())
clientV1 := helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Admin,
GVR: dashboardV1.DashboardResourceInfo.GroupVersionResource(),
})
obj, err = clientV1.Resource.Create(ctx,
helper.LoadYAMLOrJSONFile("testdata/dashboard-test-v1.yaml"),
metav1.CreateOptions{},
)
require.NoError(t, err)
require.Equal(t, "test-v1", obj.GetName())
clientV2 := helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Admin,
GVR: dashboardV2.DashboardResourceInfo.GroupVersionResource(),
})
obj, err = clientV2.Resource.Create(ctx,
helper.LoadYAMLOrJSONFile("testdata/dashboard-test-v2.yaml"),
metav1.CreateOptions{},
)
require.NoError(t, err)
require.Equal(t, "test-v2", obj.GetName())
//---------------------------------------------------------
// Now check that we can get each dashboard with any API
//---------------------------------------------------------
names := []string{"test-v0", "test-v1", "test-v2"}
clients := []dynamic.ResourceInterface{
clientV0.Resource,
clientV1.Resource,
clientV2.Resource,
}
for _, name := range names {
for _, client := range clients {
obj, err := client.Get(ctx, name, metav1.GetOptions{})
require.NoError(t, err)
require.Equal(t, name, obj.GetName())
// Can get the same thing with the /dto endpoint
obj, err = client.Get(ctx, name, metav1.GetOptions{}, "dto")
require.NoError(t, err)
require.Equal(t, name, obj.GetName())
}
}
//---------------------------------------------------------
// Check that the legacy APIs return the correct apiVersion
//---------------------------------------------------------
rsp := apis.DoRequest(helper, apis.RequestParams{
User: helper.Org1.Admin,
Path: "/api/dashboards/uid/test-v0",
}, &dtos.DashboardFullWithMeta{})
require.Equal(t, 200, rsp.Response.StatusCode)
require.Equal(t, "v0alpha1", rsp.Result.Meta.APIVersion)
rsp = apis.DoRequest(helper, apis.RequestParams{
User: helper.Org1.Admin,
Path: "/api/dashboards/uid/test-v1",
}, &dtos.DashboardFullWithMeta{})
require.Equal(t, 200, rsp.Response.StatusCode)
require.Equal(t, "v1alpha1", rsp.Result.Meta.APIVersion)
// V2 should send a redirect
rsp = apis.DoRequest(helper, apis.RequestParams{
User: helper.Org1.Admin,
Path: "/api/dashboards/uid/test-v2",
}, &dtos.DashboardFullWithMeta{})
require.Equal(t, 302, rsp.Response.StatusCode) // redirect
}
@@ -1,6 +1,6 @@
apiVersion: dashboard.grafana.app/v0alpha1
kind: Dashboard
metadata:
name: test
name: test-v0
spec:
title: Test dashboard (apply from k8s; PATCH) X
title: Test dashboard. Created at v0
@@ -0,0 +1,6 @@
apiVersion: dashboard.grafana.app/v1alpha1
kind: Dashboard
metadata:
name: test-v1
spec:
title: Test dashboard. Created at v1 XXX
@@ -0,0 +1,6 @@
apiVersion: dashboard.grafana.app/v2alpha1
kind: Dashboard
metadata:
name: test-v2
spec:
title: Test dashboard. Created at v2
+6 -1
View File
@@ -385,7 +385,12 @@ func DoRequest[T any](c *K8sTestHelper, params RequestParams, result *T) K8sResp
if params.Accept != "" {
req.Header.Set("Accept", params.Accept)
}
rsp, err := http.DefaultClient.Do(req)
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
rsp, err := client.Do(req)
require.NoError(c.t, err)
r := K8sResponse[T]{
@@ -1058,22 +1058,6 @@
"type": "string",
"uniqueItems": true
}
},
{
"name": "path",
"in": "query",
"schema": {
"type": "string",
"uniqueItems": true
}
},
{
"name": "version",
"in": "query",
"schema": {
"type": "integer",
"uniqueItems": true
}
}
]
},
@@ -1652,6 +1636,20 @@
}
}
},
"com.github.grafana.grafana.pkg.apis.dashboard.v0alpha1.ConversionStatus": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"failed": {
"type": "boolean"
},
"storedVersion": {
"type": "string"
}
}
},
"com.github.grafana.grafana.pkg.apis.dashboard.v0alpha1.Dashboard": {
"type": "object",
"required": [
@@ -1682,6 +1680,14 @@
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured"
}
]
},
"status": {
"description": "Optional dashboard status",
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.dashboard.v0alpha1.DashboardStatus"
}
]
}
},
"x-kubernetes-group-version-kind": [
@@ -1776,6 +1782,14 @@
}
]
},
"com.github.grafana.grafana.pkg.apis.dashboard.v0alpha1.DashboardStatus": {
"type": "object",
"properties": {
"conversion": {
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.dashboard.v0alpha1.ConversionStatus"
}
}
},
"com.github.grafana.grafana.pkg.apis.dashboard.v0alpha1.DashboardWithAccessInfo": {
"description": "This is like the legacy DTO where access and metadata are all returned in a single call",
"type": "object",
@@ -1816,6 +1830,14 @@
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured"
}
]
},
"status": {
"description": "Optional dashboard status",
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.dashboard.v0alpha1.DashboardStatus"
}
]
}
},
"x-kubernetes-group-version-kind": [