Dashboards: Use the OpenAPI generated by app-sdk in the manifest to … (#114858)

This commit is contained in:
Austin Pond
2025-12-06 08:01:28 +00:00
committed by GitHub
parent e9ba45ca4f
commit 8e11851bb0
6 changed files with 5552 additions and 1175 deletions
+1 -2
View File
@@ -11,8 +11,7 @@ do-generate: install-app-sdk update-app-sdk ## Run Grafana App SDK code generati
--tsgenpath=../../packages/grafana-schema/src/schema \
--grouping=group \
--defencoding=none \
--genoperatorstate=false \
--noschemasinmanifest
--genoperatorstate=false
.PHONY: post-generate-cleanup
post-generate-cleanup: ## Clean up the generated code
File diff suppressed because one or more lines are too long
+45
View File
@@ -24,6 +24,7 @@ import (
authlib "github.com/grafana/authlib/types"
"github.com/grafana/grafana-app-sdk/logging"
manifestdata "github.com/grafana/grafana/apps/dashboard/pkg/apis"
internal "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard"
dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
@@ -843,6 +844,50 @@ func (b *DashboardsAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefiniti
maps.Copy(defs, dashv1.GetOpenAPIDefinitions(ref))
maps.Copy(defs, dashv2alpha1.GetOpenAPIDefinitions(ref))
maps.Copy(defs, dashv2beta1.GetOpenAPIDefinitions(ref))
md := manifestdata.LocalManifest().ManifestData
// Overwrite the OpenAPI generated from kubernetes (sourced from the go types) with the OpenAPI generated by grafana-app-sdk
// from the manifest CUE, as it correctly handles the CUE disjunctions in the dashboard spec.
// We don't touch any types which were not specified in the manifest CUE (such as custom route types).
for _, version := range md.Versions {
// We don't need to correct the v0 or v1 openAPI as the spec type is just `any`
if len(version.Name) > 1 && (version.Name[1] == '0' || version.Name[1] == '1') {
continue
}
for _, kind := range version.Kinds {
pkgPrefix := fmt.Sprintf("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/%s", version.Name)
oapi, err := kind.Schema.AsKubeOpenAPI(schema.GroupVersionKind{
Group: md.Group,
Version: version.Name,
Kind: kind.Kind,
}, ref, pkgPrefix)
if err != nil {
logging.DefaultLogger.Error("unable to generate openAPI for kind %s: %w", kind.Kind, err)
continue
}
maps.Copy(defs, oapi)
}
}
// Fix legacyOptions schema for v2alpha1 and v2beta1 to allow any value type
// The generated schema incorrectly restricts values to objects, but map[string]interface{} can hold any type
// This fix must be applied here so structured-merge-diff uses the correct schema
// For some reason this issue occurs with both the kubernetes-generated openAPI sourced from go, _and_ the OpenAPI from the AppManifest
// TODO: @IfSentient this should really be addressed in the app-sdk's generation, or work out what about this particular CUE value is broken
for _, defKey := range []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardAnnotationQuerySpec",
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQuerySpec",
} {
if def, ok := defs[defKey]; ok {
if legacyOptions, ok := def.Schema.Properties["legacyOptions"]; ok {
// Fix: Use additionalProperties: true to allow any value type (string, number, boolean, array, object, etc.)
// instead of restricting to objects only. This must match map[string]interface{} semantics.
legacyOptions.AdditionalProperties = &spec.SchemaOrBool{Allows: true}
def.Schema.Properties["legacyOptions"] = legacyOptions
defs[defKey] = def
}
}
}
return defs
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3
View File
@@ -78,6 +78,9 @@ func TestIntegrationOpenAPIs(t *testing.T) {
}, {
Group: "dashboard.grafana.app",
Version: "v2alpha1",
}, {
Group: "dashboard.grafana.app",
Version: "v2beta1",
}, {
Group: "folder.grafana.app",
Version: "v1beta1",