diff --git a/pkg/registry/apis/datasource/sub_query.go b/pkg/registry/apis/datasource/sub_query.go index 6ab00ac5c78..51f8b90d430 100644 --- a/pkg/registry/apis/datasource/sub_query.go +++ b/pkg/registry/apis/datasource/sub_query.go @@ -2,6 +2,7 @@ package datasource import ( "context" + "errors" "fmt" "net/http" @@ -9,10 +10,14 @@ import ( data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1" query "github.com/grafana/grafana/pkg/apis/query/v0alpha1" query_headers "github.com/grafana/grafana/pkg/registry/apis/query" + "github.com/grafana/grafana/pkg/services/datasources" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/registry/rest" "github.com/grafana/grafana/pkg/web" + + k8serrors "k8s.io/apimachinery/pkg/api/errors" ) type subQueryREST struct { @@ -50,9 +55,21 @@ func (r *subQueryREST) NewConnectOptions() (runtime.Object, bool, string) { func (r *subQueryREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { pluginCtx, err := r.builder.getPluginContext(ctx, name) + if err != nil { + if errors.Is(err, datasources.ErrDataSourceNotFound) { + return nil, k8serrors.NewNotFound( + schema.GroupResource{ + Group: r.builder.connectionResourceInfo.GroupResource().Group, + Resource: r.builder.connectionResourceInfo.GroupResource().Resource, + }, + name, + ) + } + return nil, err } + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { dqr := data.QueryDataRequest{} err := web.Bind(req, &dqr) diff --git a/pkg/registry/apis/datasource/sub_query_test.go b/pkg/registry/apis/datasource/sub_query_test.go index 684f5f25cb1..6b3dc54b970 100644 --- a/pkg/registry/apis/datasource/sub_query_test.go +++ b/pkg/registry/apis/datasource/sub_query_test.go @@ -2,6 +2,7 @@ package datasource import ( "context" + "errors" "fmt" "net/http" "net/http/httptest" @@ -10,8 +11,10 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/apis/datasource/v0alpha1" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/stretchr/testify/require" + k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ) @@ -60,6 +63,26 @@ func TestSubQueryConnect(t *testing.T) { }, *sqr.builder.client.(mockClient).lastCalledWithHeaders) } +func TestSubQueryConnectWhenDatasourceNotFound(t *testing.T) { + sqr := subQueryREST{ + builder: &DataSourceAPIBuilder{ + client: mockClient{ + lastCalledWithHeaders: &map[string]string{}, + }, + datasources: mockDatasources{}, + contextProvider: mockContextProvider{}, + log: log.NewNopLogger(), + }, + } + + mr := mockResponder{} + _, err := sqr.Connect(context.Background(), "dsname-that-does-not-exist", nil, mr) + require.Error(t, err) + var statusErr *k8serrors.StatusError + require.True(t, errors.As(err, &statusErr)) + require.Equal(t, int32(404), statusErr.Status().Code) +} + type mockClient struct { lastCalledWithHeaders *map[string]string } @@ -108,7 +131,10 @@ func (m mockDatasources) List(ctx context.Context) (*v0alpha1.DataSourceConnecti // Return settings (decrypted!) for a specific plugin // This will require "query" permission for the user in context func (m mockDatasources) GetInstanceSettings(ctx context.Context, uid string) (*backend.DataSourceInstanceSettings, error) { - return nil, nil + if uid == "dsname" { + return nil, nil + } + return nil, datasources.ErrDataSourceNotFound } type mockContextProvider struct {