mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
008c51b5b1
commit
61b9ffd324
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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": {},
|
||||
|
Loading…
Reference in New Issue
Block a user