Advisor: Redefine check properties (#100874)
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
type check struct {
|
||||
@@ -72,7 +73,12 @@ func (s *uidValidationStep) Title() string {
|
||||
}
|
||||
|
||||
func (s *uidValidationStep) Description() string {
|
||||
return "Check if the UID of each data source is valid."
|
||||
return "Checks if the UID of a data source is valid."
|
||||
}
|
||||
|
||||
func (s *uidValidationStep) Resolution() string {
|
||||
return "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 or delete the data source and create a new one."
|
||||
}
|
||||
|
||||
func (s *uidValidationStep) Run(ctx context.Context, obj *advisor.CheckSpec, i any) (*advisor.CheckReportFailure, error) {
|
||||
@@ -85,10 +91,9 @@ func (s *uidValidationStep) Run(ctx context.Context, obj *advisor.CheckSpec, i a
|
||||
if err != nil {
|
||||
return checks.NewCheckReportFailure(
|
||||
advisor.CheckReportFailureSeverityLow,
|
||||
fmt.Sprintf("Invalid UID '%s' for data source %s", ds.UID, ds.Name),
|
||||
"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.",
|
||||
s.ID(),
|
||||
ds.UID,
|
||||
fmt.Sprintf("%s (%s)", ds.Name, ds.UID),
|
||||
[]advisor.CheckErrorLink{},
|
||||
), nil
|
||||
}
|
||||
return nil, nil
|
||||
@@ -104,7 +109,11 @@ func (s *healthCheckStep) Title() string {
|
||||
}
|
||||
|
||||
func (s *healthCheckStep) Description() string {
|
||||
return "Check if all data sources are healthy."
|
||||
return "Checks if a data sources is healthy."
|
||||
}
|
||||
|
||||
func (s *healthCheckStep) Resolution() string {
|
||||
return "Go to the data source configuration page and address the issues reported."
|
||||
}
|
||||
|
||||
func (s *healthCheckStep) ID() string {
|
||||
@@ -124,7 +133,9 @@ func (s *healthCheckStep) Run(ctx context.Context, obj *advisor.CheckSpec, i any
|
||||
}
|
||||
pCtx, err := s.PluginContextProvider.GetWithDataSource(ctx, ds.Type, requester, ds)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get plugin context: %w", err)
|
||||
// Unable to check health check
|
||||
klog.Error("Failed to get plugin context", "datasource_uid", ds.UID, "error", err)
|
||||
return nil, nil
|
||||
}
|
||||
req := &backend.CheckHealthRequest{
|
||||
PluginContext: pCtx,
|
||||
@@ -134,12 +145,14 @@ func (s *healthCheckStep) Run(ctx context.Context, obj *advisor.CheckSpec, i any
|
||||
if err != nil || resp.Status != backend.HealthStatusOk {
|
||||
return checks.NewCheckReportFailure(
|
||||
advisor.CheckReportFailureSeverityHigh,
|
||||
fmt.Sprintf("Health check failed for %s", ds.Name),
|
||||
fmt.Sprintf(
|
||||
"Go to the <a href='/connections/datasources/edit/%s'>data source configuration</a>"+
|
||||
" and address the issues reported.", ds.UID),
|
||||
s.ID(),
|
||||
ds.UID,
|
||||
ds.Name,
|
||||
[]advisor.CheckErrorLink{
|
||||
{
|
||||
Message: "Fix me",
|
||||
Url: fmt.Sprintf("/connections/datasources/edit/%s", ds.UID),
|
||||
},
|
||||
},
|
||||
), nil
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestCheck_Run(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(items))
|
||||
assert.Len(t, failures, 1)
|
||||
assert.Equal(t, "Invalid UID 'invalid uid' for data source Prometheus", failures[0].Reason)
|
||||
assert.Equal(t, "uid-validation", failures[0].StepID)
|
||||
})
|
||||
|
||||
t.Run("should return failures when datasource health check fails", func(t *testing.T) {
|
||||
@@ -116,7 +116,7 @@ func TestCheck_Run(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(items))
|
||||
assert.Len(t, failures, 1)
|
||||
assert.Equal(t, "Health check failed for Prometheus", failures[0].Reason)
|
||||
assert.Equal(t, "health-check", failures[0].StepID)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ type Step interface {
|
||||
Title() string
|
||||
// Description returns the description of the step
|
||||
Description() string
|
||||
// Explains the action that needs to be taken to resolve the issue
|
||||
Resolution() string
|
||||
// Run executes the step for an item and returns a report
|
||||
Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, item any) (*advisorv0alpha1.CheckReportFailure, error)
|
||||
}
|
||||
|
||||
@@ -74,6 +74,11 @@ func (s *deprecationStep) Description() string {
|
||||
return "Check if any installed plugins are deprecated."
|
||||
}
|
||||
|
||||
func (s *deprecationStep) Resolution() string {
|
||||
return "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 or delete the plugin."
|
||||
}
|
||||
|
||||
func (s *deprecationStep) ID() string {
|
||||
return "deprecation"
|
||||
}
|
||||
@@ -98,10 +103,14 @@ func (s *deprecationStep) Run(ctx context.Context, _ *advisor.CheckSpec, it any)
|
||||
if i.Status == "deprecated" {
|
||||
return checks.NewCheckReportFailure(
|
||||
advisor.CheckReportFailureSeverityHigh,
|
||||
fmt.Sprintf("Plugin deprecated: %s", p.ID),
|
||||
"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.",
|
||||
s.ID(),
|
||||
p.ID,
|
||||
[]advisor.CheckErrorLink{
|
||||
{
|
||||
Message: "Admin",
|
||||
Url: fmt.Sprintf("/plugins/%s", p.ID),
|
||||
},
|
||||
},
|
||||
), nil
|
||||
}
|
||||
return nil, nil
|
||||
@@ -118,7 +127,11 @@ func (s *updateStep) Title() string {
|
||||
}
|
||||
|
||||
func (s *updateStep) Description() string {
|
||||
return "Check if any installed plugins have a newer version available."
|
||||
return "Checks if an installed plugins has a newer version available."
|
||||
}
|
||||
|
||||
func (s *updateStep) Resolution() string {
|
||||
return "Go to the plugin admin page and upgrade to the latest version."
|
||||
}
|
||||
|
||||
func (s *updateStep) ID() string {
|
||||
@@ -151,12 +164,14 @@ func (s *updateStep) Run(ctx context.Context, _ *advisor.CheckSpec, i any) (*adv
|
||||
if hasUpdate(p, info) {
|
||||
return checks.NewCheckReportFailure(
|
||||
advisor.CheckReportFailureSeverityLow,
|
||||
fmt.Sprintf("New version available for %s", p.ID),
|
||||
fmt.Sprintf(
|
||||
"Go to the <a href='/plugins/%s?page=version-history'>plugin admin page</a>"+
|
||||
" and upgrade to the latest version.", p.ID),
|
||||
s.ID(),
|
||||
p.ID,
|
||||
[]advisor.CheckErrorLink{
|
||||
{
|
||||
Message: "Upgrade",
|
||||
Url: fmt.Sprintf("/plugins/%s?page=version-history", p.ID),
|
||||
},
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -42,10 +42,14 @@ func TestRun(t *testing.T) {
|
||||
expectedFailures: []advisor.CheckReportFailure{
|
||||
{
|
||||
Severity: advisor.CheckReportFailureSeverityHigh,
|
||||
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.",
|
||||
StepID: "deprecation",
|
||||
ItemID: "plugin1",
|
||||
Item: "plugin1",
|
||||
Links: []advisor.CheckErrorLink{
|
||||
{
|
||||
Url: "/plugins/plugin1",
|
||||
Message: "Admin",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -63,10 +67,14 @@ func TestRun(t *testing.T) {
|
||||
expectedFailures: []advisor.CheckReportFailure{
|
||||
{
|
||||
Severity: advisor.CheckReportFailureSeverityLow,
|
||||
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.",
|
||||
StepID: "update",
|
||||
ItemID: "plugin2",
|
||||
Item: "plugin2",
|
||||
Links: []advisor.CheckErrorLink{
|
||||
{
|
||||
Url: "/plugins/plugin2?page=version-history",
|
||||
Message: "Upgrade",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -84,10 +92,14 @@ func TestRun(t *testing.T) {
|
||||
expectedFailures: []advisor.CheckReportFailure{
|
||||
{
|
||||
Severity: advisor.CheckReportFailureSeverityLow,
|
||||
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.",
|
||||
StepID: "update",
|
||||
ItemID: "plugin2",
|
||||
Item: "plugin2",
|
||||
Links: []advisor.CheckErrorLink{
|
||||
{
|
||||
Url: "/plugins/plugin2?page=version-history",
|
||||
Message: "Upgrade",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -11,16 +11,14 @@ const (
|
||||
|
||||
func NewCheckReportFailure(
|
||||
severity advisor.CheckReportFailureSeverity,
|
||||
reason string,
|
||||
action string,
|
||||
stepID string,
|
||||
itemID string,
|
||||
item string,
|
||||
links []advisor.CheckErrorLink,
|
||||
) *advisor.CheckReportFailure {
|
||||
return &advisor.CheckReportFailure{
|
||||
Severity: severity,
|
||||
Reason: reason,
|
||||
Action: action,
|
||||
StepID: stepID,
|
||||
ItemID: itemID,
|
||||
Item: item,
|
||||
Links: links,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ func (r *Runner) Run(ctx context.Context) error {
|
||||
Title: s.Title(),
|
||||
Description: s.Description(),
|
||||
StepID: s.ID(),
|
||||
Resolution: s.Resolution(),
|
||||
}
|
||||
}
|
||||
obj := &advisorv0alpha1.CheckType{
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/advisor/pkg/app/checks"
|
||||
k8sErrs "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@@ -134,8 +135,6 @@ func (m *mockCheck) Steps() []checks.Step {
|
||||
}
|
||||
|
||||
type mockStep struct {
|
||||
checks.Step
|
||||
|
||||
id string
|
||||
title string
|
||||
description string
|
||||
@@ -153,6 +152,14 @@ func (m *mockStep) Description() string {
|
||||
return m.description
|
||||
}
|
||||
|
||||
func (m *mockStep) Resolution() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *mockStep) Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, item any) (*advisorv0alpha1.CheckReportFailure, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type mockClient struct {
|
||||
resource.Client
|
||||
|
||||
|
||||
@@ -191,6 +191,10 @@ func (m *mockStep) Description() string {
|
||||
return "mock"
|
||||
}
|
||||
|
||||
func (m *mockStep) Resolution() string {
|
||||
return "mock"
|
||||
}
|
||||
|
||||
func (m *mockStep) ID() string {
|
||||
return "mock"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user