diff --git a/apps/advisor/pkg/app/checks/datasourcecheck/check.go b/apps/advisor/pkg/app/checks/datasourcecheck/check.go index 0cdac81e4b8..0fc42d1bfbd 100644 --- a/apps/advisor/pkg/app/checks/datasourcecheck/check.go +++ b/apps/advisor/pkg/app/checks/datasourcecheck/check.go @@ -138,6 +138,24 @@ 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 { + if errors.Is(err, plugins.ErrPluginNotRegistered) { + // The plugin is not installed + return checks.NewCheckReportFailure( + advisor.CheckReportFailureSeverityHigh, + s.ID(), + ds.Name, + []advisor.CheckErrorLink{ + { + Message: "Delete data source", + Url: fmt.Sprintf("/connections/datasources/edit/%s", ds.UID), + }, + { + Message: "Install plugin", + Url: fmt.Sprintf("/plugins/%s", ds.Type), + }, + }, + ), nil + } // Unable to check health check s.log.Error("Failed to get plugin context", "datasource_uid", ds.UID, "error", err) return nil, nil diff --git a/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go b/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go index ee8a991555d..09a7487bd8b 100644 --- a/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go +++ b/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go @@ -156,6 +156,41 @@ func TestCheck_Run(t *testing.T) { assert.Equal(t, 1, len(items)) assert.Len(t, failures, 0) }) + + t.Run("should return failure when plugin is not installed", func(t *testing.T) { + datasources := []*datasources.DataSource{ + {UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus"}, + } + mockDatasourceSvc := &MockDatasourceSvc{dss: datasources} + mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}} + mockPluginClient := &MockPluginClient{err: plugins.ErrPluginNotRegistered} + + check := &check{ + DatasourceSvc: mockDatasourceSvc, + PluginContextProvider: mockPluginContextProvider, + PluginClient: mockPluginClient, + log: log.New("advisor.datasourcecheck"), + } + + ctx := identity.WithRequester(context.Background(), &user.SignedInUser{}) + items, err := check.Items(ctx) + assert.NoError(t, err) + failures := []advisor.CheckReportFailure{} + for _, step := range check.Steps() { + for _, item := range items { + stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item) + assert.NoError(t, err) + if stepFailures != nil { + failures = append(failures, *stepFailures) + } + } + } + + assert.NoError(t, err) + assert.Equal(t, 1, len(items)) + assert.Len(t, failures, 1) + assert.Equal(t, "health-check", failures[0].StepID) + }) } type MockDatasourceSvc struct {