Grafana Advisor: Automatically generate frontend types (#99807)

* Grafana Advisor: Frontend types

* fix bad merge
This commit is contained in:
Andres Martinez Gotor
2025-02-03 11:45:17 +01:00
committed by GitHub
parent 74e3beabd0
commit 4cd2ebe186
8 changed files with 114 additions and 103 deletions
+1
View File
@@ -0,0 +1 @@
plugin/src
+16 -13
View File
@@ -7,7 +7,7 @@ check: {
versions: { versions: {
"v0alpha1": { "v0alpha1": {
codegen: { codegen: {
frontend: false frontend: true
backend: true backend: true
} }
validation: { validation: {
@@ -17,24 +17,27 @@ check: {
] ]
} }
schema: { schema: {
spec: { #Data: {
// Generic data input that a check can receive // Generic data input that a check can receive
data?: [string]: string data?: [string]: string
} }
status: { #ReportError: {
report: { // Severity of the error
severity: "high" | "low"
// Human readable reason for the error
reason: string
// Action to take to resolve the error
action: string
}
#Report: {
// Number of elements analyzed // Number of elements analyzed
count: int count: int
// List of errors // List of errors
errors: [...{ errors: [...#ReportError]
// Severity of the error }
severity: "high" | "low" spec: #Data
// Human readable reason for the error status: {
reason: string report: #Report
// Action to take to resolve the error
action: string
}]
}
} }
} }
} }
@@ -2,6 +2,21 @@
package v0alpha1 package v0alpha1
// +k8s:openapi-gen=true
type CheckReportError struct {
// Severity of the error
Severity CheckReportErrorSeverity `json:"severity"`
// Human readable reason for the error
Reason string `json:"reason"`
// Action to take to resolve the error
Action string `json:"action"`
}
// NewCheckReportError creates a new CheckReportError object.
func NewCheckReportError() *CheckReportError {
return &CheckReportError{}
}
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
type CheckstatusOperatorState struct { type CheckstatusOperatorState struct {
// lastEvaluation is the ResourceVersion last evaluated // lastEvaluation is the ResourceVersion last evaluated
@@ -37,6 +52,14 @@ func NewCheckStatus() *CheckStatus {
} }
} }
// +k8s:openapi-gen=true
type CheckReportErrorSeverity string
const (
CheckReportErrorSeverityHigh CheckReportErrorSeverity = "high"
CheckReportErrorSeverityLow CheckReportErrorSeverity = "low"
)
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
type CheckStatusOperatorStateState string type CheckStatusOperatorStateState string
@@ -46,35 +69,12 @@ const (
CheckStatusOperatorStateStateFailed CheckStatusOperatorStateState = "failed" CheckStatusOperatorStateStateFailed CheckStatusOperatorStateState = "failed"
) )
// +k8s:openapi-gen=true
type CheckStatusSeverity string
const (
CheckStatusSeverityHigh CheckStatusSeverity = "high"
CheckStatusSeverityLow CheckStatusSeverity = "low"
)
// +k8s:openapi-gen=true
type CheckV0alpha1StatusReportErrors struct {
// Severity of the error
Severity CheckStatusSeverity `json:"severity"`
// Human readable reason for the error
Reason string `json:"reason"`
// Action to take to resolve the error
Action string `json:"action"`
}
// NewCheckV0alpha1StatusReportErrors creates a new CheckV0alpha1StatusReportErrors object.
func NewCheckV0alpha1StatusReportErrors() *CheckV0alpha1StatusReportErrors {
return &CheckV0alpha1StatusReportErrors{}
}
// +k8s:openapi-gen=true // +k8s:openapi-gen=true
type CheckV0alpha1StatusReport struct { type CheckV0alpha1StatusReport struct {
// Number of elements analyzed // Number of elements analyzed
Count int64 `json:"count"` Count int64 `json:"count"`
// List of errors // List of errors
Errors []CheckV0alpha1StatusReportErrors `json:"errors"` Errors []CheckReportError `json:"errors"`
} }
// NewCheckV0alpha1StatusReport creates a new CheckV0alpha1StatusReport object. // NewCheckV0alpha1StatusReport creates a new CheckV0alpha1StatusReport object.
@@ -12,13 +12,13 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{ return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check": schema_pkg_apis_advisor_v0alpha1_Check(ref), "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check": schema_pkg_apis_advisor_v0alpha1_Check(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckList": schema_pkg_apis_advisor_v0alpha1_CheckList(ref), "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckList": schema_pkg_apis_advisor_v0alpha1_CheckList(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec": schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref), "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportError": schema_pkg_apis_advisor_v0alpha1_CheckReportError(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus": schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref), "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec": schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref), "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus": schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReportErrors": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReportErrors(ref), "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref),
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref), "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref),
} }
} }
@@ -117,6 +117,43 @@ func schema_pkg_apis_advisor_v0alpha1_CheckList(ref common.ReferenceCallback) co
} }
} }
func schema_pkg_apis_advisor_v0alpha1_CheckReportError(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"severity": {
SchemaProps: spec.SchemaProps{
Description: "Severity of the error",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"reason": {
SchemaProps: spec.SchemaProps{
Description: "Human readable reason for the error",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"action": {
SchemaProps: spec.SchemaProps{
Description: "Action to take to resolve the error",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"severity", "reason", "action"},
},
},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { func schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{ return common.OpenAPIDefinition{
Schema: spec.Schema{ Schema: spec.Schema{
@@ -218,7 +255,7 @@ func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref common.Refer
Schema: &spec.Schema{ Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{}, Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReportErrors"), Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportError"),
}, },
}, },
}, },
@@ -229,44 +266,7 @@ func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref common.Refer
}, },
}, },
Dependencies: []string{ Dependencies: []string{
"github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReportErrors"}, "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportError"},
}
}
func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReportErrors(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"severity": {
SchemaProps: spec.SchemaProps{
Description: "Severity of the error",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"reason": {
SchemaProps: spec.SchemaProps{
Description: "Human readable reason for the error",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"action": {
SchemaProps: spec.SchemaProps{
Description: "Action to take to resolve the error",
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"severity", "reason", "action"},
},
},
} }
} }
@@ -49,13 +49,13 @@ func (c *check) Run(ctx context.Context, obj *advisor.CheckSpec) (*advisor.Check
return nil, err return nil, err
} }
dsErrs := []advisor.CheckV0alpha1StatusReportErrors{} dsErrs := []advisor.CheckReportError{}
for _, ds := range dss { for _, ds := range dss {
// Data source UID validation // Data source UID validation
err := util.ValidateUID(ds.UID) err := util.ValidateUID(ds.UID)
if err != nil { if err != nil {
dsErrs = append(dsErrs, advisor.CheckV0alpha1StatusReportErrors{ dsErrs = append(dsErrs, advisor.CheckReportError{
Severity: advisor.CheckStatusSeverityLow, Severity: advisor.CheckReportErrorSeverityLow,
Reason: fmt.Sprintf("Invalid UID '%s' for data source %s", ds.UID, ds.Name), Reason: fmt.Sprintf("Invalid UID '%s' for data source %s", ds.UID, ds.Name),
Action: "Check the <a href='https://grafana.com/docs/grafana/latest/upgrade-guide/upgrade-v11.2/#grafana-data-source-uid-format-enforcement' target=_blank>documentation</a> for more information.", Action: "Check the <a href='https://grafana.com/docs/grafana/latest/upgrade-guide/upgrade-v11.2/#grafana-data-source-uid-format-enforcement' target=_blank>documentation</a> for more information.",
}) })
@@ -81,8 +81,8 @@ func (c *check) Run(ctx context.Context, obj *advisor.CheckSpec) (*advisor.Check
continue continue
} }
if resp.Status != backend.HealthStatusOk { if resp.Status != backend.HealthStatusOk {
dsErrs = append(dsErrs, advisor.CheckV0alpha1StatusReportErrors{ dsErrs = append(dsErrs, advisor.CheckReportError{
Severity: advisor.CheckStatusSeverityHigh, Severity: advisor.CheckReportErrorSeverityHigh,
Reason: fmt.Sprintf("Health check failed for %s", ds.Name), Reason: fmt.Sprintf("Health check failed for %s", ds.Name),
Action: fmt.Sprintf( Action: fmt.Sprintf(
"Go to the <a href='/connections/datasources/edit/%s'>data source configuration</a>"+ "Go to the <a href='/connections/datasources/edit/%s'>data source configuration</a>"+
@@ -43,7 +43,7 @@ func (c *check) Type() string {
func (c *check) Run(ctx context.Context, _ *advisor.CheckSpec) (*advisor.CheckV0alpha1StatusReport, error) { func (c *check) Run(ctx context.Context, _ *advisor.CheckSpec) (*advisor.CheckV0alpha1StatusReport, error) {
ps := c.PluginStore.Plugins(ctx) ps := c.PluginStore.Plugins(ctx)
errs := []advisor.CheckV0alpha1StatusReportErrors{} errs := []advisor.CheckReportError{}
for _, p := range ps { for _, p := range ps {
// Skip if it's a core plugin // Skip if it's a core plugin
if p.IsCorePlugin() { if p.IsCorePlugin() {
@@ -56,8 +56,8 @@ func (c *check) Run(ctx context.Context, _ *advisor.CheckSpec) (*advisor.CheckV0
continue continue
} }
if i.Status == "deprecated" { if i.Status == "deprecated" {
errs = append(errs, advisor.CheckV0alpha1StatusReportErrors{ errs = append(errs, advisor.CheckReportError{
Severity: advisor.CheckStatusSeverityHigh, Severity: advisor.CheckReportErrorSeverityHigh,
Reason: fmt.Sprintf("Plugin deprecated: %s", p.ID), Reason: fmt.Sprintf("Plugin deprecated: %s", p.ID),
Action: "Check the <a href='https://grafana.com/legal/plugin-deprecation/#a-plugin-i-use-is-deprecated-what-should-i-do' target=_blank>documentation</a> for recommended steps.", Action: "Check the <a href='https://grafana.com/legal/plugin-deprecation/#a-plugin-i-use-is-deprecated-what-should-i-do' target=_blank>documentation</a> for recommended steps.",
}) })
@@ -73,8 +73,8 @@ func (c *check) Run(ctx context.Context, _ *advisor.CheckSpec) (*advisor.CheckV0
continue continue
} }
if hasUpdate(p, info) { if hasUpdate(p, info) {
errs = append(errs, advisor.CheckV0alpha1StatusReportErrors{ errs = append(errs, advisor.CheckReportError{
Severity: advisor.CheckStatusSeverityLow, Severity: advisor.CheckReportErrorSeverityLow,
Reason: fmt.Sprintf("New version available for %s", p.ID), Reason: fmt.Sprintf("New version available for %s", p.ID),
Action: fmt.Sprintf( Action: fmt.Sprintf(
"Go to the <a href='/plugins/%s?page=version-history'>plugin admin page</a>"+ "Go to the <a href='/plugins/%s?page=version-history'>plugin admin page</a>"+
@@ -21,12 +21,12 @@ func TestRun(t *testing.T) {
pluginArchives map[string]*repo.PluginArchiveInfo pluginArchives map[string]*repo.PluginArchiveInfo
pluginPreinstalled []string pluginPreinstalled []string
pluginManaged []string pluginManaged []string
expectedErrors []advisor.CheckV0alpha1StatusReportErrors expectedErrors []advisor.CheckReportError
}{ }{
{ {
name: "No plugins", name: "No plugins",
plugins: []pluginstore.Plugin{}, plugins: []pluginstore.Plugin{},
expectedErrors: []advisor.CheckV0alpha1StatusReportErrors{}, expectedErrors: []advisor.CheckReportError{},
}, },
{ {
name: "Deprecated plugin", name: "Deprecated plugin",
@@ -39,9 +39,9 @@ func TestRun(t *testing.T) {
pluginArchives: map[string]*repo.PluginArchiveInfo{ pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin1": {Version: "1.0.0"}, "plugin1": {Version: "1.0.0"},
}, },
expectedErrors: []advisor.CheckV0alpha1StatusReportErrors{ expectedErrors: []advisor.CheckReportError{
{ {
Severity: advisor.CheckStatusSeverityHigh, Severity: advisor.CheckReportErrorSeverityHigh,
Reason: "Plugin deprecated: plugin1", Reason: "Plugin deprecated: plugin1",
Action: "Check the <a href='https://grafana.com/legal/plugin-deprecation/#a-plugin-i-use-is-deprecated-what-should-i-do' target=_blank>documentation</a> for recommended steps.", Action: "Check the <a href='https://grafana.com/legal/plugin-deprecation/#a-plugin-i-use-is-deprecated-what-should-i-do' target=_blank>documentation</a> for recommended steps.",
}, },
@@ -58,9 +58,9 @@ func TestRun(t *testing.T) {
pluginArchives: map[string]*repo.PluginArchiveInfo{ pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin2": {Version: "1.1.0"}, "plugin2": {Version: "1.1.0"},
}, },
expectedErrors: []advisor.CheckV0alpha1StatusReportErrors{ expectedErrors: []advisor.CheckReportError{
{ {
Severity: advisor.CheckStatusSeverityLow, Severity: advisor.CheckReportErrorSeverityLow,
Reason: "New version available for plugin2", Reason: "New version available for plugin2",
Action: "Go to the <a href='/plugins/plugin2?page=version-history'>plugin admin page</a> and upgrade to the latest version.", Action: "Go to the <a href='/plugins/plugin2?page=version-history'>plugin admin page</a> and upgrade to the latest version.",
}, },
@@ -77,9 +77,9 @@ func TestRun(t *testing.T) {
pluginArchives: map[string]*repo.PluginArchiveInfo{ pluginArchives: map[string]*repo.PluginArchiveInfo{
"plugin2": {Version: "beta"}, "plugin2": {Version: "beta"},
}, },
expectedErrors: []advisor.CheckV0alpha1StatusReportErrors{ expectedErrors: []advisor.CheckReportError{
{ {
Severity: advisor.CheckStatusSeverityLow, Severity: advisor.CheckReportErrorSeverityLow,
Reason: "New version available for plugin2", Reason: "New version available for plugin2",
Action: "Go to the <a href='/plugins/plugin2?page=version-history'>plugin admin page</a> and upgrade to the latest version.", Action: "Go to the <a href='/plugins/plugin2?page=version-history'>plugin admin page</a> and upgrade to the latest version.",
}, },
@@ -97,7 +97,7 @@ func TestRun(t *testing.T) {
"plugin3": {Version: "1.1.0"}, "plugin3": {Version: "1.1.0"},
}, },
pluginPreinstalled: []string{"plugin3"}, pluginPreinstalled: []string{"plugin3"},
expectedErrors: []advisor.CheckV0alpha1StatusReportErrors{}, expectedErrors: []advisor.CheckReportError{},
}, },
{ {
name: "Managed plugin", name: "Managed plugin",
@@ -111,7 +111,7 @@ func TestRun(t *testing.T) {
"plugin4": {Version: "1.1.0"}, "plugin4": {Version: "1.1.0"},
}, },
pluginManaged: []string{"plugin4"}, pluginManaged: []string{"plugin4"},
expectedErrors: []advisor.CheckV0alpha1StatusReportErrors{}, expectedErrors: []advisor.CheckReportError{},
}, },
} }
+7
View File
@@ -0,0 +1,7 @@
This folder contains the automatically generated types for the frontend that are used in the app plugin.
To update the types:
1. Make any necessary changes in the `kinds` directory
2. Run `make generate`
3. Copy the `plugin` directory to the frontend app: https://github.com/grafana/grafana-advisor-app/tree/main/src/plugin