ds-querier: return QDR instead of k8s error (#95184)

* ds-querier: return QDR instead of k8s error

After parseQuery we know the request is a valid k8s request but we don't
know if the query is valid, therefore this change returns a QDR that
other systems, e.g. alerting ruler, can de-serialize properly.

Co-authored-by: Gábor Farkas <gabor.farkas@gmail.com>

* ds-querier: fix tests

Co-authored-by: Sarah Zinger <sarah.zinger@grafana.com>

* tweak status

* refactor refID to empty

---------

Co-authored-by: Gábor Farkas <gabor.farkas@gmail.com>
Co-authored-by: Sarah Zinger <sarah.zinger@grafana.com>
This commit is contained in:
Adam Simpson 2024-10-23 09:58:22 -04:00 committed by GitHub
parent 008c51b5b1
commit 61b9ffd324
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 23 deletions

View File

@ -77,3 +77,20 @@ func makeCyclicError(refID string) error {
}
return cyclicErr.Build(data)
}
type ErrorWithRefID struct {
err error
refId string
}
func (ewr ErrorWithRefID) Error() string {
return ewr.err.Error()
}
func NewErrorWithRefID(refId string, err error) error {
ewr := ErrorWithRefID{
err: err,
refId: refId,
}
return ewr
}

View File

@ -101,7 +101,7 @@ func (p *queryParser) parseRequest(ctx context.Context, input *query.QueryDataRe
}
exp, err := p.reader.ReadQuery(q, iter)
if err != nil {
return rsp, err
return rsp, NewErrorWithRefID(q.RefID, err)
}
exp.GraphID = int64(len(expressions) + 1)
expressions[q.RefID] = &exp

View File

@ -10,12 +10,12 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"golang.org/x/sync/errgroup"
errorsK8s "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/endpoints/request"
@ -24,7 +24,6 @@ import (
query "github.com/grafana/grafana/pkg/apis/query/v0alpha1"
"github.com/grafana/grafana/pkg/expr/mathexp"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/web"
)
@ -122,23 +121,32 @@ func (r *queryREST) Connect(connectCtx context.Context, name string, _ runtime.O
// Parses the request and splits it into multiple sub queries (if necessary)
req, err := b.parser.parseRequest(ctx, raw)
if err != nil {
reason := metav1.StatusReasonInvalid
message := err.Error()
var refError ErrorWithRefID
statusCode := http.StatusBadRequest
message := err
refID := ""
if errors.Is(err, datasources.ErrDataSourceNotFound) {
reason = metav1.StatusReasonNotFound
// TODO, can we wrap the error somehow?
message = "datasource not found"
statusCode = http.StatusNotFound
message = errors.New("datasource not found")
}
err = &errorsK8s.StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusBadRequest,
Reason: reason,
Message: message,
}}
if errors.As(err, &refError) {
refID = refError.refId
}
responder.Error(err)
qdr := &query.QueryDataResponse{
QueryDataResponse: backend.QueryDataResponse{
Responses: backend.Responses{
refID: {
Error: message,
Status: backend.Status(statusCode),
},
},
},
}
responder.Object(statusCode, qdr)
return
}

View File

@ -139,14 +139,14 @@ func TestIntegrationSimpleQuery(t *testing.T) {
require.Error(t, err, "expecting a 400")
require.JSONEq(t, `{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "[sse.dependencyError] did not execute expression [Y] due to a failure to of the dependent expression or query [X]",
"reason": "Invalid",
"code": 400
}`, string(body))
"results": {
"": {
"error": "[sse.dependencyError] did not execute expression [Y] due to a failure to of the dependent expression or query [X]",
"status": 400,
"errorSource": ""
}
}
}`, string(body))
// require.JSONEq(t, `{
// "status": "Failure",
// "metadata": {},