Merge remote-tracking branch 'origin/main' into ds-apiserver-with-configs
This commit is contained in:
@@ -74,7 +74,7 @@ func (hs *HTTPServer) SetHomeDashboard(c *contextmodel.ReqContext) response.Resp
|
||||
func (hs *HTTPServer) GetUserPreferences(c *contextmodel.ReqContext) response.Response {
|
||||
userID, err := identity.UserIdentifier(c.GetID())
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to update user preferences", err)
|
||||
return response.Error(http.StatusUnauthorized, "Not a valid identity", err)
|
||||
}
|
||||
|
||||
return prefapi.GetPreferencesFor(c.Req.Context(), hs.DashboardService, hs.preferenceService, hs.Features, c.GetOrgID(), userID, 0)
|
||||
|
||||
+1
-53
@@ -9,88 +9,36 @@ require (
|
||||
google.golang.org/protobuf v1.36.6
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/apimachinery v0.33.2
|
||||
k8s.io/apiserver v0.33.2
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
|
||||
github.com/jonboulle/clockwork v0.5.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.22.2 // indirect
|
||||
github.com/onsi/gomega v1.36.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.64.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.etcd.io/bbolt v1.4.0 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.21 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.21 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.34.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/api v0.33.2 // indirect
|
||||
k8s.io/client-go v0.33.2 // indirect
|
||||
k8s.io/component-base v0.33.2 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
|
||||
|
||||
@@ -1,41 +1,11 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
|
||||
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
@@ -46,156 +16,58 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
|
||||
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
|
||||
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
|
||||
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
||||
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
|
||||
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
|
||||
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=
|
||||
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||
go.etcd.io/etcd/api/v3 v3.5.21 h1:A6O2/JDb3tvHhiIz3xf9nJ7REHvtEFJJ3veW3FbCnS8=
|
||||
go.etcd.io/etcd/api/v3 v3.5.21/go.mod h1:c3aH5wcvXv/9dqIw2Y810LDXJfhSYdHQ0vxmP3CCHVY=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.21 h1:lPBu71Y7osQmzlflM9OfeIV2JlmpBjqBNlLtcoBqUTc=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.21/go.mod h1:BgqT/IXPjK9NkeSDjbzwsHySX3yIle2+ndz28nVsjUs=
|
||||
go.etcd.io/etcd/client/v2 v2.305.21 h1:eLiFfexc2mE+pTLz9WwnoEsX5JTTpLCYVivKkmVXIRA=
|
||||
go.etcd.io/etcd/client/v2 v2.305.21/go.mod h1:OKkn4hlYNf43hpjEM3Ke3aRdUkhSl8xjKjSf8eCq2J8=
|
||||
go.etcd.io/etcd/client/v3 v3.5.21 h1:T6b1Ow6fNjOLOtM0xSoKNQt1ASPCLWrF9XMHcH9pEyY=
|
||||
go.etcd.io/etcd/client/v3 v3.5.21/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU=
|
||||
go.etcd.io/etcd/pkg/v3 v3.5.21 h1:jUItxeKyrDuVuWhdh0HtjUANwyuzcb7/FAeUfABmQsk=
|
||||
go.etcd.io/etcd/pkg/v3 v3.5.21/go.mod h1:wpZx8Egv1g4y+N7JAsqi2zoUiBIUWznLjqJbylDjWgU=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.21 h1:dOmE0mT55dIUsX77TKBLq+RgyumsQuYeiRQnW/ylugk=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.21/go.mod h1:fmcuY5R2SNkklU4+fKVBQi2biVp5vafMrWUEj4TJ4Cs=
|
||||
go.etcd.io/etcd/server/v3 v3.5.21 h1:9w0/k12majtgarGmlMVuhwXRI2ob3/d1Ik3X5TKo0yU=
|
||||
go.etcd.io/etcd/server/v3 v3.5.21/go.mod h1:G1mOzdwuzKT1VRL7SqRchli/qcFrtLBTAQ4lV20sXXo=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c=
|
||||
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||
@@ -204,139 +76,58 @@ go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFw
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||
go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI=
|
||||
go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
|
||||
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
|
||||
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
|
||||
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/apiserver v0.33.2 h1:KGTRbxn2wJagJowo29kKBp4TchpO1DRO3g+dB/KOJN4=
|
||||
k8s.io/apiserver v0.33.2/go.mod h1:9qday04wEAMLPWWo9AwqCZSiIn3OYSZacDyu/AcoM/M=
|
||||
k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
|
||||
k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
|
||||
k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0=
|
||||
k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
|
||||
@@ -4,10 +4,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
)
|
||||
@@ -33,7 +31,6 @@ var SecureValuesResourceInfo = utils.NewResourceInfo(
|
||||
{Name: "Description", Type: "string", Format: "string", Description: "Short description that explains the purpose of this SecureValue"},
|
||||
{Name: "Keeper", Type: "string", Format: "string", Description: "Storage of the secure value"},
|
||||
{Name: "Ref", Type: "string", Format: "string", Description: "If present, the reference to a secret"},
|
||||
{Name: "Status", Type: "string", Format: "string", Description: "The status of the secure value"},
|
||||
},
|
||||
// Decodes the object into a concrete type. Return order in the slice must be the same as in `Definition`.
|
||||
Reader: func(obj any) ([]interface{}, error) {
|
||||
@@ -44,7 +41,6 @@ var SecureValuesResourceInfo = utils.NewResourceInfo(
|
||||
r.Spec.Description,
|
||||
r.Spec.Keeper,
|
||||
r.Spec.Ref,
|
||||
r.Status.Phase,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -92,13 +88,6 @@ var (
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Adds the status phase to the selectable fields, besides the generic metadata name and namespace.
|
||||
func SelectableSecureValueFields(obj *SecureValue) fields.Set {
|
||||
return generic.MergeFieldsSets(generic.ObjectMetaFieldsSet(&obj.ObjectMeta, false), fields.Set{
|
||||
"status.phase": string(obj.Status.Phase),
|
||||
})
|
||||
}
|
||||
|
||||
// Adds the list of known types to the given scheme.
|
||||
func AddKnownTypes(scheme *runtime.Scheme, version string) error {
|
||||
// TODO: do we need a type for the secure value decrypt?
|
||||
@@ -112,20 +101,5 @@ func AddKnownTypes(scheme *runtime.Scheme, version string) error {
|
||||
// &secretV0.SecureValueActivityList{},
|
||||
)
|
||||
|
||||
err := scheme.AddFieldLabelConversionFunc(
|
||||
SecureValuesResourceInfo.GroupVersionKind(),
|
||||
func(label, value string) (string, string, error) {
|
||||
fieldSet := SelectableSecureValueFields(&SecureValue{})
|
||||
for key := range fieldSet {
|
||||
if label == key {
|
||||
return label, value, nil
|
||||
}
|
||||
}
|
||||
return "", "", fmt.Errorf("field label not supported for %s: %s", SecureValuesResourceInfo.GroupVersionKind(), label)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,41 +11,18 @@ type SecureValue struct {
|
||||
// Standard object's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
// This is the actual secure value schema.
|
||||
Spec SecureValueSpec `json:"spec"`
|
||||
|
||||
// Read-only observed status of the `SecureValue`.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
|
||||
Status SecureValueStatus `json:"status,omitempty"`
|
||||
Status SecureValueStatus `json:"status"`
|
||||
}
|
||||
|
||||
// +enum
|
||||
type SecureValuePhase string
|
||||
|
||||
const (
|
||||
// When the `SecureValue` is created, it will start in `Pending` phase to create the underlying secret asynchronously.
|
||||
SecureValuePhasePending SecureValuePhase = "Pending"
|
||||
|
||||
// If the creation of the secret is successful, it will move to the `Succeeded` phase.
|
||||
SecureValuePhaseSucceeded SecureValuePhase = "Succeeded"
|
||||
|
||||
// If the creation of the secret fails, it will move to the `Failed` phase.
|
||||
// Check the additional `status` fields for more information on what caused the failure.
|
||||
// This state is unrecoverable.
|
||||
SecureValuePhaseFailed SecureValuePhase = "Failed"
|
||||
)
|
||||
|
||||
type SecureValueStatus struct {
|
||||
// High-level summary of where the `SecureValue` is in its lifecycle.
|
||||
// One of: `Pending`, `Succeeded` or `Failed`.
|
||||
Phase SecureValuePhase `json:"phase"`
|
||||
|
||||
// A human readable message indicating details about why the `SecureValue` is in this phase.
|
||||
// Only applicable if the `phase=Failed`.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty"`
|
||||
Version int64 `json:"version"`
|
||||
|
||||
// +optional
|
||||
ExternalID string `json:"externalId,omitempty"`
|
||||
@@ -94,7 +71,7 @@ type SecureValueList struct {
|
||||
// Standard list's metadata. It can only be one of `metav1.ObjectMeta` or `metav1.ListMeta`.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
// Slice containing all secure values. This will NOT output decrypted values.
|
||||
Items []SecureValue `json:"items"`
|
||||
|
||||
@@ -598,7 +598,7 @@ func schema_pkg_apis_secret_v0alpha1_SecureValue(ref common.ReferenceCallback) c
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"spec"},
|
||||
Required: []string{"spec", "status"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
@@ -734,20 +734,11 @@ func schema_pkg_apis_secret_v0alpha1_SecureValueStatus(ref common.ReferenceCallb
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"phase": {
|
||||
"version": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "High-level summary of where the `SecureValue` is in its lifecycle. One of: `Pending`, `Succeeded` or `Failed`.\n\nPossible enum values:\n - `\"Failed\"` If the creation of the secret fails, it will move to the `Failed` phase. Check the additional `status` fields for more information on what caused the failure. This state is unrecoverable.\n - `\"Pending\"` When the `SecureValue` is created, it will start in `Pending` phase to create the underlying secret asynchronously.\n - `\"Succeeded\"` If the creation of the secret is successful, it will move to the `Succeeded` phase.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"Failed", "Pending", "Succeeded"},
|
||||
},
|
||||
},
|
||||
"message": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A human readable message indicating details about why the `SecureValue` is in this phase. Only applicable if the `phase=Failed`.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Default: 0,
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
},
|
||||
"externalId": {
|
||||
@@ -757,7 +748,7 @@ func schema_pkg_apis_secret_v0alpha1_SecureValueStatus(ref common.ReferenceCallb
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"phase"},
|
||||
Required: []string{"version"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -6,3 +6,4 @@ API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alp
|
||||
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,KeeperSpec,Azure
|
||||
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,KeeperSpec,HashiCorp
|
||||
API rule violation: names_match,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,SecureValueStatus,ExternalID
|
||||
API rule violation: streaming_list_type_json_tags,github.com/grafana/grafana/pkg/apis/secret/v0alpha1,SecureValueList,ListMeta
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.10.6. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package filestorage
|
||||
|
||||
@@ -17,6 +17,10 @@ type MockFileStorage struct {
|
||||
func (_m *MockFileStorage) CreateFolder(ctx context.Context, path string) error {
|
||||
ret := _m.Called(ctx, path)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateFolder")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, path)
|
||||
@@ -31,6 +35,10 @@ func (_m *MockFileStorage) CreateFolder(ctx context.Context, path string) error
|
||||
func (_m *MockFileStorage) Delete(ctx context.Context, path string) error {
|
||||
ret := _m.Called(ctx, path)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Delete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, path)
|
||||
@@ -45,6 +53,10 @@ func (_m *MockFileStorage) Delete(ctx context.Context, path string) error {
|
||||
func (_m *MockFileStorage) DeleteFolder(ctx context.Context, path string, options *DeleteFolderOptions) error {
|
||||
ret := _m.Called(ctx, path, options)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteFolder")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *DeleteFolderOptions) error); ok {
|
||||
r0 = rf(ctx, path, options)
|
||||
@@ -59,7 +71,16 @@ func (_m *MockFileStorage) DeleteFolder(ctx context.Context, path string, option
|
||||
func (_m *MockFileStorage) Get(ctx context.Context, path string, options *GetFileOptions) (*File, bool, error) {
|
||||
ret := _m.Called(ctx, path, options)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Get")
|
||||
}
|
||||
|
||||
var r0 *File
|
||||
var r1 bool
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *GetFileOptions) (*File, bool, error)); ok {
|
||||
return rf(ctx, path, options)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *GetFileOptions) *File); ok {
|
||||
r0 = rf(ctx, path, options)
|
||||
} else {
|
||||
@@ -68,14 +89,12 @@ func (_m *MockFileStorage) Get(ctx context.Context, path string, options *GetFil
|
||||
}
|
||||
}
|
||||
|
||||
var r1 bool
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, *GetFileOptions) bool); ok {
|
||||
r1 = rf(ctx, path, options)
|
||||
} else {
|
||||
r1 = ret.Get(1).(bool)
|
||||
}
|
||||
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(2).(func(context.Context, string, *GetFileOptions) error); ok {
|
||||
r2 = rf(ctx, path, options)
|
||||
} else {
|
||||
@@ -89,7 +108,15 @@ func (_m *MockFileStorage) Get(ctx context.Context, path string, options *GetFil
|
||||
func (_m *MockFileStorage) List(ctx context.Context, folderPath string, paging *Paging, options *ListOptions) (*ListResponse, error) {
|
||||
ret := _m.Called(ctx, folderPath, paging, options)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for List")
|
||||
}
|
||||
|
||||
var r0 *ListResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *Paging, *ListOptions) (*ListResponse, error)); ok {
|
||||
return rf(ctx, folderPath, paging, options)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *Paging, *ListOptions) *ListResponse); ok {
|
||||
r0 = rf(ctx, folderPath, paging, options)
|
||||
} else {
|
||||
@@ -98,7 +125,6 @@ func (_m *MockFileStorage) List(ctx context.Context, folderPath string, paging *
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, *Paging, *ListOptions) error); ok {
|
||||
r1 = rf(ctx, folderPath, paging, options)
|
||||
} else {
|
||||
@@ -112,6 +138,10 @@ func (_m *MockFileStorage) List(ctx context.Context, folderPath string, paging *
|
||||
func (_m *MockFileStorage) Upsert(ctx context.Context, command *UpsertFileCommand) error {
|
||||
ret := _m.Called(ctx, command)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Upsert")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *UpsertFileCommand) error); ok {
|
||||
r0 = rf(ctx, command)
|
||||
@@ -122,10 +152,14 @@ func (_m *MockFileStorage) Upsert(ctx context.Context, command *UpsertFileComman
|
||||
return r0
|
||||
}
|
||||
|
||||
// close provides a mock function with given fields:
|
||||
// close provides a mock function with no fields
|
||||
func (_m *MockFileStorage) close() error {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for close")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
@@ -135,3 +169,17 @@ func (_m *MockFileStorage) close() error {
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// NewMockFileStorage creates a new instance of MockFileStorage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockFileStorage(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockFileStorage {
|
||||
mock := &MockFileStorage{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestIntegrationSocialService_ProvideService(t *testing.T) {
|
||||
expectedGenericOAuthSkipOrgRoleSync bool
|
||||
}{
|
||||
{
|
||||
name: "should load all social connectors when ssoSettingsApi is enabled",
|
||||
name: "should load all social connectors",
|
||||
expectedSocialMapLength: 7,
|
||||
expectedGenericOAuthSkipOrgRoleSync: false,
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.27.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package socialtest
|
||||
|
||||
@@ -31,6 +31,10 @@ func (_m *MockSocialConnector) AuthCodeURL(state string, opts ...oauth2.AuthCode
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for AuthCodeURL")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(string, ...oauth2.AuthCodeOption) string); ok {
|
||||
r0 = rf(state, opts...)
|
||||
@@ -45,6 +49,10 @@ func (_m *MockSocialConnector) AuthCodeURL(state string, opts ...oauth2.AuthCode
|
||||
func (_m *MockSocialConnector) Client(ctx context.Context, t *oauth2.Token) *http.Client {
|
||||
ret := _m.Called(ctx, t)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Client")
|
||||
}
|
||||
|
||||
var r0 *http.Client
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *oauth2.Token) *http.Client); ok {
|
||||
r0 = rf(ctx, t)
|
||||
@@ -68,6 +76,10 @@ func (_m *MockSocialConnector) Exchange(ctx context.Context, code string, authOp
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Exchange")
|
||||
}
|
||||
|
||||
var r0 *oauth2.Token
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...oauth2.AuthCodeOption) (*oauth2.Token, error)); ok {
|
||||
@@ -90,10 +102,14 @@ func (_m *MockSocialConnector) Exchange(ctx context.Context, code string, authOp
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetOAuthInfo provides a mock function with given fields:
|
||||
// GetOAuthInfo provides a mock function with no fields
|
||||
func (_m *MockSocialConnector) GetOAuthInfo() *social.OAuthInfo {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetOAuthInfo")
|
||||
}
|
||||
|
||||
var r0 *social.OAuthInfo
|
||||
if rf, ok := ret.Get(0).(func() *social.OAuthInfo); ok {
|
||||
r0 = rf()
|
||||
@@ -110,6 +126,10 @@ func (_m *MockSocialConnector) GetOAuthInfo() *social.OAuthInfo {
|
||||
func (_m *MockSocialConnector) IsEmailAllowed(email string) bool {
|
||||
ret := _m.Called(email)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for IsEmailAllowed")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||
r0 = rf(email)
|
||||
@@ -120,10 +140,14 @@ func (_m *MockSocialConnector) IsEmailAllowed(email string) bool {
|
||||
return r0
|
||||
}
|
||||
|
||||
// IsSignupAllowed provides a mock function with given fields:
|
||||
// IsSignupAllowed provides a mock function with no fields
|
||||
func (_m *MockSocialConnector) IsSignupAllowed() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for IsSignupAllowed")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||
r0 = rf()
|
||||
@@ -138,6 +162,10 @@ func (_m *MockSocialConnector) IsSignupAllowed() bool {
|
||||
func (_m *MockSocialConnector) SupportBundleContent(_a0 *bytes.Buffer) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SupportBundleContent")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*bytes.Buffer) error); ok {
|
||||
r0 = rf(_a0)
|
||||
@@ -152,6 +180,10 @@ func (_m *MockSocialConnector) SupportBundleContent(_a0 *bytes.Buffer) error {
|
||||
func (_m *MockSocialConnector) TokenSource(ctx context.Context, t *oauth2.Token) oauth2.TokenSource {
|
||||
ret := _m.Called(ctx, t)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for TokenSource")
|
||||
}
|
||||
|
||||
var r0 oauth2.TokenSource
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *oauth2.Token) oauth2.TokenSource); ok {
|
||||
r0 = rf(ctx, t)
|
||||
@@ -168,6 +200,10 @@ func (_m *MockSocialConnector) TokenSource(ctx context.Context, t *oauth2.Token)
|
||||
func (_m *MockSocialConnector) UserInfo(ctx context.Context, client *http.Client, token *oauth2.Token) (*social.BasicUserInfo, error) {
|
||||
ret := _m.Called(ctx, client, token)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UserInfo")
|
||||
}
|
||||
|
||||
var r0 *social.BasicUserInfo
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *http.Client, *oauth2.Token) (*social.BasicUserInfo, error)); ok {
|
||||
@@ -190,13 +226,12 @@ func (_m *MockSocialConnector) UserInfo(ctx context.Context, client *http.Client
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewMockSocialConnector interface {
|
||||
// NewMockSocialConnector creates a new instance of MockSocialConnector. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockSocialConnector(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewMockSocialConnector creates a new instance of MockSocialConnector. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewMockSocialConnector(t mockConstructorTestingTNewMockSocialConnector) *MockSocialConnector {
|
||||
}) *MockSocialConnector {
|
||||
mock := &MockSocialConnector{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
|
||||
@@ -46,10 +46,6 @@ func DefaultService(cfg *config.PluginManagementCfg) *Service {
|
||||
|
||||
// Base returns the base path for the specified plugin.
|
||||
func (s *Service) Base(n PluginInfo) (string, error) {
|
||||
if n.class == plugins.ClassCore {
|
||||
baseDir := getBaseDir(n.fs.Base())
|
||||
return path.Join("public/app/plugins", string(n.pluginJSON.Type), baseDir), nil
|
||||
}
|
||||
if n.class == plugins.ClassCDN {
|
||||
return n.fs.Base(), nil
|
||||
}
|
||||
@@ -64,7 +60,6 @@ func (s *Service) Base(n PluginInfo) (string, error) {
|
||||
if s.cdn.PluginSupported(n.parent.pluginJSON.ID) {
|
||||
return s.cdn.AssetURL(n.parent.pluginJSON.ID, n.parent.pluginJSON.Info.Version, relPath)
|
||||
}
|
||||
return path.Join("public/plugins", n.parent.pluginJSON.ID, relPath), nil
|
||||
}
|
||||
|
||||
return path.Join("public/plugins", n.pluginJSON.ID), nil
|
||||
@@ -73,32 +68,12 @@ func (s *Service) Base(n PluginInfo) (string, error) {
|
||||
// Module returns the module.js path for the specified plugin.
|
||||
func (s *Service) Module(n PluginInfo) (string, error) {
|
||||
if n.class == plugins.ClassCore {
|
||||
if filepath.Base(n.fs.Base()) == "dist" {
|
||||
// The core plugin has been built externally, use the module from the dist folder
|
||||
} else {
|
||||
baseDir := getBaseDir(n.fs.Base())
|
||||
return path.Join("core:plugin", baseDir), nil
|
||||
if filepath.Base(n.fs.Base()) != "dist" {
|
||||
return path.Join("core:plugin", filepath.Base(n.fs.Base())), nil
|
||||
}
|
||||
}
|
||||
if n.class == plugins.ClassCDN {
|
||||
return pluginscdn.JoinPath(n.fs.Base(), "module.js")
|
||||
}
|
||||
|
||||
if s.cdn.PluginSupported(n.pluginJSON.ID) {
|
||||
return s.cdn.AssetURL(n.pluginJSON.ID, n.pluginJSON.Info.Version, "module.js")
|
||||
}
|
||||
if n.parent != nil {
|
||||
relPath, err := n.parent.fs.Rel(n.fs.Base())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if s.cdn.PluginSupported(n.parent.pluginJSON.ID) {
|
||||
return s.cdn.AssetURL(n.parent.pluginJSON.ID, n.parent.pluginJSON.Info.Version, path.Join(relPath, "module.js"))
|
||||
}
|
||||
return path.Join("public/plugins", n.parent.pluginJSON.ID, relPath, "module.js"), nil
|
||||
}
|
||||
|
||||
return path.Join("public/plugins", n.pluginJSON.ID, "module.js"), nil
|
||||
return s.RelativeURL(n, "module.js")
|
||||
}
|
||||
|
||||
// RelativeURL returns the relative URL for an arbitrary plugin asset.
|
||||
@@ -145,15 +120,6 @@ func (s *Service) DefaultLogoPath(pluginType plugins.Type) string {
|
||||
return path.Join("public/img", fmt.Sprintf("icn-%s.svg", string(pluginType)))
|
||||
}
|
||||
|
||||
func getBaseDir(pluginDir string) string {
|
||||
baseDir := filepath.Base(pluginDir)
|
||||
// Decoupled core plugins will be suffixed with "dist" if they have been built
|
||||
if baseDir == "dist" {
|
||||
return filepath.Base(strings.TrimSuffix(pluginDir, baseDir))
|
||||
}
|
||||
return baseDir
|
||||
}
|
||||
|
||||
func (s *Service) GetTranslations(n PluginInfo) (map[string]string, error) {
|
||||
pathToTranslations, err := s.RelativeURL(n, "locales")
|
||||
if err != nil {
|
||||
|
||||
@@ -78,7 +78,7 @@ func TestService(t *testing.T) {
|
||||
|
||||
base, err = svc.Base(NewPluginInfo(jsonData["table-old"], plugins.ClassCore, tableOldFS, nil))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "public/app/plugins/table-old", base)
|
||||
require.Equal(t, "public/plugins/table-old", base)
|
||||
|
||||
parentFS := pluginFS(oneCDNURL)
|
||||
parentFS.RelFunc = func(_ string) (string, error) {
|
||||
@@ -243,9 +243,9 @@ func TestService_ChildPlugins(t *testing.T) {
|
||||
return childInfo
|
||||
},
|
||||
expected: expected{
|
||||
module: "public/plugins/parent/child/module.js",
|
||||
baseURL: "public/plugins/parent/child",
|
||||
relURL: "public/plugins/parent/child/path/to/file.txt",
|
||||
module: "public/plugins/child/module.js",
|
||||
baseURL: "public/plugins/child",
|
||||
relURL: "public/plugins/child/path/to/file.txt",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -256,8 +256,8 @@ func TestService_ChildPlugins(t *testing.T) {
|
||||
},
|
||||
expected: expected{
|
||||
module: "core:plugin/parent",
|
||||
baseURL: "public/app/plugins/parent",
|
||||
relURL: "public/app/plugins/parent/path/to/file.txt",
|
||||
baseURL: "public/plugins/parent",
|
||||
relURL: "public/plugins/parent/path/to/file.txt",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -268,8 +268,8 @@ func TestService_ChildPlugins(t *testing.T) {
|
||||
},
|
||||
expected: expected{
|
||||
module: "public/plugins/parent/module.js",
|
||||
baseURL: "public/app/plugins/parent",
|
||||
relURL: "public/app/plugins/parent/path/to/file.txt",
|
||||
baseURL: "public/plugins/parent",
|
||||
relURL: "public/plugins/parent/path/to/file.txt",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -85,8 +85,8 @@ func TestLoader_Load(t *testing.T) {
|
||||
Description: "Data source for Amazon AWS monitoring service",
|
||||
Keywords: []string{"aws", "amazon"},
|
||||
Logos: plugins.Logos{
|
||||
Small: "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
|
||||
Large: "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
|
||||
Small: "public/plugins/cloudwatch/img/amazon-web-services.png",
|
||||
Large: "public/plugins/cloudwatch/img/amazon-web-services.png",
|
||||
},
|
||||
Links: []plugins.InfoLink{
|
||||
{Name: "Raise issue", URL: "https://github.com/grafana/grafana/issues/new"},
|
||||
@@ -123,7 +123,7 @@ func TestLoader_Load(t *testing.T) {
|
||||
QueryOptions: map[string]bool{"minInterval": true},
|
||||
},
|
||||
Module: "core:plugin/cloudwatch",
|
||||
BaseURL: "public/app/plugins/datasource/cloudwatch",
|
||||
BaseURL: "public/plugins/cloudwatch",
|
||||
FS: mustNewStaticFSForTests(t, filepath.Join(corePluginDir, "app/plugins/datasource/cloudwatch")),
|
||||
Signature: plugins.SignatureStatusInternal,
|
||||
Class: plugins.ClassCore,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package legacy
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
|
||||
resourcepb "github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ func (b *FolderAPIBuilder) Mutate(ctx context.Context, a admission.Attributes, _
|
||||
if !ok {
|
||||
return fmt.Errorf("obj is not folders.Folder")
|
||||
}
|
||||
f.Spec.Title = strings.Trim(f.Spec.Title, "")
|
||||
f.Spec.Title = strings.Trim(f.Spec.Title, " ")
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -479,7 +479,7 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := b.Validate(context.Background(), admission.NewAttributesRecord(
|
||||
admAttr := admission.NewAttributesRecord(
|
||||
tt.input,
|
||||
nil,
|
||||
folders.SchemeGroupVersion.WithKind("folder"),
|
||||
@@ -491,13 +491,18 @@ func TestFolderAPIBuilder_Mutate_Create(t *testing.T) {
|
||||
nil,
|
||||
true,
|
||||
&user.SignedInUser{},
|
||||
), nil)
|
||||
)
|
||||
|
||||
err := b.Validate(context.Background(), admAttr, nil)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
err = b.Mutate(context.Background(), admAttr, nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.input, tt.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -585,7 +590,7 @@ func TestFolderAPIBuilder_Mutate_Update(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := b.Validate(context.Background(), admission.NewAttributesRecord(
|
||||
admAttr := admission.NewAttributesRecord(
|
||||
tt.input,
|
||||
existingObj,
|
||||
folders.SchemeGroupVersion.WithKind("folder"),
|
||||
@@ -597,13 +602,18 @@ func TestFolderAPIBuilder_Mutate_Update(t *testing.T) {
|
||||
nil,
|
||||
true,
|
||||
&user.SignedInUser{},
|
||||
), nil)
|
||||
)
|
||||
|
||||
err := b.Validate(context.Background(), admAttr, nil)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
err = b.Mutate(context.Background(), admAttr, nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.input, tt.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package export
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package export
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package jobs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package jobs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package migrate
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
resourcepb "github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
)
|
||||
|
||||
// MockBulkStoreClient is an autogenerated mock type for the BulkStoreClient type
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package migrate
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package migrate
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package jobs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package jobs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package jobs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package jobs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package sync
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package sync
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package sync
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package sync
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package sync
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package jobs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package github
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package github
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package github
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package gogit
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package gogit
|
||||
|
||||
|
||||
@@ -595,7 +595,7 @@ func (r *gitRepository) resolveRefToHash(ctx context.Context, ref string) (hash.
|
||||
|
||||
// Try to parse ref as a hash first
|
||||
refHash, err := hash.FromHex(ref)
|
||||
if err == nil && refHash != nil {
|
||||
if err == nil && refHash != hash.Zero {
|
||||
// Valid hash, return it
|
||||
return refHash, nil
|
||||
}
|
||||
@@ -604,9 +604,9 @@ func (r *gitRepository) resolveRefToHash(ctx context.Context, ref string) (hash.
|
||||
branchRef, err := r.client.GetRef(ctx, ref)
|
||||
if err != nil {
|
||||
if errors.Is(err, nanogit.ErrObjectNotFound) {
|
||||
return nil, fmt.Errorf("ref not found: %s: %w", ref, repository.ErrRefNotFound)
|
||||
return hash.Zero, fmt.Errorf("ref not found: %s: %w", ref, repository.ErrRefNotFound)
|
||||
}
|
||||
return nil, fmt.Errorf("get ref %s: %w", ref, err)
|
||||
return hash.Zero, fmt.Errorf("get ref %s: %w", ref, err)
|
||||
}
|
||||
|
||||
return branchRef.Hash, nil
|
||||
|
||||
@@ -695,7 +695,7 @@ func TestGitRepository_Read(t *testing.T) {
|
||||
Hash: hash.Hash{},
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{
|
||||
Tree: hash.Hash([]byte("tree-hash")),
|
||||
Tree: hash.MustFromHex("abcdef1234567890abcdef1234567890abcdef12"),
|
||||
}, nil)
|
||||
mockClient.GetTreeByPathReturns(&nanogit.Tree{
|
||||
Hash: hash.Hash{},
|
||||
@@ -1191,7 +1191,7 @@ func TestGitRepository_LatestRef(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3}, // Non-empty hash
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, // Non-empty hash
|
||||
}, nil)
|
||||
},
|
||||
gitConfig: RepositoryConfig{
|
||||
@@ -1412,11 +1412,11 @@ func TestGitRepository_CompareFiles(t *testing.T) {
|
||||
// Return refs for base and ref
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
|
||||
// Return comparison results
|
||||
@@ -1449,11 +1449,11 @@ func TestGitRepository_CompareFiles(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
|
||||
mockClient.CompareCommitsReturns([]nanogit.CommitFile{}, nil)
|
||||
@@ -1547,7 +1547,7 @@ func TestGitRepository_ensureBranchExists(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
},
|
||||
gitConfig: RepositoryConfig{
|
||||
@@ -1565,7 +1565,7 @@ func TestGitRepository_ensureBranchExists(t *testing.T) {
|
||||
// Second call - get source branch
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
// CreateRef succeeds
|
||||
mockClient.CreateRefReturns(nil)
|
||||
@@ -1862,7 +1862,7 @@ func TestGitRepository_resolveRefToHash(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
},
|
||||
gitConfig: RepositoryConfig{
|
||||
@@ -1887,7 +1887,7 @@ func TestGitRepository_resolveRefToHash(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
},
|
||||
gitConfig: RepositoryConfig{
|
||||
@@ -1939,7 +1939,7 @@ func TestGitRepository_resolveRefToHash(t *testing.T) {
|
||||
|
||||
if tt.wantError {
|
||||
require.Error(t, err)
|
||||
require.Nil(t, refHash)
|
||||
require.Equal(t, hash.Zero, refHash)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, refHash)
|
||||
@@ -2212,7 +2212,7 @@ func TestGitRepository_EdgeCases(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
@@ -2251,7 +2251,7 @@ func TestGitRepository_EdgeCases(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{Tree: hash.Hash{}}, nil)
|
||||
mockClient.GetBlobByPathReturns(&nanogit.Blob{}, errors.New("some read error"))
|
||||
@@ -2401,7 +2401,7 @@ func TestGitRepository_ResolveRefToHash_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/invalid-hex",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
},
|
||||
ref: "invalid-hex-zzz",
|
||||
@@ -2412,7 +2412,7 @@ func TestGitRepository_ResolveRefToHash_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
},
|
||||
ref: "refs/heads/feature",
|
||||
@@ -2423,7 +2423,7 @@ func TestGitRepository_ResolveRefToHash_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/tags/v1.0.0",
|
||||
Hash: hash.Hash{7, 8, 9},
|
||||
Hash: hash.Hash{7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26},
|
||||
}, nil)
|
||||
},
|
||||
ref: "refs/tags/v1.0.0",
|
||||
@@ -2540,11 +2540,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
mockClient.CompareCommitsReturns(nil, errors.New("compare error"))
|
||||
},
|
||||
@@ -2558,11 +2558,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
mockClient.CompareCommitsReturns([]nanogit.CommitFile{
|
||||
{
|
||||
@@ -2580,11 +2580,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
mockClient.CompareCommitsReturns([]nanogit.CommitFile{
|
||||
{
|
||||
@@ -2606,11 +2606,11 @@ func TestGitRepository_CompareFiles_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
mockClient.CompareCommitsReturns([]nanogit.CommitFile{
|
||||
{
|
||||
@@ -2683,7 +2683,7 @@ func TestGitRepository_ReadTree_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetFlatTreeReturns(nil, errors.New("flat tree error"))
|
||||
},
|
||||
@@ -2694,23 +2694,23 @@ func TestGitRepository_ReadTree_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.GetFlatTreeReturns(&nanogit.FlatTree{
|
||||
Entries: []nanogit.FlatTreeEntry{
|
||||
{
|
||||
Path: "other/file.yaml", // Outside configs/
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
Type: protocol.ObjectTypeBlob,
|
||||
},
|
||||
{
|
||||
Path: "configs/included.yaml", // Inside configs/
|
||||
Hash: hash.Hash{7, 8, 9},
|
||||
Hash: hash.Hash{7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26},
|
||||
Type: protocol.ObjectTypeBlob,
|
||||
},
|
||||
{
|
||||
Path: "configs/dir", // Directory without trailing slash
|
||||
Hash: hash.Hash{10, 11, 12},
|
||||
Hash: hash.Hash{10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
|
||||
Type: protocol.ObjectTypeTree,
|
||||
},
|
||||
},
|
||||
@@ -2828,7 +2828,7 @@ func TestGitRepository_ensureBranchExists_ErrorConditions(t *testing.T) {
|
||||
// Second call - get source branch
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
// CreateRef fails
|
||||
mockClient.CreateRefReturns(errors.New("create ref failed"))
|
||||
@@ -2880,10 +2880,10 @@ func TestGitRepository_Read_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121315"),
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{
|
||||
Tree: hash.Hash([]byte("tree-hash")),
|
||||
Tree: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetTreeByPathReturns(nil, errors.New("tree error"))
|
||||
},
|
||||
@@ -2895,7 +2895,7 @@ func TestGitRepository_Read_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(nil, errors.New("commit error"))
|
||||
},
|
||||
@@ -2907,10 +2907,10 @@ func TestGitRepository_Read_EdgeCases(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{
|
||||
Tree: hash.Hash{4, 5, 6},
|
||||
Hash: hash.MustFromHex("0102030405060708092a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetBlobByPathReturns(nil, errors.New("blob error"))
|
||||
},
|
||||
@@ -2965,7 +2965,7 @@ func TestGitRepository_Create_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.NewStagedWriterReturns(nil, errors.New("staged writer error"))
|
||||
},
|
||||
@@ -2977,7 +2977,7 @@ func TestGitRepository_Create_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
mockWriter.CreateBlobReturns(hash.Hash{}, errors.New("create blob error"))
|
||||
@@ -3030,7 +3030,7 @@ func TestGitRepository_Update_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.Hash{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
}, nil)
|
||||
mockClient.NewStagedWriterReturns(nil, errors.New("staged writer error"))
|
||||
},
|
||||
@@ -3042,7 +3042,7 @@ func TestGitRepository_Update_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
mockWriter.UpdateBlobReturns(hash.Hash{}, errors.New("update blob error"))
|
||||
@@ -3096,7 +3096,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.NewStagedWriterReturns(nil, errors.New("staged writer error"))
|
||||
},
|
||||
@@ -3109,7 +3109,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
mockWriter.DeleteBlobReturns(hash.Hash{}, errors.New("delete blob error"))
|
||||
@@ -3124,7 +3124,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
mockWriter.DeleteTreeReturns(hash.Hash{}, errors.New("delete tree error"))
|
||||
@@ -3139,7 +3139,7 @@ func TestGitRepository_Delete_ErrorConditions(t *testing.T) {
|
||||
setupMock: func(mockClient *mocks.FakeClient) {
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
mockWriter.DeleteTreeReturns(hash.Hash{}, nanogit.ErrObjectNotFound)
|
||||
@@ -3186,7 +3186,7 @@ func TestGitRepository_CompareFiles_EmptyBase(t *testing.T) {
|
||||
// Only setup for ref resolution
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.CompareCommitsReturns([]nanogit.CommitFile{
|
||||
{
|
||||
@@ -3218,8 +3218,8 @@ func TestGitRepository_CompareFiles_EmptyBase(t *testing.T) {
|
||||
// Verify CompareCommits was called with empty base hash and feature hash
|
||||
require.Equal(t, 1, mockClient.CompareCommitsCallCount())
|
||||
_, baseHash, refHash := mockClient.CompareCommitsArgsForCall(0)
|
||||
require.Nil(t, baseHash) // Empty hash for empty base
|
||||
require.Equal(t, hash.Hash{4, 5, 6}, refHash)
|
||||
require.Equal(t, hash.Zero, baseHash) // Empty hash for empty base
|
||||
require.Equal(t, hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"), refHash)
|
||||
}
|
||||
|
||||
func TestGitRepository_EmptyRefHandling(t *testing.T) {
|
||||
@@ -3237,7 +3237,7 @@ func TestGitRepository_EmptyRefHandling(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
@@ -3299,7 +3299,7 @@ func TestGitRepository_CompareFiles_ResolveErrors(t *testing.T) {
|
||||
// First call succeeds for base
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
// Second call fails for ref
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{}, errors.New("ref error"))
|
||||
@@ -3341,14 +3341,14 @@ func TestGitRepository_Read_EmptyRef(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{
|
||||
Tree: hash.Hash{4, 5, 6},
|
||||
Tree: hash.Hash{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
|
||||
}, nil)
|
||||
mockClient.GetBlobByPathReturns(&nanogit.Blob{
|
||||
Content: []byte("file content"),
|
||||
Hash: hash.Hash{7, 8, 9},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
|
||||
gitRepo := &gitRepository{
|
||||
@@ -3376,13 +3376,13 @@ func TestGitRepository_ReadTree_EmptyRef(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetFlatTreeReturns(&nanogit.FlatTree{
|
||||
Entries: []nanogit.FlatTreeEntry{
|
||||
{
|
||||
Path: "configs/test.yaml",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
Type: protocol.ObjectTypeBlob,
|
||||
},
|
||||
},
|
||||
@@ -3504,17 +3504,17 @@ func TestGitRepository_Write_DefaultRef(t *testing.T) {
|
||||
// First call for Read check - file not found
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{
|
||||
Tree: hash.Hash{4, 5, 6},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetBlobByPathReturns(&nanogit.Blob{}, nanogit.ErrObjectNotFound)
|
||||
|
||||
// Second call for Create
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockWriter := &mocks.FakeStagedWriter{}
|
||||
mockWriter.CreateBlobReturns(hash.Hash{}, nil)
|
||||
@@ -3545,14 +3545,14 @@ func TestGitRepository_Read_RefInFileInfo(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{
|
||||
Tree: hash.Hash{4, 5, 6},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetBlobByPathReturns(&nanogit.Blob{
|
||||
Content: []byte("file content"),
|
||||
Hash: hash.Hash{7, 8, 9},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
|
||||
gitRepo := &gitRepository{
|
||||
@@ -3582,10 +3582,10 @@ func TestGitRepository_Read_GetTreeByPath_NotFound(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetCommitReturns(&nanogit.Commit{
|
||||
Tree: hash.Hash([]byte("tree-hash")),
|
||||
Tree: hash.Hash{30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49},
|
||||
}, nil)
|
||||
mockClient.GetTreeByPathReturns(nil, nanogit.ErrObjectNotFound)
|
||||
|
||||
@@ -3614,7 +3614,7 @@ func TestGitRepository_ReadTree_GetFlatTree_NotFound(t *testing.T) {
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturns(nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetFlatTreeReturns(nil, nanogit.ErrObjectNotFound)
|
||||
|
||||
@@ -3655,11 +3655,11 @@ func TestGitRepository_CompareFiles_FilesOutsideConfiguredPath_AllStatuses(t *te
|
||||
mockClient := &mocks.FakeClient{}
|
||||
mockClient.GetRefReturnsOnCall(0, nanogit.Ref{
|
||||
Name: "refs/heads/main",
|
||||
Hash: hash.Hash{1, 2, 3},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121314"),
|
||||
}, nil)
|
||||
mockClient.GetRefReturnsOnCall(1, nanogit.Ref{
|
||||
Name: "refs/heads/feature",
|
||||
Hash: hash.Hash{4, 5, 6},
|
||||
Hash: hash.MustFromHex("0102030405060708090a0b0c0d0e0f1011121315"),
|
||||
}, nil)
|
||||
mockClient.CompareCommitsReturns([]nanogit.CommitFile{
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
@@ -26,64 +26,6 @@ func (_m *MockRepositoryResources) EXPECT() *MockRepositoryResources_Expecter {
|
||||
return &MockRepositoryResources_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// WriteResourceFileFromObject provides a mock function with given fields: ctx, obj, options
|
||||
func (_m *MockRepositoryResources) WriteResourceFileFromObject(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions) (string, error) {
|
||||
ret := _m.Called(ctx, obj, options)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for WriteResourceFileFromObject")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)); ok {
|
||||
return rf(ctx, obj, options)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) string); ok {
|
||||
r0 = rf(ctx, obj, options)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *unstructured.Unstructured, WriteOptions) error); ok {
|
||||
r1 = rf(ctx, obj, options)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRepositoryResources_WriteResourceFileFromObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteResourceFileFromObject'
|
||||
type MockRepositoryResources_WriteResourceFileFromObject_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// WriteResourceFileFromObject is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - obj *unstructured.Unstructured
|
||||
// - options WriteOptions
|
||||
func (_e *MockRepositoryResources_Expecter) WriteResourceFileFromObject(ctx interface{}, obj interface{}, options interface{}) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
return &MockRepositoryResources_WriteResourceFileFromObject_Call{Call: _e.mock.On("WriteResourceFileFromObject", ctx, obj, options)}
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Run(run func(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions)) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*unstructured.Unstructured), args[2].(WriteOptions))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Return(_a0 string, _a1 error) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) RunAndReturn(run func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// EnsureFolderExists provides a mock function with given fields: ctx, folder, parentID
|
||||
func (_m *MockRepositoryResources) EnsureFolderExists(ctx context.Context, folder Folder, parentID string) error {
|
||||
ret := _m.Called(ctx, folder, parentID)
|
||||
@@ -520,6 +462,64 @@ func (_c *MockRepositoryResources_Stats_Call) RunAndReturn(run func(context.Cont
|
||||
return _c
|
||||
}
|
||||
|
||||
// WriteResourceFileFromObject provides a mock function with given fields: ctx, obj, options
|
||||
func (_m *MockRepositoryResources) WriteResourceFileFromObject(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions) (string, error) {
|
||||
ret := _m.Called(ctx, obj, options)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for WriteResourceFileFromObject")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)); ok {
|
||||
return rf(ctx, obj, options)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *unstructured.Unstructured, WriteOptions) string); ok {
|
||||
r0 = rf(ctx, obj, options)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *unstructured.Unstructured, WriteOptions) error); ok {
|
||||
r1 = rf(ctx, obj, options)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockRepositoryResources_WriteResourceFileFromObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteResourceFileFromObject'
|
||||
type MockRepositoryResources_WriteResourceFileFromObject_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// WriteResourceFileFromObject is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - obj *unstructured.Unstructured
|
||||
// - options WriteOptions
|
||||
func (_e *MockRepositoryResources_Expecter) WriteResourceFileFromObject(ctx interface{}, obj interface{}, options interface{}) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
return &MockRepositoryResources_WriteResourceFileFromObject_Call{Call: _e.mock.On("WriteResourceFileFromObject", ctx, obj, options)}
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Run(run func(ctx context.Context, obj *unstructured.Unstructured, options WriteOptions)) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*unstructured.Unstructured), args[2].(WriteOptions))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) Return(_a0 string, _a1 error) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockRepositoryResources_WriteResourceFileFromObject_Call) RunAndReturn(run func(context.Context, *unstructured.Unstructured, WriteOptions) (string, error)) *MockRepositoryResources_WriteResourceFileFromObject_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// WriteResourceFromFile provides a mock function with given fields: ctx, path, ref
|
||||
func (_m *MockRepositoryResources) WriteResourceFromFile(ctx context.Context, path string, ref string) (string, schema.GroupVersionKind, error) {
|
||||
ret := _m.Called(ctx, path, ref)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package signature
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package signature
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package resources
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package secrets
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package pullrequest
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
resourcepb "github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
)
|
||||
|
||||
// MockBlobStoreClient is an autogenerated mock type for the BlobStoreClient type
|
||||
@@ -69,7 +69,7 @@ type MockBlobStoreClient_PutBlob_Call struct {
|
||||
|
||||
// PutBlob is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *resource.PutBlobRequest
|
||||
// - in *resourcepb.PutBlobRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *MockBlobStoreClient_Expecter) PutBlob(ctx interface{}, in interface{}, opts ...interface{}) *MockBlobStoreClient_PutBlob_Call {
|
||||
return &MockBlobStoreClient_PutBlob_Call{Call: _e.mock.On("PutBlob",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package pullrequest
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package pullrequest
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package pullrequest
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.52.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package pullrequest
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
package contracts
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type contextRequestIdKey struct{}
|
||||
|
||||
type OutboxMessageType string
|
||||
|
||||
func GetRequestId(ctx context.Context) string {
|
||||
v := ctx.Value(contextRequestIdKey{})
|
||||
requestId, ok := v.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
return requestId
|
||||
}
|
||||
|
||||
func ContextWithRequestID(ctx context.Context, requestId string) context.Context {
|
||||
return context.WithValue(ctx, contextRequestIdKey{}, requestId)
|
||||
}
|
||||
|
||||
const (
|
||||
CreateSecretOutboxMessage OutboxMessageType = "create"
|
||||
UpdateSecretOutboxMessage OutboxMessageType = "update"
|
||||
DeleteSecretOutboxMessage OutboxMessageType = "delete"
|
||||
)
|
||||
|
||||
type AppendOutboxMessage struct {
|
||||
RequestID string
|
||||
Type OutboxMessageType
|
||||
Name string
|
||||
Namespace string
|
||||
EncryptedSecret string
|
||||
KeeperName *string
|
||||
ExternalID *string
|
||||
}
|
||||
|
||||
type OutboxMessage struct {
|
||||
RequestID string
|
||||
Type OutboxMessageType
|
||||
MessageID int64
|
||||
Name string
|
||||
Namespace string
|
||||
EncryptedSecret string
|
||||
KeeperName *string
|
||||
ExternalID *string
|
||||
// How many times this message has been received
|
||||
ReceiveCount int
|
||||
Created int64
|
||||
}
|
||||
|
||||
type OutboxQueue interface {
|
||||
// Appends a message to the outbox queue
|
||||
Append(ctx context.Context, message AppendOutboxMessage) (int64, error)
|
||||
// Receives at most n messages from the outbox queue
|
||||
ReceiveN(ctx context.Context, n uint) ([]OutboxMessage, error)
|
||||
// Deletes a message from the outbox queue
|
||||
Delete(ctx context.Context, messageID int64) error
|
||||
// Increments the number of times each message has been received by 1. Must be atomic.
|
||||
IncrementReceiveCount(ctx context.Context, messageIDs []int64) error
|
||||
}
|
||||
@@ -32,10 +32,9 @@ type ReadOpts struct {
|
||||
type SecureValueMetadataStorage interface {
|
||||
Create(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error)
|
||||
Read(ctx context.Context, namespace xkube.Namespace, name string, opts ReadOpts) (*secretv0alpha1.SecureValue, error)
|
||||
Update(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error)
|
||||
Delete(ctx context.Context, namespace xkube.Namespace, name string) error
|
||||
List(ctx context.Context, namespace xkube.Namespace) ([]secretv0alpha1.SecureValue, error)
|
||||
SetStatus(ctx context.Context, namespace xkube.Namespace, name string, status secretv0alpha1.SecureValueStatus) error
|
||||
SetExternalID(ctx context.Context, namespace xkube.Namespace, name string, externalID ExternalID) error
|
||||
SetVersionToActive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error
|
||||
SetVersionToInactive(ctx context.Context, namespace xkube.Namespace, name string, version int64) error
|
||||
SetExternalID(ctx context.Context, namespace xkube.Namespace, name string, version int64, externalID ExternalID) error
|
||||
ReadForDecrypt(ctx context.Context, namespace xkube.Namespace, name string) (*DecryptSecureValue, error)
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
claims "github.com/grafana/authlib/types"
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/tracectx"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
@@ -19,8 +19,8 @@ type SecureValueService struct {
|
||||
accessClient claims.AccessClient
|
||||
database contracts.Database
|
||||
secureValueMetadataStorage contracts.SecureValueMetadataStorage
|
||||
outboxQueue contracts.OutboxQueue
|
||||
encryptionManager contracts.EncryptionManager
|
||||
keeperMetadataStorage contracts.KeeperMetadataStorage
|
||||
keeperService contracts.KeeperService
|
||||
}
|
||||
|
||||
func ProvideSecureValueService(
|
||||
@@ -28,16 +28,16 @@ func ProvideSecureValueService(
|
||||
accessClient claims.AccessClient,
|
||||
database contracts.Database,
|
||||
secureValueMetadataStorage contracts.SecureValueMetadataStorage,
|
||||
outboxQueue contracts.OutboxQueue,
|
||||
encryptionManager contracts.EncryptionManager,
|
||||
keeperMetadataStorage contracts.KeeperMetadataStorage,
|
||||
keeperService contracts.KeeperService,
|
||||
) *SecureValueService {
|
||||
return &SecureValueService{
|
||||
tracer: tracer,
|
||||
accessClient: accessClient,
|
||||
database: database,
|
||||
secureValueMetadataStorage: secureValueMetadataStorage,
|
||||
outboxQueue: outboxQueue,
|
||||
encryptionManager: encryptionManager,
|
||||
keeperMetadataStorage: keeperMetadataStorage,
|
||||
keeperService: keeperService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,43 +48,91 @@ func (s *SecureValueService) Create(ctx context.Context, sv *secretv0alpha1.Secu
|
||||
attribute.String("actor", actorUID),
|
||||
))
|
||||
defer span.End()
|
||||
return s.createNewVersion(ctx, sv, actorUID)
|
||||
}
|
||||
|
||||
sv.Status = secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhasePending, Message: "Creating secure value"}
|
||||
func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, bool, error) {
|
||||
ctx, span := s.tracer.Start(ctx, "SecureValueService.Update", trace.WithAttributes(
|
||||
attribute.String("name", newSecureValue.GetName()),
|
||||
attribute.String("namespace", newSecureValue.GetNamespace()),
|
||||
attribute.String("actor", actorUID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
var out *secretv0alpha1.SecureValue
|
||||
|
||||
encryptedSecret, err := s.encryptionManager.Encrypt(ctx, sv.Namespace, []byte(sv.Spec.Value.DangerouslyExposeAndConsumeValue()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("encrypting secure value secret: %w", err)
|
||||
}
|
||||
|
||||
// Specifically here so that the spans from the worker are not inside the transaction.
|
||||
requestID := tracectx.HexEncodeTraceFromContext(ctx)
|
||||
|
||||
if err := s.database.Transaction(ctx, func(ctx context.Context) error {
|
||||
createdSecureValue, err := s.secureValueMetadataStorage.Create(ctx, sv, actorUID)
|
||||
if newSecureValue.Spec.Value == "" {
|
||||
decrypted, err := s.secureValueMetadataStorage.ReadForDecrypt(ctx, xkube.Namespace(newSecureValue.Namespace), newSecureValue.Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create securevalue: %w", err)
|
||||
}
|
||||
out = createdSecureValue
|
||||
|
||||
if _, err := s.outboxQueue.Append(ctx, contracts.AppendOutboxMessage{
|
||||
RequestID: requestID,
|
||||
Type: contracts.CreateSecretOutboxMessage,
|
||||
Name: sv.Name,
|
||||
Namespace: sv.Namespace,
|
||||
EncryptedSecret: string(encryptedSecret),
|
||||
KeeperName: sv.Spec.Keeper,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to append message to create secure value to outbox queue: %w", err)
|
||||
return nil, false, fmt.Errorf("reading secure value secret: %+w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return out, err
|
||||
// TODO: does this need to be for update?
|
||||
keeperCfg, err := s.keeperMetadataStorage.GetKeeperConfig(ctx, newSecureValue.Namespace, newSecureValue.Spec.Keeper, contracts.ReadOpts{ForUpdate: true})
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("fetching keeper config: namespace=%+v keeperName=%+v %w", newSecureValue.Namespace, newSecureValue.Spec.Keeper, err)
|
||||
}
|
||||
|
||||
keeper, err := s.keeperService.KeeperForConfig(keeperCfg)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("getting keeper for config: namespace=%+v keeperName=%+v %w", newSecureValue.Namespace, newSecureValue.Spec.Keeper, err)
|
||||
}
|
||||
logging.FromContext(ctx).Debug("retrieved keeper", "namespace", newSecureValue.Namespace, "keeperName", newSecureValue.Spec.Keeper, "type", keeperCfg.Type())
|
||||
|
||||
secret, err := keeper.Expose(ctx, keeperCfg, newSecureValue.Namespace, contracts.ExternalID(decrypted.ExternalID))
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("reading secret value from keeper: %w", err)
|
||||
}
|
||||
|
||||
newSecureValue.Spec.Value = secret
|
||||
}
|
||||
|
||||
return out, nil
|
||||
const updateIsSync = true
|
||||
createdSv, err := s.createNewVersion(ctx, newSecureValue, actorUID)
|
||||
return createdSv, updateIsSync, err
|
||||
}
|
||||
|
||||
func (s *SecureValueService) createNewVersion(ctx context.Context, sv *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, error) {
|
||||
createdSv, err := s.secureValueMetadataStorage.Create(ctx, sv, actorUID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating secure value: %w", err)
|
||||
}
|
||||
createdSv.Status = secretv0alpha1.SecureValueStatus{
|
||||
Version: createdSv.Status.Version,
|
||||
}
|
||||
|
||||
// TODO: does this need to be for update?
|
||||
keeperCfg, err := s.keeperMetadataStorage.GetKeeperConfig(ctx, sv.Namespace, sv.Spec.Keeper, contracts.ReadOpts{ForUpdate: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching keeper config: namespace=%+v keeperName=%+v %w", sv.Namespace, sv.Spec.Keeper, err)
|
||||
}
|
||||
|
||||
keeper, err := s.keeperService.KeeperForConfig(keeperCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting keeper for config: namespace=%+v keeperName=%+v %w", sv.Namespace, sv.Spec.Keeper, err)
|
||||
}
|
||||
logging.FromContext(ctx).Debug("retrieved keeper", "namespace", sv.Namespace, "keeperName", sv.Spec.Keeper, "type", keeperCfg.Type())
|
||||
|
||||
// TODO: can we stop using external id?
|
||||
// TODO: store uses only the namespace and returns and id. It could be a kv instead.
|
||||
// TODO: check that the encrypted store works with multiple versions
|
||||
externalID, err := keeper.Store(ctx, keeperCfg, sv.Namespace, sv.Spec.Value.DangerouslyExposeAndConsumeValue())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("storing secure value in keeper: %w", err)
|
||||
}
|
||||
createdSv.Status.ExternalID = string(externalID)
|
||||
|
||||
if err := s.secureValueMetadataStorage.SetExternalID(ctx, xkube.Namespace(sv.Namespace), sv.Name, createdSv.Status.Version, externalID); err != nil {
|
||||
return nil, fmt.Errorf("setting secure value external id: %w", err)
|
||||
}
|
||||
|
||||
if err := s.secureValueMetadataStorage.SetVersionToActive(ctx, xkube.Namespace(sv.Namespace), sv.Name, createdSv.Status.Version); err != nil {
|
||||
return nil, fmt.Errorf("marking secure value version as active: %w", err)
|
||||
}
|
||||
|
||||
// In a single query:
|
||||
// TODO: set external id
|
||||
// TODO: set to active
|
||||
|
||||
return createdSv, nil
|
||||
}
|
||||
|
||||
func (s *SecureValueService) Read(ctx context.Context, namespace xkube.Namespace, name string) (*secretv0alpha1.SecureValue, error) {
|
||||
@@ -139,84 +187,6 @@ func (s *SecureValueService) List(ctx context.Context, namespace xkube.Namespace
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *SecureValueService) Update(ctx context.Context, newSecureValue *secretv0alpha1.SecureValue, actorUID string) (*secretv0alpha1.SecureValue, bool, error) {
|
||||
ctx, span := s.tracer.Start(ctx, "SecureValueService.Create", trace.WithAttributes(
|
||||
attribute.String("name", newSecureValue.GetName()),
|
||||
attribute.String("namespace", newSecureValue.GetNamespace()),
|
||||
attribute.String("actor", actorUID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
// True when the effects of an update can be seen immediately.
|
||||
// Never true in this case since updating a secure value is async.
|
||||
const updateIsSync = false
|
||||
|
||||
var (
|
||||
out *secretv0alpha1.SecureValue
|
||||
encryptedSecret string
|
||||
)
|
||||
|
||||
if newSecureValue.Spec.Value != "" {
|
||||
buffer, err := s.encryptionManager.Encrypt(ctx, newSecureValue.Namespace, []byte(newSecureValue.Spec.Value.DangerouslyExposeAndConsumeValue()))
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("encrypting secure value secret: %w", err)
|
||||
}
|
||||
encryptedSecret = string(buffer)
|
||||
}
|
||||
|
||||
// Especifically here so that the spans from the worker are not inside the transaction.
|
||||
requestID := tracectx.HexEncodeTraceFromContext(ctx)
|
||||
|
||||
if err := s.database.Transaction(ctx, func(ctx context.Context) error {
|
||||
sv, err := s.secureValueMetadataStorage.Read(ctx, xkube.Namespace(newSecureValue.Namespace), newSecureValue.Name, contracts.ReadOpts{ForUpdate: true})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching secure value: %+w", err)
|
||||
}
|
||||
|
||||
if sv.Status.Phase == secretv0alpha1.SecureValuePhasePending {
|
||||
return contracts.ErrSecureValueOperationInProgress
|
||||
}
|
||||
|
||||
// Succeed immediately if the value is not going to be updated
|
||||
if encryptedSecret == "" {
|
||||
newSecureValue.Status = secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseSucceeded}
|
||||
} else {
|
||||
newSecureValue.Status = secretv0alpha1.SecureValueStatus{
|
||||
Message: "Updating secure value",
|
||||
Phase: secretv0alpha1.SecureValuePhasePending,
|
||||
}
|
||||
}
|
||||
|
||||
// Current implementation replaces everything passed in the spec, so it is not a PATCH. Do we want/need to support that?
|
||||
updatedSecureValue, err := s.secureValueMetadataStorage.Update(ctx, newSecureValue, actorUID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update secure value: %w", err)
|
||||
}
|
||||
out = updatedSecureValue
|
||||
|
||||
// Only the value needs to be updated asynchronously by the outbox worker
|
||||
if encryptedSecret != "" {
|
||||
if _, err := s.outboxQueue.Append(ctx, contracts.AppendOutboxMessage{
|
||||
RequestID: requestID,
|
||||
Type: contracts.UpdateSecretOutboxMessage,
|
||||
Name: newSecureValue.Name,
|
||||
Namespace: newSecureValue.Namespace,
|
||||
EncryptedSecret: encryptedSecret,
|
||||
KeeperName: newSecureValue.Spec.Keeper,
|
||||
ExternalID: &updatedSecureValue.Status.ExternalID,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to append message to update secure value to outbox queue: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return out, updateIsSync, err
|
||||
}
|
||||
|
||||
return out, updateIsSync, nil
|
||||
}
|
||||
|
||||
func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespace, name string) (*secretv0alpha1.SecureValue, error) {
|
||||
ctx, span := s.tracer.Start(ctx, "SecureValueService.Delete", trace.WithAttributes(
|
||||
attribute.String("name", name),
|
||||
@@ -224,45 +194,14 @@ func (s *SecureValueService) Delete(ctx context.Context, namespace xkube.Namespa
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
// Set inside of the transaction callback
|
||||
var out *secretv0alpha1.SecureValue
|
||||
|
||||
// Especifically here so that the spans from the worker are not inside the transaction.
|
||||
requestID := tracectx.HexEncodeTraceFromContext(ctx)
|
||||
|
||||
if err := s.database.Transaction(ctx, func(ctx context.Context) error {
|
||||
sv, err := s.secureValueMetadataStorage.Read(ctx, namespace, name, contracts.ReadOpts{ForUpdate: true})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching secure value: %+w", err)
|
||||
}
|
||||
|
||||
if sv.Status.Phase == secretv0alpha1.SecureValuePhasePending {
|
||||
return contracts.ErrSecureValueOperationInProgress
|
||||
}
|
||||
|
||||
sv.Status = secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhasePending, Message: "Deleting secure value"}
|
||||
|
||||
if err := s.secureValueMetadataStorage.SetStatus(ctx, namespace, name, sv.Status); err != nil {
|
||||
return fmt.Errorf("setting secure value status phase: %+w", err)
|
||||
}
|
||||
|
||||
if _, err := s.outboxQueue.Append(ctx, contracts.AppendOutboxMessage{
|
||||
RequestID: requestID,
|
||||
Type: contracts.DeleteSecretOutboxMessage,
|
||||
Name: name,
|
||||
Namespace: namespace.String(),
|
||||
KeeperName: sv.Spec.Keeper,
|
||||
ExternalID: &sv.Status.ExternalID,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("appending delete secure value message to outbox queue: %+w", err)
|
||||
}
|
||||
|
||||
out = sv
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return out, err
|
||||
sv, err := s.secureValueMetadataStorage.Read(ctx, namespace, name, contracts.ReadOpts{ForUpdate: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching secure value: %+w", err)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
if err := s.secureValueMetadataStorage.SetVersionToInactive(ctx, namespace, name, sv.Status.Version); err != nil {
|
||||
return nil, fmt.Errorf("setting secure value version to inactive: %+w", err)
|
||||
}
|
||||
|
||||
return sv, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package service_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/testutils"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCrud(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("creating a secure value creates new versions", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
sut := testutils.Setup(t)
|
||||
|
||||
sv1, err := sut.CreateSv(t.Context())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create the same secure value twice
|
||||
input := sv1.DeepCopy()
|
||||
input.Spec.Description = "d2"
|
||||
input.Spec.Value = v0alpha1.NewExposedSecureValue("v2")
|
||||
|
||||
sv2, err := sut.CreateSv(t.Context(), testutils.CreateSvWithSv(input))
|
||||
require.NoError(t, err)
|
||||
require.True(t, sv2.Status.Version > sv1.Status.Version)
|
||||
|
||||
// Read the secure value
|
||||
sv, err := sut.SecureValueService.Read(t.Context(), xkube.Namespace(sv2.Namespace), sv2.Name)
|
||||
require.NoError(t, err)
|
||||
|
||||
// It should be the latest version
|
||||
require.Equal(t, sv2.Namespace, sv.Namespace)
|
||||
require.Equal(t, sv2.Name, sv.Name)
|
||||
require.Equal(t, "d2", sv.Spec.Description)
|
||||
require.Equal(t, sv2.Status.Version, sv.Status.Version)
|
||||
})
|
||||
|
||||
t.Run("updating a secure value creates new versions", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
|
||||
// Create a secure value
|
||||
sv1, err := sut.CreateSv(t.Context())
|
||||
require.NoError(t, err)
|
||||
|
||||
ns := sv1.Namespace
|
||||
name := sv1.Name
|
||||
|
||||
// Update the secure value
|
||||
input := sv1.DeepCopy()
|
||||
input.Spec.Description = "d2"
|
||||
sv2, err := sut.UpdateSv(t.Context(), input)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read the secure value
|
||||
sv3, err := sut.SecureValueService.Read(t.Context(), xkube.Namespace(ns), name)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Nothing has changed except for the updated field.
|
||||
require.Equal(t, ns, sv2.Namespace)
|
||||
require.Equal(t, name, sv2.Name)
|
||||
require.True(t, sv2.Status.Version > sv1.Status.Version)
|
||||
require.Equal(t, "d2", sv2.Spec.Description)
|
||||
|
||||
require.Equal(t, ns, sv3.Namespace)
|
||||
require.Equal(t, name, sv3.Name)
|
||||
require.Equal(t, sv2.Status.Version, sv3.Status.Version)
|
||||
require.Equal(t, "d2", sv3.Spec.Description)
|
||||
})
|
||||
|
||||
t.Run("deleting secure values", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
|
||||
sv1, err := sut.CreateSv(t.Context())
|
||||
require.NoError(t, err)
|
||||
|
||||
sv2, err := sut.DeleteSv(t.Context(), sv1.Namespace, sv1.Name)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, sv1.Namespace, sv2.Namespace)
|
||||
require.Equal(t, sv1.Name, sv2.Name)
|
||||
|
||||
_, err = sut.SecureValueMetadataStorage.Read(t.Context(), xkube.Namespace(sv1.Namespace), sv1.Name, contracts.ReadOpts{})
|
||||
require.ErrorIs(t, err, contracts.ErrSecureValueNotFound)
|
||||
})
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package testutils
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
||||
encryptionstorage "github.com/grafana/grafana/pkg/storage/secret/encryption"
|
||||
@@ -12,11 +11,11 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/decrypt"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/encryption"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper/sqlkeeper"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/service"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/worker"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
@@ -29,35 +28,28 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type setupConfig struct {
|
||||
workerCfg worker.Config
|
||||
keeperService contracts.KeeperService
|
||||
type SetupConfig struct {
|
||||
KeeperService contracts.KeeperService
|
||||
AllowList map[string]struct{}
|
||||
}
|
||||
|
||||
func defaultSetupCfg() setupConfig {
|
||||
return setupConfig{
|
||||
workerCfg: worker.Config{
|
||||
BatchSize: 10,
|
||||
ReceiveTimeout: 1 * time.Second,
|
||||
PollingInterval: time.Millisecond,
|
||||
MaxMessageProcessingAttempts: 5,
|
||||
},
|
||||
func defaultSetupCfg() SetupConfig {
|
||||
return SetupConfig{}
|
||||
}
|
||||
|
||||
func WithKeeperService(keeperService contracts.KeeperService) func(*SetupConfig) {
|
||||
return func(setupCfg *SetupConfig) {
|
||||
setupCfg.KeeperService = keeperService
|
||||
}
|
||||
}
|
||||
|
||||
func WithWorkerConfig(cfg worker.Config) func(*setupConfig) {
|
||||
return func(setupCfg *setupConfig) {
|
||||
setupCfg.workerCfg = cfg
|
||||
func WithMutateCfg(f func(*SetupConfig)) func(*SetupConfig) {
|
||||
return func(cfg *SetupConfig) {
|
||||
f(cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func WithKeeperService(keeperService contracts.KeeperService) func(*setupConfig) {
|
||||
return func(setupCfg *setupConfig) {
|
||||
setupCfg.keeperService = keeperService
|
||||
}
|
||||
}
|
||||
|
||||
func Setup(t *testing.T, opts ...func(*setupConfig)) Sut {
|
||||
func Setup(t *testing.T, opts ...func(*SetupConfig)) Sut {
|
||||
setupCfg := defaultSetupCfg()
|
||||
for _, opt := range opts {
|
||||
opt(&setupCfg)
|
||||
@@ -68,8 +60,6 @@ func Setup(t *testing.T, opts ...func(*setupConfig)) Sut {
|
||||
|
||||
database := database.ProvideDatabase(testDB, tracer)
|
||||
|
||||
outboxQueue := metadata.ProvideOutboxQueue(database, tracer, nil)
|
||||
|
||||
features := featuremgmt.WithFeatures(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, featuremgmt.FlagSecretsManagementAppPlatform)
|
||||
|
||||
keeperMetadataStorage, err := metadata.ProvideKeeperMetadataStorage(database, tracer, features, nil)
|
||||
@@ -111,34 +101,24 @@ func Setup(t *testing.T, opts ...func(*setupConfig)) Sut {
|
||||
|
||||
var keeperService contracts.KeeperService = newKeeperServiceWrapper(sqlKeeper)
|
||||
|
||||
if setupCfg.keeperService != nil {
|
||||
keeperService = setupCfg.keeperService
|
||||
if setupCfg.KeeperService != nil {
|
||||
keeperService = setupCfg.KeeperService
|
||||
}
|
||||
|
||||
secureValueService := service.ProvideSecureValueService(tracer, accessClient, database, secureValueMetadataStorage, outboxQueue, encryptionManager)
|
||||
secureValueService := service.ProvideSecureValueService(tracer, accessClient, database, secureValueMetadataStorage, keeperMetadataStorage, keeperService)
|
||||
|
||||
worker, err := worker.NewWorker(
|
||||
setupCfg.workerCfg,
|
||||
tracer,
|
||||
database,
|
||||
outboxQueue,
|
||||
secureValueMetadataStorage,
|
||||
keeperMetadataStorage,
|
||||
keeperService,
|
||||
encryptionManager,
|
||||
features,
|
||||
nil, // metrics
|
||||
)
|
||||
decryptAuthorizer := decrypt.ProvideDecryptAuthorizer(tracer, setupCfg.AllowList)
|
||||
|
||||
decryptStorage, err := metadata.ProvideDecryptStorage(features, tracer, keeperService, keeperMetadataStorage, secureValueMetadataStorage, decryptAuthorizer, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
return Sut{Worker: worker, SecureValueService: secureValueService, SecureValueMetadataStorage: secureValueMetadataStorage, OutboxQueue: outboxQueue, Database: database}
|
||||
return Sut{SecureValueService: secureValueService, SecureValueMetadataStorage: secureValueMetadataStorage, Database: database, DecryptStorage: decryptStorage}
|
||||
}
|
||||
|
||||
type Sut struct {
|
||||
Worker *worker.Worker
|
||||
SecureValueService *service.SecureValueService
|
||||
SecureValueMetadataStorage contracts.SecureValueMetadataStorage
|
||||
OutboxQueue contracts.OutboxQueue
|
||||
DecryptStorage contracts.DecryptStorage
|
||||
Database *database.Database
|
||||
}
|
||||
|
||||
@@ -163,9 +143,7 @@ func (s *Sut) CreateSv(ctx context.Context, opts ...func(*CreateSvConfig)) (*sec
|
||||
Description: "desc1",
|
||||
Value: secretv0alpha1.NewExposedSecureValue("v1"),
|
||||
},
|
||||
Status: secretv0alpha1.SecureValueStatus{
|
||||
Phase: secretv0alpha1.SecureValuePhasePending,
|
||||
},
|
||||
Status: secretv0alpha1.SecureValueStatus{},
|
||||
},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
namespace = "grafana_secrets_manager"
|
||||
subsystem = "outbox_worker"
|
||||
)
|
||||
|
||||
// OutboxMetrics is a struct that contains all the metrics for an implementation of the secrets service.
|
||||
type OutboxMetrics struct {
|
||||
OutboxMessageProcessingDuration *prometheus.HistogramVec
|
||||
}
|
||||
|
||||
func newOutboxMetrics() *OutboxMetrics {
|
||||
return &OutboxMetrics{
|
||||
OutboxMessageProcessingDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "message_processing_duration_seconds",
|
||||
Help: "Duration of outbox message processing",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
}, []string{"message_type", "keeper_type"}),
|
||||
}
|
||||
}
|
||||
|
||||
// NewOutboxMetrics creates a new SecretsMetrics struct containing registered metrics
|
||||
func NewOutboxMetrics(reg prometheus.Registerer) *OutboxMetrics {
|
||||
m := newOutboxMetrics()
|
||||
|
||||
if reg != nil {
|
||||
reg.MustRegister(
|
||||
m.OutboxMessageProcessingDuration,
|
||||
)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func NewTestMetrics() *OutboxMetrics {
|
||||
return newOutboxMetrics()
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/tracectx"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Consumes and processes messages from the secure value outbox queue
|
||||
type Worker struct {
|
||||
config Config
|
||||
tracer trace.Tracer
|
||||
database contracts.Database
|
||||
outboxQueue contracts.OutboxQueue
|
||||
secureValueMetadataStorage contracts.SecureValueMetadataStorage
|
||||
keeperMetadataStorage contracts.KeeperMetadataStorage
|
||||
keeperService contracts.KeeperService
|
||||
encryptionManager contracts.EncryptionManager
|
||||
metrics *OutboxMetrics
|
||||
enabled bool
|
||||
}
|
||||
|
||||
// DefaultConfig for the secure value outbox worker.
|
||||
var DefaultConfig = Config{
|
||||
BatchSize: 20,
|
||||
ReceiveTimeout: 5 * time.Second,
|
||||
PollingInterval: 100 * time.Millisecond,
|
||||
MaxMessageProcessingAttempts: 10,
|
||||
}
|
||||
|
||||
// ProvideWorkerConfig used for wire.
|
||||
func ProvideWorkerConfig() Config {
|
||||
return DefaultConfig
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
// The max number of messages to fetch from the outbox queue in a batch
|
||||
BatchSize uint
|
||||
// How long to wait for a request to fetch messages from the outbox queue
|
||||
ReceiveTimeout time.Duration
|
||||
// How often to poll the outbox queue for new messages
|
||||
PollingInterval time.Duration
|
||||
// How many tries to try to process a message before marking the operation as failed
|
||||
MaxMessageProcessingAttempts uint
|
||||
}
|
||||
|
||||
func NewWorker(
|
||||
config Config,
|
||||
tracer trace.Tracer,
|
||||
database contracts.Database,
|
||||
outboxQueue contracts.OutboxQueue,
|
||||
secureValueMetadataStorage contracts.SecureValueMetadataStorage,
|
||||
keeperMetadataStorage contracts.KeeperMetadataStorage,
|
||||
keeperService contracts.KeeperService,
|
||||
encryptionManager contracts.EncryptionManager,
|
||||
features featuremgmt.FeatureToggles,
|
||||
reg prometheus.Registerer,
|
||||
) (*Worker, error) {
|
||||
if config.BatchSize == 0 {
|
||||
return nil, fmt.Errorf("config.BatchSize is required")
|
||||
}
|
||||
if config.ReceiveTimeout == 0 {
|
||||
return nil, fmt.Errorf("config.ReceiveTimeout is required")
|
||||
}
|
||||
if config.PollingInterval == 0 {
|
||||
return nil, fmt.Errorf("config.PollingInterval is required")
|
||||
}
|
||||
if config.MaxMessageProcessingAttempts == 0 {
|
||||
return nil, fmt.Errorf("config.MaxMessageProcessingAttempts is required")
|
||||
}
|
||||
|
||||
// Require both features to be enabled for the worker to run.
|
||||
enabled := features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) && features.IsEnabledGlobally(featuremgmt.FlagSecretsManagementAppPlatform)
|
||||
|
||||
return &Worker{
|
||||
config: config,
|
||||
tracer: tracer,
|
||||
database: database,
|
||||
outboxQueue: outboxQueue,
|
||||
secureValueMetadataStorage: secureValueMetadataStorage,
|
||||
keeperMetadataStorage: keeperMetadataStorage,
|
||||
keeperService: keeperService,
|
||||
encryptionManager: encryptionManager,
|
||||
metrics: NewOutboxMetrics(reg),
|
||||
enabled: enabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Ensure that Worker implements the BackgroundService interface, so we can start it as a background service.
|
||||
var _ registry.BackgroundService = (*Worker)(nil)
|
||||
|
||||
// Run is the main method to drive the worker
|
||||
func (w *Worker) Run(ctx context.Context) error {
|
||||
if !w.enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
logging.FromContext(ctx).Debug("starting worker control loop")
|
||||
|
||||
t := time.NewTicker(w.config.PollingInterval)
|
||||
defer t.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
// If the context was canceled
|
||||
case <-ctx.Done():
|
||||
// return the reason it was canceled
|
||||
return ctx.Err()
|
||||
|
||||
// Otherwise try to receive messages
|
||||
case <-t.C:
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
if err := w.ReceiveAndProcessMessages(ctx); err != nil {
|
||||
logging.FromContext(ctx).Error("receiving outbox messages", "err", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: don't rollback every message when a single error happens
|
||||
func (w *Worker) ReceiveAndProcessMessages(ctx context.Context) error {
|
||||
messageIDs := make([]int64, 0)
|
||||
|
||||
txErr := w.database.Transaction(ctx, func(ctx context.Context) error {
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, w.config.ReceiveTimeout)
|
||||
messages, err := w.outboxQueue.ReceiveN(timeoutCtx, w.config.BatchSize)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, message := range messages {
|
||||
messageIDs = append(messageIDs, message.MessageID)
|
||||
if err := w.processMessage(ctx, message); err != nil {
|
||||
return fmt.Errorf("processing message: %+v %w", message, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// This call is made outside the transaction to make sure the receive count is updated on rollbacks.
|
||||
incrementErr := w.outboxQueue.IncrementReceiveCount(ctx, messageIDs)
|
||||
if incrementErr != nil {
|
||||
incrementErr = fmt.Errorf("incrementing receive count for outbox message: %w", incrementErr)
|
||||
}
|
||||
|
||||
return errors.Join(txErr, incrementErr)
|
||||
}
|
||||
|
||||
func (w *Worker) processMessage(ctx context.Context, message contracts.OutboxMessage) error {
|
||||
start := time.Now()
|
||||
keeperType := "unknown"
|
||||
defer func() {
|
||||
w.metrics.OutboxMessageProcessingDuration.WithLabelValues(string(message.Type), keeperType).Observe(time.Since(start).Seconds())
|
||||
}()
|
||||
logging.FromContext(ctx).Debug("processing message", "type", message.Type, "name", message.Name, "namespace", message.Namespace, "receiveCount", message.ReceiveCount)
|
||||
|
||||
opts := []trace.SpanStartOption{}
|
||||
// If there's no request ID in the message, start a new root span and log an error.
|
||||
ctx, err := tracectx.HexDecodeTraceIntoContext(ctx, message.RequestID)
|
||||
if err != nil {
|
||||
opts = append(opts, trace.WithNewRoot())
|
||||
logging.FromContext(ctx).Error("decoding trace context from message", "err", err.Error(), "message.requestID", message.RequestID)
|
||||
}
|
||||
|
||||
opts = append(opts, trace.WithAttributes(
|
||||
attribute.String("message.requestID", message.RequestID),
|
||||
attribute.Int64("message.id", message.MessageID),
|
||||
attribute.String("message.type", string(message.Type)),
|
||||
attribute.String("message.namespace", message.Namespace),
|
||||
attribute.String("message.secureValue.name", message.Name),
|
||||
attribute.Int("message.receive.count", message.ReceiveCount),
|
||||
))
|
||||
|
||||
ctx, span := w.tracer.Start(ctx, "Worker.ProcessMessage", opts...)
|
||||
defer span.End()
|
||||
|
||||
if message.ReceiveCount >= int(w.config.MaxMessageProcessingAttempts) {
|
||||
if err := w.secureValueMetadataStorage.SetStatus(ctx, xkube.Namespace(message.Namespace), message.Name, secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseFailed, Message: fmt.Sprintf("Reached max number of attempts to complete operation: %s", message.Type)}); err != nil {
|
||||
return fmt.Errorf("setting secret metadata status to Succeeded: message=%+v", message)
|
||||
}
|
||||
if err := w.outboxQueue.Delete(ctx, message.MessageID); err != nil {
|
||||
return fmt.Errorf("deleting message from outbox queue: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
keeperCfg, err := w.keeperMetadataStorage.GetKeeperConfig(ctx, message.Namespace, message.KeeperName, contracts.ReadOpts{ForUpdate: true})
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetching keeper config: namespace=%+v keeperName=%+v %w", message.Namespace, message.KeeperName, err)
|
||||
}
|
||||
keeperType = string(keeperCfg.Type())
|
||||
|
||||
keeper, err := w.keeperService.KeeperForConfig(keeperCfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting keeper for config: namespace=%+v keeperName=%+v %w", message.Namespace, message.KeeperName, err)
|
||||
}
|
||||
logging.FromContext(ctx).Debug("retrieved keeper", "namespace", message.Namespace, "keeperName", message.KeeperName, "type", keeperCfg.Type())
|
||||
|
||||
switch message.Type {
|
||||
case contracts.CreateSecretOutboxMessage:
|
||||
rawSecret, err := w.encryptionManager.Decrypt(ctx, message.Namespace, []byte(message.EncryptedSecret))
|
||||
if err != nil {
|
||||
return fmt.Errorf("decrypting secure value secret: %w", err)
|
||||
}
|
||||
|
||||
externalID, err := keeper.Store(ctx, keeperCfg, message.Namespace, string(rawSecret))
|
||||
if err != nil {
|
||||
return fmt.Errorf("storing secret: message=%+v %w", message, err)
|
||||
}
|
||||
|
||||
if err := w.secureValueMetadataStorage.SetExternalID(ctx, xkube.Namespace(message.Namespace), message.Name, externalID); err != nil {
|
||||
return fmt.Errorf("setting secret metadata externalID: externalID=%+v message=%+v %w", externalID, message, err)
|
||||
}
|
||||
|
||||
// Setting the status to Succeeded must be the last action
|
||||
// since it acts as a fence to clients.
|
||||
if err := w.secureValueMetadataStorage.SetStatus(ctx, xkube.Namespace(message.Namespace), message.Name, secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseSucceeded}); err != nil {
|
||||
return fmt.Errorf("setting secret metadata status to Succeeded: message=%+v %w", message, err)
|
||||
}
|
||||
|
||||
case contracts.UpdateSecretOutboxMessage:
|
||||
rawSecret, err := w.encryptionManager.Decrypt(ctx, message.Namespace, []byte(message.EncryptedSecret))
|
||||
if err != nil {
|
||||
return fmt.Errorf("decrypting secure value secret: %w", err)
|
||||
}
|
||||
|
||||
if err := keeper.Update(ctx, keeperCfg, message.Namespace, contracts.ExternalID(*message.ExternalID), string(rawSecret)); err != nil {
|
||||
return fmt.Errorf("calling keeper to update secret: %w", err)
|
||||
}
|
||||
|
||||
// Setting the status to Succeeded must be the last action
|
||||
// since it acts as a fence to clients.
|
||||
if err := w.secureValueMetadataStorage.SetStatus(ctx, xkube.Namespace(message.Namespace), message.Name, secretv0alpha1.SecureValueStatus{Phase: secretv0alpha1.SecureValuePhaseSucceeded}); err != nil {
|
||||
return fmt.Errorf("setting secret metadata status to Succeeded: message=%+v", message)
|
||||
}
|
||||
|
||||
case contracts.DeleteSecretOutboxMessage:
|
||||
if err := keeper.Delete(ctx, keeperCfg, message.Namespace, contracts.ExternalID(*message.ExternalID)); err != nil {
|
||||
return fmt.Errorf("calling keeper to delete secret: %w", err)
|
||||
}
|
||||
if err := w.secureValueMetadataStorage.Delete(ctx, xkube.Namespace(message.Namespace), message.Name); err != nil {
|
||||
return fmt.Errorf("deleting secure value metadata: %+w", err)
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unhandled message type: %s", message.Type)
|
||||
}
|
||||
|
||||
// Delete the message from the queue after completing all operations because
|
||||
// if the message is deleted first, the response may be lost,
|
||||
// resulting in an error, but since the message was actually deleted
|
||||
// the worker would never retry.
|
||||
if err := w.outboxQueue.Delete(ctx, message.MessageID); err != nil {
|
||||
return fmt.Errorf("deleting message from outbox queue: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
package worker_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
secretv0alpha1 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/testutils"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/worker"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type fakeKeeperService struct {
|
||||
keeperForConfigFunc func(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error)
|
||||
}
|
||||
|
||||
func newFakeKeeperService(keeperForConfigFunc func(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error)) *fakeKeeperService {
|
||||
return &fakeKeeperService{keeperForConfigFunc: keeperForConfigFunc}
|
||||
}
|
||||
|
||||
func (s *fakeKeeperService) KeeperForConfig(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error) {
|
||||
return s.keeperForConfigFunc(cfg)
|
||||
}
|
||||
|
||||
func TestProcessMessage(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("secure value metadata status is set to Failed when processing a message fails too many times", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Given a worker that will attempt to process a message N times
|
||||
workerCfg := worker.Config{
|
||||
BatchSize: 10,
|
||||
ReceiveTimeout: 1 * time.Second,
|
||||
PollingInterval: time.Millisecond,
|
||||
MaxMessageProcessingAttempts: 2,
|
||||
}
|
||||
|
||||
// And an error that keeps happening
|
||||
keeperService := newFakeKeeperService(func(cfg secretv0alpha1.KeeperConfig) (contracts.Keeper, error) {
|
||||
return nil, fmt.Errorf("oops")
|
||||
})
|
||||
|
||||
sut := testutils.Setup(t, testutils.WithWorkerConfig(workerCfg), testutils.WithKeeperService(keeperService))
|
||||
ctx := context.Background()
|
||||
|
||||
// Queue a create secure value operation
|
||||
sv, err := sut.CreateSv(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
for range workerCfg.MaxMessageProcessingAttempts + 1 {
|
||||
// The secure value status should be Pending while the worker is trying to process the message
|
||||
sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhasePending, sv.Status.Phase)
|
||||
|
||||
// Worker tries to process messages
|
||||
_ = sut.Worker.ReceiveAndProcessMessages(ctx)
|
||||
}
|
||||
|
||||
// After the worker fails to process a message too many times,
|
||||
// the secure value status is changed to Failed
|
||||
sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhaseFailed, sv.Status.Phase)
|
||||
|
||||
messages, err := sut.OutboxQueue.ReceiveN(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, messages)
|
||||
})
|
||||
|
||||
t.Run("create sv: secure value metadata status is set to Succeeded when message is processed successfully", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// Queue a create secure value operation
|
||||
sv, err := sut.CreateSv(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Worker receives and processes the message
|
||||
require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx))
|
||||
|
||||
// and sets the secure value status to Succeeded
|
||||
sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, sv.Status.Phase)
|
||||
|
||||
messages, err := sut.OutboxQueue.ReceiveN(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, messages)
|
||||
})
|
||||
|
||||
t.Run("update sv: secure value metadata status is set to Succeeded when message is processed successfully", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// Queue a create secure value operation
|
||||
sv, err := sut.CreateSv(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Worker receives and processes the message
|
||||
require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx))
|
||||
|
||||
// and sets the secure value status to Succeeded
|
||||
sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, sv.Status.Phase)
|
||||
|
||||
sv.Spec.Description = "desc2"
|
||||
sv.Spec.Value = secretv0alpha1.NewExposedSecureValue("v2")
|
||||
|
||||
// Queue an update operation
|
||||
sv, err = sut.UpdateSv(ctx, sv)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhasePending, sv.Status.Phase)
|
||||
|
||||
// Worker receives and processes the message
|
||||
require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx))
|
||||
updatedSv, err := sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, updatedSv.Status.Phase)
|
||||
require.Equal(t, sv.Spec.Description, updatedSv.Spec.Description)
|
||||
|
||||
messages, err := sut.OutboxQueue.ReceiveN(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, messages)
|
||||
})
|
||||
|
||||
t.Run("delete sv: secure value metadata is deleted", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// Queue a create secure value operation
|
||||
sv, err := sut.CreateSv(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Worker receives and processes the message
|
||||
require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx))
|
||||
|
||||
// and sets the secure value status to Succeeded
|
||||
sv, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhaseSucceeded, sv.Status.Phase)
|
||||
|
||||
// Queue a delete operation
|
||||
updatedSv, err := sut.DeleteSv(ctx, sv.Namespace, sv.Name)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secretv0alpha1.SecureValuePhasePending, updatedSv.Status.Phase)
|
||||
|
||||
// Worker receives and processes the message
|
||||
require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx))
|
||||
|
||||
// The secure value has been deleted
|
||||
_, err = sut.SecureValueMetadataStorage.Read(ctx, xkube.Namespace(sv.Namespace), sv.Name, contracts.ReadOpts{})
|
||||
require.ErrorIs(t, err, contracts.ErrSecureValueNotFound)
|
||||
|
||||
messages, err := sut.OutboxQueue.ReceiveN(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, messages)
|
||||
})
|
||||
|
||||
t.Run("when creating a secure value, the secret is encrypted before it is added to the outbox queue", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// Queue a create secure value operation
|
||||
var secret string
|
||||
_, err := sut.CreateSv(ctx, func(cfg *testutils.CreateSvConfig) {
|
||||
secret = string(cfg.Sv.Spec.Value)
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
messages, err := sut.OutboxQueue.ReceiveN(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(messages))
|
||||
|
||||
encryptedSecret := messages[0].EncryptedSecret
|
||||
require.NotEmpty(t, secret)
|
||||
require.NotEmpty(t, encryptedSecret)
|
||||
require.NotEqual(t, secret, encryptedSecret)
|
||||
})
|
||||
|
||||
t.Run("when updating a secure value, the secret is encrypted before it is added to the outbox queue", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// Queue a create secure value operation
|
||||
sv, err := sut.CreateSv(ctx)
|
||||
require.NoError(t, err)
|
||||
sv.Spec.Value = secretv0alpha1.NewExposedSecureValue("v2")
|
||||
|
||||
require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx))
|
||||
|
||||
newValue := "v2"
|
||||
sv.Spec.Value = secretv0alpha1.NewExposedSecureValue(newValue)
|
||||
|
||||
// Queue an update secure value operation
|
||||
_, err = sut.UpdateSv(ctx, sv)
|
||||
require.NoError(t, err)
|
||||
|
||||
messages, err := sut.OutboxQueue.ReceiveN(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(messages))
|
||||
|
||||
encryptedSecret := messages[0].EncryptedSecret
|
||||
require.NotEmpty(t, encryptedSecret)
|
||||
require.NotEqual(t, newValue, encryptedSecret)
|
||||
})
|
||||
|
||||
t.Run("when deleting a secure value, no value is added to the outbox message", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
sut := testutils.Setup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// Queue a create secure value operation
|
||||
sv, err := sut.CreateSv(ctx)
|
||||
require.NoError(t, err)
|
||||
sv.Spec.Value = secretv0alpha1.NewExposedSecureValue("v2")
|
||||
|
||||
require.NoError(t, sut.Worker.ReceiveAndProcessMessages(ctx))
|
||||
|
||||
// Queue a delete secure value operation
|
||||
_, err = sut.DeleteSv(ctx, sv.Namespace, sv.Name)
|
||||
require.NoError(t, err)
|
||||
|
||||
messages, err := sut.OutboxQueue.ReceiveN(ctx, 100)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(messages))
|
||||
require.Empty(t, messages[0].EncryptedSecret)
|
||||
})
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats/statscollector"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
apiregistry "github.com/grafana/grafana/pkg/registry/apis"
|
||||
secretworker "github.com/grafana/grafana/pkg/registry/apis/secret/worker"
|
||||
appregistry "github.com/grafana/grafana/pkg/registry/apps"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/dualwrite"
|
||||
"github.com/grafana/grafana/pkg/services/anonymous/anonimpl"
|
||||
@@ -71,7 +70,6 @@ func ProvideBackgroundServiceRegistry(
|
||||
appRegistry *appregistry.Service,
|
||||
pluginDashboardUpdater *plugindashboardsservice.DashboardUpdater,
|
||||
dashboardServiceImpl *service.DashboardServiceImpl,
|
||||
secretManagerWorker *secretworker.Worker,
|
||||
// Need to make sure these are initialized, is there a better place to put them?
|
||||
_ dashboardsnapshots.Service,
|
||||
_ serviceaccounts.Service,
|
||||
@@ -119,7 +117,6 @@ func ProvideBackgroundServiceRegistry(
|
||||
appRegistry,
|
||||
pluginDashboardUpdater,
|
||||
dashboardServiceImpl,
|
||||
secretManagerWorker,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/services/authz"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
@@ -39,6 +40,7 @@ func NewModule(opts Options,
|
||||
indexMetrics *resource.BleveIndexMetrics,
|
||||
reg prometheus.Registerer,
|
||||
promGatherer prometheus.Gatherer,
|
||||
tracer tracing.Tracer, // Ensures tracing is initialized
|
||||
license licensing.Licensing,
|
||||
) (*ModuleServer, error) {
|
||||
s, err := newModuleServer(opts, apiOpts, features, cfg, storageMetrics, indexMetrics, reg, promGatherer, license)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
claims "github.com/grafana/authlib/types"
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
|
||||
@@ -321,7 +322,9 @@ func initModuleServerForTest(
|
||||
opts Options,
|
||||
apiOpts api.ServerOptions,
|
||||
) testModuleServer {
|
||||
ms, err := NewModule(opts, apiOpts, featuremgmt.WithFeatures(featuremgmt.FlagUnifiedStorageSearch), cfg, nil, nil, prometheus.NewRegistry(), prometheus.DefaultGatherer, nil)
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
|
||||
ms, err := NewModule(opts, apiOpts, featuremgmt.WithFeatures(featuremgmt.FlagUnifiedStorageSearch), cfg, nil, nil, prometheus.NewRegistry(), prometheus.DefaultGatherer, tracer, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
conn, err := grpc.NewClient(cfg.GRPCServer.Address,
|
||||
|
||||
@@ -46,7 +46,6 @@ import (
|
||||
gsmEncryption "github.com/grafana/grafana/pkg/registry/apis/secret/encryption"
|
||||
encryptionManager "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager"
|
||||
secretsecurevalueservice "github.com/grafana/grafana/pkg/registry/apis/secret/service"
|
||||
secretworker "github.com/grafana/grafana/pkg/registry/apis/secret/worker"
|
||||
appregistry "github.com/grafana/grafana/pkg/registry/apps"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
@@ -431,15 +430,12 @@ var wireBasicSet = wire.NewSet(
|
||||
secretdecrypt.ProvideDecryptAllowList,
|
||||
secretencryption.ProvideDataKeyStorage,
|
||||
secretencryption.ProvideEncryptedValueStorage,
|
||||
secretmetadata.ProvideOutboxQueue,
|
||||
secretsecurevalueservice.ProvideSecureValueService,
|
||||
secretmigrator.NewWithEngine,
|
||||
secretdatabase.ProvideDatabase,
|
||||
wire.Bind(new(secretcontracts.Database), new(*secretdatabase.Database)),
|
||||
encryptionManager.ProvideEncryptionManager,
|
||||
gsmEncryption.ProvideThirdPartyProviderMap,
|
||||
secretworker.ProvideWorkerConfig,
|
||||
secretworker.NewWorker,
|
||||
// Unified storage
|
||||
resource.ProvideStorageMetrics,
|
||||
resource.ProvideIndexMetrics,
|
||||
|
||||
+15
-73
File diff suppressed because one or more lines are too long
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/google/wire"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
@@ -165,6 +166,10 @@ var wireExtsBaseCLISet = wire.NewSet(
|
||||
var wireExtsModuleServerSet = wire.NewSet(
|
||||
NewModule,
|
||||
wireExtsBaseCLISet,
|
||||
// Tracing
|
||||
tracing.ProvideTracingConfig,
|
||||
tracing.ProvideService,
|
||||
wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)),
|
||||
// Unified storage
|
||||
resource.ProvideStorageMetrics,
|
||||
resource.ProvideIndexMetrics,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.43.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package actest
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// Code generated by mockery v2.12.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package annotations
|
||||
|
||||
import (
|
||||
context "context"
|
||||
testing "testing"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
@@ -18,6 +17,10 @@ type FakeAnnotationsRepo struct {
|
||||
func (_m *FakeAnnotationsRepo) Delete(ctx context.Context, params *DeleteParams) error {
|
||||
ret := _m.Called(ctx, params)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Delete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *DeleteParams) error); ok {
|
||||
r0 = rf(ctx, params)
|
||||
@@ -32,7 +35,15 @@ func (_m *FakeAnnotationsRepo) Delete(ctx context.Context, params *DeleteParams)
|
||||
func (_m *FakeAnnotationsRepo) Find(ctx context.Context, query *ItemQuery) ([]*ItemDTO, error) {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Find")
|
||||
}
|
||||
|
||||
var r0 []*ItemDTO
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *ItemQuery) ([]*ItemDTO, error)); ok {
|
||||
return rf(ctx, query)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *ItemQuery) []*ItemDTO); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
@@ -41,7 +52,6 @@ func (_m *FakeAnnotationsRepo) Find(ctx context.Context, query *ItemQuery) ([]*I
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *ItemQuery) error); ok {
|
||||
r1 = rf(ctx, query)
|
||||
} else {
|
||||
@@ -55,14 +65,21 @@ func (_m *FakeAnnotationsRepo) Find(ctx context.Context, query *ItemQuery) ([]*I
|
||||
func (_m *FakeAnnotationsRepo) FindTags(ctx context.Context, query *TagsQuery) (FindTagsResult, error) {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for FindTags")
|
||||
}
|
||||
|
||||
var r0 FindTagsResult
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *TagsQuery) (FindTagsResult, error)); ok {
|
||||
return rf(ctx, query)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *TagsQuery) FindTagsResult); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Get(0).(FindTagsResult)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *TagsQuery) error); ok {
|
||||
r1 = rf(ctx, query)
|
||||
} else {
|
||||
@@ -76,6 +93,10 @@ func (_m *FakeAnnotationsRepo) FindTags(ctx context.Context, query *TagsQuery) (
|
||||
func (_m *FakeAnnotationsRepo) Save(ctx context.Context, item *Item) error {
|
||||
ret := _m.Called(ctx, item)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Save")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *Item) error); ok {
|
||||
r0 = rf(ctx, item)
|
||||
@@ -90,6 +111,10 @@ func (_m *FakeAnnotationsRepo) Save(ctx context.Context, item *Item) error {
|
||||
func (_m *FakeAnnotationsRepo) SaveMany(ctx context.Context, items []Item) error {
|
||||
ret := _m.Called(ctx, items)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SaveMany")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, []Item) error); ok {
|
||||
r0 = rf(ctx, items)
|
||||
@@ -104,6 +129,10 @@ func (_m *FakeAnnotationsRepo) SaveMany(ctx context.Context, items []Item) error
|
||||
func (_m *FakeAnnotationsRepo) Update(ctx context.Context, item *Item) error {
|
||||
ret := _m.Called(ctx, item)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Update")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *Item) error); ok {
|
||||
r0 = rf(ctx, item)
|
||||
@@ -114,8 +143,12 @@ func (_m *FakeAnnotationsRepo) Update(ctx context.Context, item *Item) error {
|
||||
return r0
|
||||
}
|
||||
|
||||
// NewFakeAnnotationsRepo creates a new instance of FakeAnnotationsRepo. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewFakeAnnotationsRepo(t testing.TB) *FakeAnnotationsRepo {
|
||||
// NewFakeAnnotationsRepo creates a new instance of FakeAnnotationsRepo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewFakeAnnotationsRepo(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *FakeAnnotationsRepo {
|
||||
mock := &FakeAnnotationsRepo{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.42.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package authtest
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.42.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package authtest
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.42.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package idtest
|
||||
|
||||
|
||||
@@ -150,17 +150,19 @@ const (
|
||||
type ItemErrorCode string
|
||||
|
||||
const (
|
||||
ErrDatasourceNameConflict ItemErrorCode = "DATASOURCE_NAME_CONFLICT"
|
||||
ErrDatasourceInvalidURL ItemErrorCode = "DATASOURCE_INVALID_URL"
|
||||
ErrDatasourceAlreadyManaged ItemErrorCode = "DATASOURCE_ALREADY_MANAGED"
|
||||
ErrFolderNameConflict ItemErrorCode = "FOLDER_NAME_CONFLICT"
|
||||
ErrDashboardAlreadyManaged ItemErrorCode = "DASHBOARD_ALREADY_MANAGED"
|
||||
ErrLibraryElementNameConflict ItemErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT"
|
||||
ErrUnsupportedDataType ItemErrorCode = "UNSUPPORTED_DATA_TYPE"
|
||||
ErrResourceConflict ItemErrorCode = "RESOURCE_CONFLICT"
|
||||
ErrUnexpectedStatus ItemErrorCode = "UNEXPECTED_STATUS_CODE"
|
||||
ErrInternalServiceError ItemErrorCode = "INTERNAL_SERVICE_ERROR"
|
||||
ErrGeneric ItemErrorCode = "GENERIC_ERROR"
|
||||
ErrAlertRulesQuotaReached ItemErrorCode = "ALERT_RULES_QUOTA_REACHED"
|
||||
ErrAlertRulesGroupQuotaReached ItemErrorCode = "ALERT_RULES_GROUP_QUOTA_REACHED"
|
||||
ErrDatasourceNameConflict ItemErrorCode = "DATASOURCE_NAME_CONFLICT"
|
||||
ErrDatasourceInvalidURL ItemErrorCode = "DATASOURCE_INVALID_URL"
|
||||
ErrDatasourceAlreadyManaged ItemErrorCode = "DATASOURCE_ALREADY_MANAGED"
|
||||
ErrFolderNameConflict ItemErrorCode = "FOLDER_NAME_CONFLICT"
|
||||
ErrDashboardAlreadyManaged ItemErrorCode = "DASHBOARD_ALREADY_MANAGED"
|
||||
ErrLibraryElementNameConflict ItemErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT"
|
||||
ErrUnsupportedDataType ItemErrorCode = "UNSUPPORTED_DATA_TYPE"
|
||||
ErrResourceConflict ItemErrorCode = "RESOURCE_CONFLICT"
|
||||
ErrUnexpectedStatus ItemErrorCode = "UNEXPECTED_STATUS_CODE"
|
||||
ErrInternalServiceError ItemErrorCode = "INTERNAL_SERVICE_ERROR"
|
||||
ErrGeneric ItemErrorCode = "GENERIC_ERROR"
|
||||
)
|
||||
|
||||
// swagger:parameters getCloudMigrationRun
|
||||
|
||||
@@ -110,17 +110,19 @@ const (
|
||||
type ResourceErrorCode string
|
||||
|
||||
const (
|
||||
ErrDatasourceNameConflict ResourceErrorCode = "DATASOURCE_NAME_CONFLICT"
|
||||
ErrDatasourceInvalidURL ResourceErrorCode = "DATASOURCE_INVALID_URL"
|
||||
ErrDatasourceAlreadyManaged ResourceErrorCode = "DATASOURCE_ALREADY_MANAGED"
|
||||
ErrFolderNameConflict ResourceErrorCode = "FOLDER_NAME_CONFLICT"
|
||||
ErrDashboardAlreadyManaged ResourceErrorCode = "DASHBOARD_ALREADY_MANAGED"
|
||||
ErrLibraryElementNameConflict ResourceErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT"
|
||||
ErrUnsupportedDataType ResourceErrorCode = "UNSUPPORTED_DATA_TYPE"
|
||||
ErrResourceConflict ResourceErrorCode = "RESOURCE_CONFLICT"
|
||||
ErrUnexpectedStatus ResourceErrorCode = "UNEXPECTED_STATUS_CODE"
|
||||
ErrInternalServiceError ResourceErrorCode = "INTERNAL_SERVICE_ERROR"
|
||||
ErrGeneric ResourceErrorCode = "GENERIC_ERROR"
|
||||
ErrAlertRulesQuotaReached ResourceErrorCode = "ALERT_RULES_QUOTA_REACHED"
|
||||
ErrAlertRulesGroupQuotaReached ResourceErrorCode = "ALERT_RULES_GROUP_QUOTA_REACHED"
|
||||
ErrDatasourceNameConflict ResourceErrorCode = "DATASOURCE_NAME_CONFLICT"
|
||||
ErrDatasourceInvalidURL ResourceErrorCode = "DATASOURCE_INVALID_URL"
|
||||
ErrDatasourceAlreadyManaged ResourceErrorCode = "DATASOURCE_ALREADY_MANAGED"
|
||||
ErrFolderNameConflict ResourceErrorCode = "FOLDER_NAME_CONFLICT"
|
||||
ErrDashboardAlreadyManaged ResourceErrorCode = "DASHBOARD_ALREADY_MANAGED"
|
||||
ErrLibraryElementNameConflict ResourceErrorCode = "LIBRARY_ELEMENT_NAME_CONFLICT"
|
||||
ErrUnsupportedDataType ResourceErrorCode = "UNSUPPORTED_DATA_TYPE"
|
||||
ErrResourceConflict ResourceErrorCode = "RESOURCE_CONFLICT"
|
||||
ErrUnexpectedStatus ResourceErrorCode = "UNEXPECTED_STATUS_CODE"
|
||||
ErrInternalServiceError ResourceErrorCode = "INTERNAL_SERVICE_ERROR"
|
||||
ErrGeneric ResourceErrorCode = "GENERIC_ERROR"
|
||||
)
|
||||
|
||||
type SnapshotResourceStats struct {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package dashboards
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package dashboards
|
||||
|
||||
@@ -94,36 +94,6 @@ func (_m *FakeDashboardService) CountDashboardsInOrg(ctx context.Context, orgID
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID
|
||||
func (_m *FakeDashboardService) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) {
|
||||
ret := _m.Called(ctx, libraryPanelUID, orgID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetDashboardsByLibraryPanelUID")
|
||||
}
|
||||
|
||||
var r0 []*DashboardRef
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok {
|
||||
return rf(ctx, libraryPanelUID, orgID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok {
|
||||
r0 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*DashboardRef)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
|
||||
r1 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CountInFolders provides a mock function with given fields: ctx, orgID, folderUIDs, user
|
||||
func (_m *FakeDashboardService) CountInFolders(ctx context.Context, orgID int64, folderUIDs []string, user identity.Requester) (int64, error) {
|
||||
ret := _m.Called(ctx, orgID, folderUIDs, user)
|
||||
@@ -368,6 +338,36 @@ func (_m *FakeDashboardService) GetDashboards(ctx context.Context, query *GetDas
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID
|
||||
func (_m *FakeDashboardService) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) {
|
||||
ret := _m.Called(ctx, libraryPanelUID, orgID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetDashboardsByLibraryPanelUID")
|
||||
}
|
||||
|
||||
var r0 []*DashboardRef
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok {
|
||||
return rf(ctx, libraryPanelUID, orgID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok {
|
||||
r0 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*DashboardRef)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
|
||||
r1 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ImportDashboard provides a mock function with given fields: ctx, dto
|
||||
func (_m *FakeDashboardService) ImportDashboard(ctx context.Context, dto *SaveDashboardDTO) (*Dashboard, error) {
|
||||
ret := _m.Called(ctx, dto)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package dashboards
|
||||
|
||||
@@ -370,6 +370,36 @@ func (_m *FakeDashboardStore) GetDashboards(ctx context.Context, query *GetDashb
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID
|
||||
func (_m *FakeDashboardStore) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) {
|
||||
ret := _m.Called(ctx, libraryPanelUID, orgID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetDashboardsByLibraryPanelUID")
|
||||
}
|
||||
|
||||
var r0 []*DashboardRef
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok {
|
||||
return rf(ctx, libraryPanelUID, orgID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok {
|
||||
r0 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*DashboardRef)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
|
||||
r1 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetDashboardsByPluginID provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardStore) GetDashboardsByPluginID(ctx context.Context, query *GetDashboardsByPluginIDQuery) ([]*Dashboard, error) {
|
||||
ret := _m.Called(ctx, query)
|
||||
@@ -628,36 +658,6 @@ func (_m *FakeDashboardStore) UnprovisionDashboard(ctx context.Context, id int64
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetDashboardsByLibraryPanelUID provides a mock function with given fields: ctx, libraryPanelUID, orgID
|
||||
func (_m *FakeDashboardStore) GetDashboardsByLibraryPanelUID(ctx context.Context, libraryPanelUID string, orgID int64) ([]*DashboardRef, error) {
|
||||
ret := _m.Called(ctx, libraryPanelUID, orgID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetDashboardsByLibraryPanelUID")
|
||||
}
|
||||
|
||||
var r0 []*DashboardRef
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) ([]*DashboardRef, error)); ok {
|
||||
return rf(ctx, libraryPanelUID, orgID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, int64) []*DashboardRef); ok {
|
||||
r0 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*DashboardRef)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
|
||||
r1 = rf(ctx, libraryPanelUID, orgID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ValidateDashboardBeforeSave provides a mock function with given fields: ctx, dashboard, overwrite
|
||||
func (_m *FakeDashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashboard *Dashboard, overwrite bool) (bool, error) {
|
||||
ret := _m.Called(ctx, dashboard, overwrite)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.34.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package dashboardsnapshots
|
||||
|
||||
@@ -17,6 +17,10 @@ type MockService struct {
|
||||
func (_m *MockService) CreateDashboardSnapshot(_a0 context.Context, _a1 *CreateDashboardSnapshotCommand) (*DashboardSnapshot, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateDashboardSnapshot")
|
||||
}
|
||||
|
||||
var r0 *DashboardSnapshot
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *CreateDashboardSnapshotCommand) (*DashboardSnapshot, error)); ok {
|
||||
@@ -43,6 +47,10 @@ func (_m *MockService) CreateDashboardSnapshot(_a0 context.Context, _a1 *CreateD
|
||||
func (_m *MockService) DeleteDashboardSnapshot(_a0 context.Context, _a1 *DeleteDashboardSnapshotCommand) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteDashboardSnapshot")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *DeleteDashboardSnapshotCommand) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
@@ -57,6 +65,10 @@ func (_m *MockService) DeleteDashboardSnapshot(_a0 context.Context, _a1 *DeleteD
|
||||
func (_m *MockService) DeleteExpiredSnapshots(_a0 context.Context, _a1 *DeleteExpiredSnapshotsCommand) error {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteExpiredSnapshots")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *DeleteExpiredSnapshotsCommand) error); ok {
|
||||
r0 = rf(_a0, _a1)
|
||||
@@ -71,6 +83,10 @@ func (_m *MockService) DeleteExpiredSnapshots(_a0 context.Context, _a1 *DeleteEx
|
||||
func (_m *MockService) GetDashboardSnapshot(_a0 context.Context, _a1 *GetDashboardSnapshotQuery) (*DashboardSnapshot, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetDashboardSnapshot")
|
||||
}
|
||||
|
||||
var r0 *DashboardSnapshot
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardSnapshotQuery) (*DashboardSnapshot, error)); ok {
|
||||
@@ -97,6 +113,10 @@ func (_m *MockService) GetDashboardSnapshot(_a0 context.Context, _a1 *GetDashboa
|
||||
func (_m *MockService) SearchDashboardSnapshots(_a0 context.Context, _a1 *GetDashboardSnapshotsQuery) (DashboardSnapshotsList, error) {
|
||||
ret := _m.Called(_a0, _a1)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SearchDashboardSnapshots")
|
||||
}
|
||||
|
||||
var r0 DashboardSnapshotsList
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardSnapshotsQuery) (DashboardSnapshotsList, error)); ok {
|
||||
@@ -123,6 +143,10 @@ func (_m *MockService) SearchDashboardSnapshots(_a0 context.Context, _a1 *GetDas
|
||||
func (_m *MockService) ValidateDashboardExists(_a0 context.Context, _a1 int64, _a2 string) error {
|
||||
ret := _m.Called(_a0, _a1, _a2)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ValidateDashboardExists")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
|
||||
r0 = rf(_a0, _a1, _a2)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.35.2. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package tests
|
||||
|
||||
@@ -18,6 +18,10 @@ type ExternalServiceRegistryMock struct {
|
||||
func (_m *ExternalServiceRegistryMock) GetExternalServiceNames(ctx context.Context) ([]string, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetExternalServiceNames")
|
||||
}
|
||||
|
||||
var r0 []string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) ([]string, error)); ok {
|
||||
@@ -44,6 +48,10 @@ func (_m *ExternalServiceRegistryMock) GetExternalServiceNames(ctx context.Conte
|
||||
func (_m *ExternalServiceRegistryMock) HasExternalService(ctx context.Context, name string) (bool, error) {
|
||||
ret := _m.Called(ctx, name)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for HasExternalService")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (bool, error)); ok {
|
||||
@@ -68,6 +76,10 @@ func (_m *ExternalServiceRegistryMock) HasExternalService(ctx context.Context, n
|
||||
func (_m *ExternalServiceRegistryMock) RemoveExternalService(ctx context.Context, name string) error {
|
||||
ret := _m.Called(ctx, name)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveExternalService")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, name)
|
||||
@@ -82,6 +94,10 @@ func (_m *ExternalServiceRegistryMock) RemoveExternalService(ctx context.Context
|
||||
func (_m *ExternalServiceRegistryMock) SaveExternalService(ctx context.Context, cmd *extsvcauth.ExternalServiceRegistration) (*extsvcauth.ExternalService, error) {
|
||||
ret := _m.Called(ctx, cmd)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SaveExternalService")
|
||||
}
|
||||
|
||||
var r0 *extsvcauth.ExternalService
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *extsvcauth.ExternalServiceRegistration) (*extsvcauth.ExternalService, error)); ok {
|
||||
|
||||
@@ -1714,7 +1714,7 @@ var (
|
||||
Description: "Use fixed-width numbers globally in the UI",
|
||||
Stage: FeatureStageGeneralAvailability,
|
||||
Owner: grafanaFrontendPlatformSquad,
|
||||
Expression: "true",
|
||||
Expression: "false",
|
||||
},
|
||||
{
|
||||
Name: "newInfluxDSConfigPageDesign",
|
||||
|
||||
@@ -2943,17 +2943,17 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "tabularNumbers",
|
||||
"resourceVersion": "1750754828442",
|
||||
"resourceVersion": "1752078306230",
|
||||
"creationTimestamp": "2025-06-24T11:52:03Z",
|
||||
"annotations": {
|
||||
"grafana.app/updatedTimestamp": "2025-06-24 08:47:08.442537461 +0000 UTC"
|
||||
"grafana.app/updatedTimestamp": "2025-07-09 16:25:06.230922635 +0000 UTC"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"description": "Use fixed-width numbers globally in the UI",
|
||||
"stage": "GA",
|
||||
"codeowner": "@grafana/grafana-frontend-platform",
|
||||
"expression": "true"
|
||||
"expression": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.32.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package foldertest
|
||||
|
||||
@@ -14,10 +14,44 @@ type FakeFolderStore struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: ctx, q
|
||||
func (_m *FakeFolderStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, q)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Get")
|
||||
}
|
||||
|
||||
var r0 *folder.Folder
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) (*folder.Folder, error)); ok {
|
||||
return rf(ctx, q)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) *folder.Folder); ok {
|
||||
r0 = rf(ctx, q)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, folder.GetFolderQuery) error); ok {
|
||||
r1 = rf(ctx, q)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetFolderByID provides a mock function with given fields: ctx, orgID, id
|
||||
func (_m *FakeFolderStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetFolderByID")
|
||||
}
|
||||
|
||||
var r0 *folder.Folder
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, int64) (*folder.Folder, error)); ok {
|
||||
@@ -40,36 +74,14 @@ func (_m *FakeFolderStore) GetFolderByID(ctx context.Context, orgID int64, id in
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeFolderStore) Get(ctx context.Context, query folder.GetFolderQuery) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 *folder.Folder
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) (*folder.Folder, error)); ok {
|
||||
return rf(ctx, query)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) *folder.Folder); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, folder.GetFolderQuery) error); ok {
|
||||
r1 = rf(ctx, query)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetFolderByUID provides a mock function with given fields: ctx, orgID, uid
|
||||
func (_m *FakeFolderStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, uid)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetFolderByUID")
|
||||
}
|
||||
|
||||
var r0 *folder.Folder
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*folder.Folder, error)); ok {
|
||||
@@ -96,6 +108,10 @@ func (_m *FakeFolderStore) GetFolderByUID(ctx context.Context, orgID int64, uid
|
||||
func (_m *FakeFolderStore) GetFolders(ctx context.Context, orgID int64, uids []string) (map[string]*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, uids)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetFolders")
|
||||
}
|
||||
|
||||
var r0 map[string]*folder.Folder
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, []string) (map[string]*folder.Folder, error)); ok {
|
||||
@@ -118,29 +134,6 @@ func (_m *FakeFolderStore) GetFolders(ctx context.Context, orgID int64, uids []s
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (_m *FakeFolderStore) CountInOrg(ctx context.Context, orgID int64) (int64, error) {
|
||||
ret := _m.Called(ctx, orgID)
|
||||
|
||||
var r0 int64
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) (int64, error)); ok {
|
||||
return rf(ctx, orgID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) int64); ok {
|
||||
r0 = rf(ctx, orgID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
|
||||
r1 = rf(ctx, orgID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// NewFakeFolderStore creates a new instance of FakeFolderStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewFakeFolderStore(t interface {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"go.opentelemetry.io/otel"
|
||||
|
||||
"github.com/grafana/dskit/services"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -15,6 +16,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var tracer = otel.Tracer("github.com/grafana/grafana/pkg/services/frontend")
|
||||
|
||||
type frontendService struct {
|
||||
*services.BasicService
|
||||
cfg *setting.Cfg
|
||||
|
||||
@@ -79,6 +79,9 @@ func NewIndexProvider(cfg *setting.Cfg, license licensing.Licensing) (*IndexProv
|
||||
}
|
||||
|
||||
func (p *IndexProvider) HandleRequest(writer http.ResponseWriter, request *http.Request) {
|
||||
_, span := tracer.Start(request.Context(), "frontend.index.HandleRequest")
|
||||
defer span.End()
|
||||
|
||||
if request.Method != "GET" {
|
||||
writer.WriteHeader(http.StatusMethodNotAllowed)
|
||||
return
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package eval_mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
time "time"
|
||||
|
||||
backend "github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
eval "github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
time "time"
|
||||
)
|
||||
|
||||
// ConditionEvaluatorMock is an autogenerated mock type for the ConditionEvaluator type
|
||||
@@ -29,7 +31,15 @@ func (_m *ConditionEvaluatorMock) EXPECT() *ConditionEvaluatorMock_Expecter {
|
||||
func (_m *ConditionEvaluatorMock) Evaluate(ctx context.Context, now time.Time) (eval.Results, error) {
|
||||
ret := _m.Called(ctx, now)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Evaluate")
|
||||
}
|
||||
|
||||
var r0 eval.Results
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, time.Time) (eval.Results, error)); ok {
|
||||
return rf(ctx, now)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, time.Time) eval.Results); ok {
|
||||
r0 = rf(ctx, now)
|
||||
} else {
|
||||
@@ -38,7 +48,6 @@ func (_m *ConditionEvaluatorMock) Evaluate(ctx context.Context, now time.Time) (
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, time.Time) error); ok {
|
||||
r1 = rf(ctx, now)
|
||||
} else {
|
||||
@@ -56,7 +65,7 @@ type ConditionEvaluatorMock_Evaluate_Call struct {
|
||||
// Evaluate is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - now time.Time
|
||||
func (_e *ConditionEvaluatorMock_Expecter) Evaluate(ctx any, now any) *ConditionEvaluatorMock_Evaluate_Call {
|
||||
func (_e *ConditionEvaluatorMock_Expecter) Evaluate(ctx interface{}, now interface{}) *ConditionEvaluatorMock_Evaluate_Call {
|
||||
return &ConditionEvaluatorMock_Evaluate_Call{Call: _e.mock.On("Evaluate", ctx, now)}
|
||||
}
|
||||
|
||||
@@ -72,11 +81,24 @@ func (_c *ConditionEvaluatorMock_Evaluate_Call) Return(_a0 eval.Results, _a1 err
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *ConditionEvaluatorMock_Evaluate_Call) RunAndReturn(run func(context.Context, time.Time) (eval.Results, error)) *ConditionEvaluatorMock_Evaluate_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// EvaluateRaw provides a mock function with given fields: ctx, now
|
||||
func (_m *ConditionEvaluatorMock) EvaluateRaw(ctx context.Context, now time.Time) (*backend.QueryDataResponse, error) {
|
||||
ret := _m.Called(ctx, now)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for EvaluateRaw")
|
||||
}
|
||||
|
||||
var r0 *backend.QueryDataResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, time.Time) (*backend.QueryDataResponse, error)); ok {
|
||||
return rf(ctx, now)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, time.Time) *backend.QueryDataResponse); ok {
|
||||
r0 = rf(ctx, now)
|
||||
} else {
|
||||
@@ -85,7 +107,6 @@ func (_m *ConditionEvaluatorMock) EvaluateRaw(ctx context.Context, now time.Time
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, time.Time) error); ok {
|
||||
r1 = rf(ctx, now)
|
||||
} else {
|
||||
@@ -103,7 +124,7 @@ type ConditionEvaluatorMock_EvaluateRaw_Call struct {
|
||||
// EvaluateRaw is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - now time.Time
|
||||
func (_e *ConditionEvaluatorMock_Expecter) EvaluateRaw(ctx any, now any) *ConditionEvaluatorMock_EvaluateRaw_Call {
|
||||
func (_e *ConditionEvaluatorMock_Expecter) EvaluateRaw(ctx interface{}, now interface{}) *ConditionEvaluatorMock_EvaluateRaw_Call {
|
||||
return &ConditionEvaluatorMock_EvaluateRaw_Call{Call: _e.mock.On("EvaluateRaw", ctx, now)}
|
||||
}
|
||||
|
||||
@@ -119,13 +140,17 @@ func (_c *ConditionEvaluatorMock_EvaluateRaw_Call) Return(resp *backend.QueryDat
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewConditionEvaluatorMock interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
func (_c *ConditionEvaluatorMock_EvaluateRaw_Call) RunAndReturn(run func(context.Context, time.Time) (*backend.QueryDataResponse, error)) *ConditionEvaluatorMock_EvaluateRaw_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewConditionEvaluatorMock creates a new instance of ConditionEvaluatorMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewConditionEvaluatorMock(t mockConstructorTestingTNewConditionEvaluatorMock) *ConditionEvaluatorMock {
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewConditionEvaluatorMock(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *ConditionEvaluatorMock {
|
||||
mock := &ConditionEvaluatorMock{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.44.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package alertmanager_mock
|
||||
|
||||
@@ -585,7 +585,7 @@ func (_c *AlertmanagerMock_PutAlerts_Call) RunAndReturn(run func(context.Context
|
||||
return _c
|
||||
}
|
||||
|
||||
// Ready provides a mock function with given fields:
|
||||
// Ready provides a mock function with no fields
|
||||
func (_m *AlertmanagerMock) Ready() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
@@ -781,7 +781,7 @@ func (_c *AlertmanagerMock_SilenceState_Call) RunAndReturn(run func(context.Cont
|
||||
return _c
|
||||
}
|
||||
|
||||
// StopAndWait provides a mock function with given fields:
|
||||
// StopAndWait provides a mock function with no fields
|
||||
func (_m *AlertmanagerMock) StopAndWait() {
|
||||
_m.Called()
|
||||
}
|
||||
@@ -809,7 +809,7 @@ func (_c *AlertmanagerMock_StopAndWait_Call) Return() *AlertmanagerMock_StopAndW
|
||||
}
|
||||
|
||||
func (_c *AlertmanagerMock_StopAndWait_Call) RunAndReturn(run func()) *AlertmanagerMock_StopAndWait_Call {
|
||||
_c.Call.Return(run)
|
||||
_c.Run(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.44.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package legacy_storage
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.34.2. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package provisioning
|
||||
|
||||
@@ -26,6 +26,10 @@ func (_m *MockProvisioningStore) EXPECT() *MockProvisioningStore_Expecter {
|
||||
func (_m *MockProvisioningStore) DeleteProvenance(ctx context.Context, o models.Provisionable, org int64) error {
|
||||
ret := _m.Called(ctx, o, org)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteProvenance")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Provisionable, int64) error); ok {
|
||||
r0 = rf(ctx, o, org)
|
||||
@@ -70,6 +74,10 @@ func (_c *MockProvisioningStore_DeleteProvenance_Call) RunAndReturn(run func(con
|
||||
func (_m *MockProvisioningStore) GetProvenance(ctx context.Context, o models.Provisionable, org int64) (models.Provenance, error) {
|
||||
ret := _m.Called(ctx, o, org)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetProvenance")
|
||||
}
|
||||
|
||||
var r0 models.Provenance
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Provisionable, int64) (models.Provenance, error)); ok {
|
||||
@@ -124,6 +132,10 @@ func (_c *MockProvisioningStore_GetProvenance_Call) RunAndReturn(run func(contex
|
||||
func (_m *MockProvisioningStore) GetProvenances(ctx context.Context, org int64, resourceType string) (map[string]models.Provenance, error) {
|
||||
ret := _m.Called(ctx, org, resourceType)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetProvenances")
|
||||
}
|
||||
|
||||
var r0 map[string]models.Provenance
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) (map[string]models.Provenance, error)); ok {
|
||||
@@ -180,6 +192,10 @@ func (_c *MockProvisioningStore_GetProvenances_Call) RunAndReturn(run func(conte
|
||||
func (_m *MockProvisioningStore) SetProvenance(ctx context.Context, o models.Provisionable, org int64, p models.Provenance) error {
|
||||
ret := _m.Called(ctx, o, org, p)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SetProvenance")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, models.Provisionable, int64, models.Provenance) error); ok {
|
||||
r0 = rf(ctx, o, org, p)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.34.2. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
||||
|
||||
package provisioning
|
||||
|
||||
@@ -26,6 +26,10 @@ func (_m *MockQuotaChecker) EXPECT() *MockQuotaChecker_Expecter {
|
||||
func (_m *MockQuotaChecker) CheckQuotaReached(ctx context.Context, target quota.TargetSrv, scopeParams *quota.ScopeParameters) (bool, error) {
|
||||
ret := _m.Called(ctx, target, scopeParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CheckQuotaReached")
|
||||
}
|
||||
|
||||
var r0 bool
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, quota.TargetSrv, *quota.ScopeParameters) (bool, error)); ok {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user