Zanzana: bump openfga version (#94485)
* Bump openfga * Remove internall sqlite implementation for openfga * Use sqlite implementation from openfga
This commit is contained in:
+12
-12
@@ -23,7 +23,7 @@ require (
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/apache/arrow/go/v15 v15.0.2 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
@@ -53,7 +53,7 @@ require (
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/cel-go v0.20.1 // indirect
|
||||
github.com/google/cel-go v0.21.0 // indirect
|
||||
github.com/google/flatbuffers v24.3.25+incompatible // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
@@ -98,7 +98,7 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // 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.20.3 // indirect
|
||||
github.com/prometheus/client_golang v1.20.4 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
@@ -118,21 +118,21 @@ require (
|
||||
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.14 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.30.0 // indirect
|
||||
go.opentelemetry.io/contrib/samplers/jaegerremote v0.23.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.30.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.29.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
@@ -143,11 +143,11 @@ require (
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
|
||||
gonum.org/v1/gonum v0.14.0 // indirect
|
||||
gonum.org/v1/gonum v0.15.1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/grpc v1.66.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
|
||||
|
||||
+24
-24
@@ -5,8 +5,8 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
|
||||
github.com/apache/arrow/go/v15 v15.0.2 h1:60IliRbiyTWCWjERBCkO1W4Qun9svcYoZrSLcyOsMLE=
|
||||
github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
@@ -106,8 +106,8 @@ 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.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
|
||||
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
|
||||
github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI=
|
||||
github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc=
|
||||
github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI=
|
||||
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
@@ -247,8 +247,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
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.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
|
||||
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
||||
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
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=
|
||||
@@ -342,8 +342,8 @@ go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw=
|
||||
go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok=
|
||||
go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0 h1:sqmsIQ75l6lfZjjpnXXT9DFVtYEDg6CH0/Cn4/3A1Wg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0/go.mod h1:rsg1EO8LXSs2po50PB5CeY/MSVlhghuKBgXlKnqm6ks=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||
@@ -355,16 +355,16 @@ go.opentelemetry.io/contrib/samplers/jaegerremote v0.23.0/go.mod h1:1kbAgQa5lgYC
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
|
||||
@@ -386,8 +386,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
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=
|
||||
@@ -462,8 +462,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk=
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
|
||||
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
|
||||
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
|
||||
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=
|
||||
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=
|
||||
@@ -471,18 +471,18 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 h1:CT2Thj5AuPV9phrYMtzX11k+XkzMGfRAet42PmoTATM=
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988/go.mod h1:7uvplUBj4RjHAxIZ//98LzOvrQ04JBkaixRmCMI29hc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
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.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -39,8 +39,8 @@ require (
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/grpc v1.66.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
@@ -135,10 +135,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
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/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -6,7 +6,7 @@ require (
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/grafana/authlib/claims v0.0.0-20240903121118-16441568af1e
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1
|
||||
github.com/prometheus/client_golang v1.20.3
|
||||
github.com/prometheus/client_golang v1.20.4
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.30.0
|
||||
go.opentelemetry.io/otel v1.30.0
|
||||
@@ -64,16 +64,16 @@ require (
|
||||
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.14 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/net v0.29.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
@@ -82,9 +82,9 @@ require (
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/grpc v1.66.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
+18
-18
@@ -132,8 +132,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
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.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
|
||||
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
||||
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
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=
|
||||
@@ -188,22 +188,22 @@ go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw=
|
||||
go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok=
|
||||
go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.30.0 h1:g8+Y+7lnhH1DB0THjPPthzQ+RlzAntmTz8+TH2sRU0k=
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.30.0/go.mod h1:lRMaD/FjOQJ2yz/MwOHYxP/BTCMFodNW/wuYDkJvdA4=
|
||||
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4=
|
||||
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
|
||||
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
@@ -224,8 +224,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
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=
|
||||
@@ -290,18 +290,18 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 h1:CT2Thj5AuPV9phrYMtzX11k+XkzMGfRAet42PmoTATM=
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988/go.mod h1:7uvplUBj4RjHAxIZ//98LzOvrQ04JBkaixRmCMI29hc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
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.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
+9
-9
@@ -20,7 +20,7 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // @grafana/grafana-release-guild
|
||||
github.com/aws/aws-sdk-go v1.55.5 // @grafana/aws-datasources
|
||||
github.com/blang/semver/v4 v4.0.0 // @grafana/grafana-release-guild
|
||||
github.com/docker/docker v26.0.2+incompatible // @grafana/grafana-release-guild
|
||||
github.com/docker/docker v27.3.1+incompatible // @grafana/grafana-release-guild
|
||||
github.com/drone/drone-cli v1.6.1 // @grafana/grafana-release-guild
|
||||
github.com/gogo/protobuf v1.3.2 // indirect; @grafana/alerting-backend
|
||||
github.com/google/go-cmp v0.6.0 // @grafana/grafana-backend-group
|
||||
@@ -32,9 +32,9 @@ require (
|
||||
github.com/stretchr/testify v1.9.0 // @grafana/grafana-backend-group
|
||||
github.com/urfave/cli v1.22.15 // @grafana/grafana-backend-group
|
||||
github.com/urfave/cli/v2 v2.27.1 // @grafana/grafana-backend-group
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect; @grafana/plugins-platform-backend
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect; @grafana/plugins-platform-backend
|
||||
go.opentelemetry.io/otel v1.30.0 // indirect; @grafana/grafana-backend-group
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 // indirect; @grafana/grafana-backend-group
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 // indirect; @grafana/grafana-backend-group
|
||||
go.opentelemetry.io/otel/trace v1.30.0 // indirect; @grafana/grafana-backend-group
|
||||
golang.org/x/crypto v0.27.0 // indirect; @grafana/grafana-backend-group
|
||||
golang.org/x/mod v0.20.0 // @grafana/grafana-backend-group
|
||||
@@ -45,7 +45,7 @@ require (
|
||||
golang.org/x/time v0.6.0 // indirect; @grafana/grafana-backend-group
|
||||
golang.org/x/tools v0.24.0 // indirect; @grafana/grafana-as-code
|
||||
google.golang.org/api v0.191.0 // @grafana/grafana-backend-group
|
||||
google.golang.org/grpc v1.66.0 // indirect; @grafana/plugins-platform-backend
|
||||
google.golang.org/grpc v1.67.0 // indirect; @grafana/plugins-platform-backend
|
||||
google.golang.org/protobuf v1.34.2 // indirect; @grafana/plugins-platform-backend
|
||||
gopkg.in/yaml.v3 v3.0.1 // @grafana/alerting-backend
|
||||
)
|
||||
@@ -87,8 +87,8 @@ require (
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 // indirect; @grafana/grafana-backend-group
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
@@ -110,13 +110,13 @@ require (
|
||||
github.com/vektah/gqlparser/v2 v2.5.11 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.2.0-alpha // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.2.0-alpha // indirect
|
||||
go.opentelemetry.io/otel/sdk/log v0.2.0-alpha // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
)
|
||||
|
||||
|
||||
+16
-16
@@ -227,8 +227,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
||||
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||
@@ -237,18 +237,18 @@ go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-2024051809000
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88/go.mod h1:JGG8ebaMO5nXOPnvKEl+DiA4MGwFjCbjsxT1WHIEBPY=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.2.0-alpha h1:z2s6Zba+OUyayRv5m1AXWNUTGh57K1iMhy6emU5QT5Y=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.2.0-alpha/go.mod h1:paOXXyUgPW6jYxYkP0pB47H2zHE1fPvMJ4E4G9LHOi0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 h1:JAv0Jwtl01UFiyWZEMiJZBiTlv5A50zNs8lsthXqIio=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0/go.mod h1:QNKLmUEAq2QUbPQUfvw4fmv0bgbK7UlOSFCnXyfvSNc=
|
||||
go.opentelemetry.io/otel/log v0.2.0-alpha h1:ixOPvMzserpqA07SENHvRzkZOsnG0XbPr74hv1AQ+n0=
|
||||
go.opentelemetry.io/otel/log v0.2.0-alpha/go.mod h1:vbFZc65yq4c4ssvXY43y/nIqkNJLxORrqw0L85P59LA=
|
||||
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
|
||||
go.opentelemetry.io/otel/sdk/log v0.2.0-alpha h1:jGTkL/jroJ31jnP6jDl34N/mDOfRGGYZHcHsCM+5kWA=
|
||||
go.opentelemetry.io/otel/sdk/log v0.2.0-alpha/go.mod h1:Hd8Lw9FPGUM3pfY7iGMRvFaC2Nyau4Ajb5WnQ9OdIho=
|
||||
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||
@@ -266,8 +266,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
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=
|
||||
@@ -339,18 +339,18 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988 h1:CT2Thj5AuPV9phrYMtzX11k+XkzMGfRAet42PmoTATM=
|
||||
google.golang.org/genproto v0.0.0-20240812133136-8ffd90a71988/go.mod h1:7uvplUBj4RjHAxIZ//98LzOvrQ04JBkaixRmCMI29hc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
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.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
||||
+10
-10
@@ -7,13 +7,13 @@ require (
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.251.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/prometheus/client_golang v1.20.3
|
||||
github.com/prometheus/client_golang v1.20.4
|
||||
github.com/prometheus/common v0.55.0
|
||||
github.com/prometheus/prometheus v1.8.2-0.20221021121301-51a44e6657c3
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.opentelemetry.io/otel v1.30.0
|
||||
go.opentelemetry.io/otel/trace v1.30.0
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e
|
||||
k8s.io/apimachinery v0.31.1
|
||||
)
|
||||
|
||||
@@ -101,14 +101,14 @@ require (
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/zeebo/xxh3 v1.0.2 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.30.0 // indirect
|
||||
go.opentelemetry.io/contrib/samplers/jaegerremote v0.23.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/goleak v1.3.0 // indirect
|
||||
@@ -119,10 +119,10 @@ require (
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
|
||||
gonum.org/v1/gonum v0.14.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect
|
||||
google.golang.org/grpc v1.66.0 // indirect
|
||||
gonum.org/v1/gonum v0.15.1 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
||||
+20
-20
@@ -199,8 +199,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
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 v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4=
|
||||
github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
||||
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
@@ -262,8 +262,8 @@ github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0 h1:sqmsIQ75l6lfZjjpnXXT9DFVtYEDg6CH0/Cn4/3A1Wg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0/go.mod h1:rsg1EO8LXSs2po50PB5CeY/MSVlhghuKBgXlKnqm6ks=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||
@@ -275,16 +275,16 @@ go.opentelemetry.io/contrib/samplers/jaegerremote v0.23.0/go.mod h1:1kbAgQa5lgYC
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
|
||||
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
|
||||
@@ -297,8 +297,8 @@ go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
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/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
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/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
@@ -349,14 +349,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk=
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
|
||||
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
|
||||
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -4,10 +4,14 @@ import (
|
||||
"context"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/openfga/openfga/pkg/logger"
|
||||
)
|
||||
|
||||
var _ logger.Logger = (*ZanzanaLogger)(nil)
|
||||
|
||||
// ZanzanaLogger is a grafana logger wrapper compatible with OpenFGA logger interface
|
||||
type ZanzanaLogger struct {
|
||||
logger log.Logger
|
||||
@@ -36,6 +40,13 @@ func zapFieldsToArgs(fields []zap.Field) []any {
|
||||
return args
|
||||
}
|
||||
|
||||
// With implements logger.Logger.
|
||||
func (l *ZanzanaLogger) With(fields ...zapcore.Field) logger.Logger {
|
||||
return &ZanzanaLogger{
|
||||
logger: l.logger.New(zapFieldsToArgs(fields)...),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ZanzanaLogger) Debug(msg string, fields ...zap.Field) {
|
||||
l.logger.Debug(msg, zapFieldsToArgs(fields)...)
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package assets
|
||||
|
||||
import "embed"
|
||||
|
||||
// EmbedMigrations within the grafana binary.
|
||||
//
|
||||
//go:embed migrations/*
|
||||
var EmbedMigrations embed.FS
|
||||
|
||||
const SQLiteMigrationDir = "migrations/sqlite"
|
||||
@@ -1,56 +0,0 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE tuple (
|
||||
store CHAR(26) NOT NULL,
|
||||
object_type VARCHAR(128) NOT NULL,
|
||||
object_id VARCHAR(128) NOT NULL,
|
||||
relation VARCHAR(50) NOT NULL,
|
||||
_user VARCHAR(256) NOT NULL,
|
||||
user_type VARCHAR(7) NOT NULL,
|
||||
ulid CHAR(26) NOT NULL,
|
||||
inserted_at TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY (store, object_type, object_id, relation, _user)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_tuple_ulid ON tuple (ulid);
|
||||
|
||||
CREATE TABLE authorization_model (
|
||||
store CHAR(26) NOT NULL,
|
||||
authorization_model_id CHAR(26) NOT NULL,
|
||||
type VARCHAR(256) NOT NULL,
|
||||
type_definition BLOB,
|
||||
PRIMARY KEY (store, authorization_model_id, type)
|
||||
);
|
||||
|
||||
CREATE TABLE store (
|
||||
id CHAR(26) PRIMARY KEY,
|
||||
name VARCHAR(64) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE assertion (
|
||||
store CHAR(26) NOT NULL,
|
||||
authorization_model_id CHAR(26) NOT NULL,
|
||||
assertions BLOB,
|
||||
PRIMARY KEY (store, authorization_model_id)
|
||||
);
|
||||
|
||||
CREATE TABLE changelog (
|
||||
store CHAR(26) NOT NULL,
|
||||
object_type VARCHAR(256) NOT NULL,
|
||||
object_id VARCHAR(256) NOT NULL,
|
||||
relation VARCHAR(50) NOT NULL,
|
||||
_user VARCHAR(512) NOT NULL,
|
||||
operation INTEGER NOT NULL,
|
||||
ulid CHAR(26) NOT NULL,
|
||||
inserted_at TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY (store, ulid, object_type)
|
||||
);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE tuple;
|
||||
DROP TABLE authorization_model;
|
||||
DROP TABLE store;
|
||||
DROP TABLE assertion;
|
||||
DROP TABLE changelog;
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE authorization_model ADD COLUMN schema_version VARCHAR(5) NOT NULL DEFAULT '1.0';
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE authorization_model DROP COLUMN schema_version;
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
-- +goose Up
|
||||
CREATE INDEX idx_reverse_lookup_user on tuple (store, object_type, relation, _user);
|
||||
|
||||
-- +goose Down
|
||||
DROP INDEX idx_reverse_lookup_user on tuple;
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE authorization_model ADD COLUMN serialized_protobuf LONGBLOB;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE authorization_model DROP COLUMN serialized_protobuf;
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE tuple ADD COLUMN condition_name VARCHAR(256);
|
||||
ALTER TABLE tuple ADD COLUMN condition_context LONGBLOB;
|
||||
ALTER TABLE changelog ADD COLUMN condition_name VARCHAR(256);
|
||||
ALTER TABLE changelog ADD COLUMN condition_context LONGBLOB;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE tuple DROP COLUMN condition_name;
|
||||
ALTER TABLE tuple DROP COLUMN condition_context;
|
||||
ALTER TABLE changelog DROP COLUMN condition_name;
|
||||
ALTER TABLE changelog DROP COLUMN condition_context;
|
||||
@@ -15,13 +15,17 @@ import (
|
||||
func Run(cfg *setting.Cfg, typ, connStr string, fs embed.FS, path string) error {
|
||||
engine, err := xorm.NewEngine(typ, connStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse database config: %w", err)
|
||||
return fmt.Errorf("failed to create db engine: %w", err)
|
||||
}
|
||||
|
||||
m := migrator.NewMigrator(engine, cfg)
|
||||
m.AddCreateMigration()
|
||||
|
||||
return RunWithMigrator(m, cfg, fs, path)
|
||||
if err := RunWithMigrator(m, cfg, fs, path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return engine.Close()
|
||||
}
|
||||
|
||||
func RunWithMigrator(m *migrator.Migrator, cfg *setting.Cfg, fs embed.FS, path string) error {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package sqlite
|
||||
|
||||
import "github.com/openfga/openfga/pkg/storage/sqlcommon"
|
||||
|
||||
type Config struct {
|
||||
*sqlcommon.Config
|
||||
QueryRetries int
|
||||
}
|
||||
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
Config: sqlcommon.NewConfig(),
|
||||
QueryRetries: 0,
|
||||
}
|
||||
}
|
||||
@@ -1,821 +0,0 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/collectors"
|
||||
"go.opentelemetry.io/otel"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
// Pull in sqlite driver.
|
||||
"github.com/mattn/go-sqlite3"
|
||||
|
||||
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||
"github.com/openfga/openfga/pkg/logger"
|
||||
"github.com/openfga/openfga/pkg/storage"
|
||||
"github.com/openfga/openfga/pkg/storage/sqlcommon"
|
||||
tupleUtils "github.com/openfga/openfga/pkg/tuple"
|
||||
)
|
||||
|
||||
var tracer = otel.Tracer("openfga/pkg/storage/sqlite")
|
||||
|
||||
// SQLite provides a SQLite based implementation of [storage.OpenFGADatastore].
|
||||
type SQLite struct {
|
||||
stbl sq.StatementBuilderType
|
||||
cfg *Config
|
||||
db *sql.DB
|
||||
dbInfo *sqlcommon.DBInfo
|
||||
sqlTime sq.Sqlizer
|
||||
logger logger.Logger
|
||||
dbStatsCollector prometheus.Collector
|
||||
}
|
||||
|
||||
// Ensures that SQLite implements the OpenFGADatastore interface.
|
||||
var _ storage.OpenFGADatastore = (*SQLite)(nil)
|
||||
|
||||
// New creates a new [SQLite] storage.
|
||||
func New(uri string, cfg *Config) (*SQLite, error) {
|
||||
// Set journal mode and busy timeout pragmas if not specified.
|
||||
query := url.Values{}
|
||||
var err error
|
||||
|
||||
if i := strings.Index(uri, "?"); i != -1 {
|
||||
query, err = url.ParseQuery(uri[i+1:])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing dsn: %w", err)
|
||||
}
|
||||
|
||||
uri = uri[:i]
|
||||
}
|
||||
|
||||
foundJournalMode := false
|
||||
foundBusyTimeout := false
|
||||
for _, val := range query["_pragma"] {
|
||||
if strings.HasPrefix(val, "journal_mode") {
|
||||
foundJournalMode = true
|
||||
} else if strings.HasPrefix(val, "busy_timeout") {
|
||||
foundBusyTimeout = true
|
||||
}
|
||||
}
|
||||
|
||||
if !foundJournalMode {
|
||||
query.Add("_pragma", "journal_mode(WAL)")
|
||||
}
|
||||
if !foundBusyTimeout {
|
||||
query.Add("_pragma", "busy_timeout(500)")
|
||||
}
|
||||
|
||||
uri += "?" + query.Encode()
|
||||
|
||||
db, err := sql.Open("sqlite", uri)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("initialize sqlite connection: %w", err)
|
||||
}
|
||||
|
||||
return NewWithDB(db, cfg)
|
||||
}
|
||||
|
||||
// NewWithDB creates a new [SQLite] storage using provided [*sql.DB]
|
||||
func NewWithDB(db *sql.DB, cfg *Config) (*SQLite, error) {
|
||||
var collector prometheus.Collector
|
||||
if cfg.ExportMetrics {
|
||||
collector = collectors.NewDBStatsCollector(db, "openfga")
|
||||
if err := prometheus.Register(collector); err != nil {
|
||||
return nil, fmt.Errorf("initialize metrics: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
sqlTime := sq.Expr("datetime('subsec')")
|
||||
stbl := sq.StatementBuilder.RunWith(db)
|
||||
dbInfo := sqlcommon.NewDBInfo(db, stbl, sqlTime)
|
||||
|
||||
return &SQLite{
|
||||
cfg: cfg,
|
||||
stbl: stbl,
|
||||
db: db,
|
||||
sqlTime: sqlTime,
|
||||
dbInfo: dbInfo,
|
||||
logger: cfg.Logger,
|
||||
dbStatsCollector: collector,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close see [storage.OpenFGADatastore].Close.
|
||||
func (m *SQLite) Close() {
|
||||
if m.dbStatsCollector != nil {
|
||||
prometheus.Unregister(m.dbStatsCollector)
|
||||
}
|
||||
_ = m.db.Close()
|
||||
}
|
||||
|
||||
// Read see [storage.RelationshipTupleReader].Read.
|
||||
func (m *SQLite) Read(ctx context.Context, store string, tupleKey *openfgav1.TupleKey) (storage.TupleIterator, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.Read")
|
||||
defer span.End()
|
||||
|
||||
return m.read(ctx, store, tupleKey, nil)
|
||||
}
|
||||
|
||||
// ReadPage see [storage.RelationshipTupleReader].ReadPage.
|
||||
func (m *SQLite) ReadPage(
|
||||
ctx context.Context,
|
||||
store string,
|
||||
tupleKey *openfgav1.TupleKey,
|
||||
opts storage.PaginationOptions,
|
||||
) ([]*openfgav1.Tuple, []byte, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadPage")
|
||||
defer span.End()
|
||||
|
||||
iter, err := m.read(ctx, store, tupleKey, &opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer iter.Stop()
|
||||
|
||||
return iter.ToArray(opts)
|
||||
}
|
||||
|
||||
func (m *SQLite) read(ctx context.Context, store string, tupleKey *openfgav1.TupleKey, opts *storage.PaginationOptions) (*sqlcommon.SQLTupleIterator, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.read")
|
||||
defer span.End()
|
||||
|
||||
sb := m.stbl.
|
||||
Select(
|
||||
"store", "object_type", "object_id", "relation", "_user",
|
||||
"condition_name", "condition_context", "ulid", "inserted_at",
|
||||
).
|
||||
From("tuple").
|
||||
Where(sq.Eq{"store": store})
|
||||
if opts != nil {
|
||||
sb = sb.OrderBy("ulid")
|
||||
}
|
||||
objectType, objectID := tupleUtils.SplitObject(tupleKey.GetObject())
|
||||
if objectType != "" {
|
||||
sb = sb.Where(sq.Eq{"object_type": objectType})
|
||||
}
|
||||
if objectID != "" {
|
||||
sb = sb.Where(sq.Eq{"object_id": objectID})
|
||||
}
|
||||
if tupleKey.GetRelation() != "" {
|
||||
sb = sb.Where(sq.Eq{"relation": tupleKey.GetRelation()})
|
||||
}
|
||||
if tupleKey.GetUser() != "" {
|
||||
sb = sb.Where(sq.Eq{"_user": tupleKey.GetUser()})
|
||||
}
|
||||
if opts != nil && opts.From != "" {
|
||||
token, err := sqlcommon.UnmarshallContToken(opts.From)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sb = sb.Where(sq.GtOrEq{"ulid": token.Ulid})
|
||||
}
|
||||
if opts != nil && opts.PageSize != 0 {
|
||||
sb = sb.Limit(uint64(opts.PageSize + 1)) // + 1 is used to determine whether to return a continuation token.
|
||||
}
|
||||
|
||||
rows, err := sb.QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
return sqlcommon.NewSQLTupleIterator(rows), nil
|
||||
}
|
||||
|
||||
// Write see [storage.RelationshipTupleWriter].Write.
|
||||
func (m *SQLite) Write(ctx context.Context, store string, deletes storage.Deletes, writes storage.Writes) error {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.Write")
|
||||
defer span.End()
|
||||
|
||||
if len(deletes)+len(writes) > m.MaxTuplesPerWrite() {
|
||||
return storage.ErrExceededWriteBatchLimit
|
||||
}
|
||||
|
||||
return m.busyRetry(func() error {
|
||||
now := time.Now().UTC()
|
||||
return write(ctx, m.db, m.stbl, m.sqlTime, store, deletes, writes, now)
|
||||
})
|
||||
}
|
||||
|
||||
// ReadUserTuple see [storage.RelationshipTupleReader].ReadUserTuple.
|
||||
func (m *SQLite) ReadUserTuple(ctx context.Context, store string, tupleKey *openfgav1.TupleKey) (*openfgav1.Tuple, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadUserTuple")
|
||||
defer span.End()
|
||||
|
||||
objectType, objectID := tupleUtils.SplitObject(tupleKey.GetObject())
|
||||
userType := tupleUtils.GetUserTypeFromUser(tupleKey.GetUser())
|
||||
|
||||
var conditionName sql.NullString
|
||||
var conditionContext []byte
|
||||
var record storage.TupleRecord
|
||||
err := m.stbl.
|
||||
Select(
|
||||
"object_type", "object_id", "relation", "_user",
|
||||
"condition_name", "condition_context",
|
||||
).
|
||||
From("tuple").
|
||||
Where(sq.Eq{
|
||||
"store": store,
|
||||
"object_type": objectType,
|
||||
"object_id": objectID,
|
||||
"relation": tupleKey.GetRelation(),
|
||||
"_user": tupleKey.GetUser(),
|
||||
"user_type": userType,
|
||||
}).
|
||||
QueryRowContext(ctx).
|
||||
Scan(
|
||||
&record.ObjectType,
|
||||
&record.ObjectID,
|
||||
&record.Relation,
|
||||
&record.User,
|
||||
&conditionName,
|
||||
&conditionContext,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
if conditionName.String != "" {
|
||||
record.ConditionName = conditionName.String
|
||||
|
||||
if conditionContext != nil {
|
||||
var conditionContextStruct structpb.Struct
|
||||
if err := proto.Unmarshal(conditionContext, &conditionContextStruct); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
record.ConditionContext = &conditionContextStruct
|
||||
}
|
||||
}
|
||||
|
||||
return record.AsTuple(), nil
|
||||
}
|
||||
|
||||
// ReadUsersetTuples see [storage.RelationshipTupleReader].ReadUsersetTuples.
|
||||
func (m *SQLite) ReadUsersetTuples(
|
||||
ctx context.Context,
|
||||
store string,
|
||||
filter storage.ReadUsersetTuplesFilter,
|
||||
) (storage.TupleIterator, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadUsersetTuples")
|
||||
defer span.End()
|
||||
|
||||
sb := m.stbl.
|
||||
Select(
|
||||
"store", "object_type", "object_id", "relation", "_user",
|
||||
"condition_name", "condition_context", "ulid", "inserted_at",
|
||||
).
|
||||
From("tuple").
|
||||
Where(sq.Eq{"store": store}).
|
||||
Where(sq.Eq{"user_type": tupleUtils.UserSet})
|
||||
|
||||
objectType, objectID := tupleUtils.SplitObject(filter.Object)
|
||||
if objectType != "" {
|
||||
sb = sb.Where(sq.Eq{"object_type": objectType})
|
||||
}
|
||||
if objectID != "" {
|
||||
sb = sb.Where(sq.Eq{"object_id": objectID})
|
||||
}
|
||||
if filter.Relation != "" {
|
||||
sb = sb.Where(sq.Eq{"relation": filter.Relation})
|
||||
}
|
||||
if len(filter.AllowedUserTypeRestrictions) > 0 {
|
||||
orConditions := sq.Or{}
|
||||
for _, userset := range filter.AllowedUserTypeRestrictions {
|
||||
if _, ok := userset.GetRelationOrWildcard().(*openfgav1.RelationReference_Relation); ok {
|
||||
orConditions = append(orConditions, sq.Like{"_user": userset.GetType() + ":%#" + userset.GetRelation()})
|
||||
}
|
||||
if _, ok := userset.GetRelationOrWildcard().(*openfgav1.RelationReference_Wildcard); ok {
|
||||
orConditions = append(orConditions, sq.Eq{"_user": userset.GetType() + ":*"})
|
||||
}
|
||||
}
|
||||
sb = sb.Where(orConditions)
|
||||
}
|
||||
rows, err := sb.QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
return sqlcommon.NewSQLTupleIterator(rows), nil
|
||||
}
|
||||
|
||||
// ReadStartingWithUser see [storage.RelationshipTupleReader].ReadStartingWithUser.
|
||||
func (m *SQLite) ReadStartingWithUser(
|
||||
ctx context.Context,
|
||||
store string,
|
||||
opts storage.ReadStartingWithUserFilter,
|
||||
) (storage.TupleIterator, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadStartingWithUser")
|
||||
defer span.End()
|
||||
|
||||
targetUsersArg := make([]string, 0, len(opts.UserFilter))
|
||||
for _, u := range opts.UserFilter {
|
||||
targetUser := u.GetObject()
|
||||
if u.GetRelation() != "" {
|
||||
targetUser = strings.Join([]string{u.GetObject(), u.GetRelation()}, "#")
|
||||
}
|
||||
targetUsersArg = append(targetUsersArg, targetUser)
|
||||
}
|
||||
|
||||
rows, err := m.stbl.
|
||||
Select(
|
||||
"store", "object_type", "object_id", "relation", "_user",
|
||||
"condition_name", "condition_context", "ulid", "inserted_at",
|
||||
).
|
||||
From("tuple").
|
||||
Where(sq.Eq{
|
||||
"store": store,
|
||||
"object_type": opts.ObjectType,
|
||||
"relation": opts.Relation,
|
||||
"_user": targetUsersArg,
|
||||
}).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
return sqlcommon.NewSQLTupleIterator(rows), nil
|
||||
}
|
||||
|
||||
// MaxTuplesPerWrite see [storage.RelationshipTupleWriter].MaxTuplesPerWrite.
|
||||
func (m *SQLite) MaxTuplesPerWrite() int {
|
||||
return m.cfg.MaxTuplesPerWriteField
|
||||
}
|
||||
|
||||
// ReadAuthorizationModel see [storage.AuthorizationModelReadBackend].ReadAuthorizationModel.
|
||||
func (m *SQLite) ReadAuthorizationModel(ctx context.Context, store string, modelID string) (*openfgav1.AuthorizationModel, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadAuthorizationModel")
|
||||
defer span.End()
|
||||
|
||||
return sqlcommon.ReadAuthorizationModel(ctx, m.dbInfo, store, modelID)
|
||||
}
|
||||
|
||||
// ReadAuthorizationModels see [storage.AuthorizationModelReadBackend].ReadAuthorizationModels.
|
||||
func (m *SQLite) ReadAuthorizationModels(
|
||||
ctx context.Context,
|
||||
store string,
|
||||
opts storage.PaginationOptions,
|
||||
) ([]*openfgav1.AuthorizationModel, []byte, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadAuthorizationModels")
|
||||
defer span.End()
|
||||
|
||||
sb := m.stbl.Select("authorization_model_id").
|
||||
Distinct().
|
||||
From("authorization_model").
|
||||
Where(sq.Eq{"store": store}).
|
||||
OrderBy("authorization_model_id desc")
|
||||
|
||||
if opts.From != "" {
|
||||
token, err := sqlcommon.UnmarshallContToken(opts.From)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sb = sb.Where(sq.LtOrEq{"authorization_model_id": token.Ulid})
|
||||
}
|
||||
if opts.PageSize > 0 {
|
||||
sb = sb.Limit(uint64(opts.PageSize + 1)) // + 1 is used to determine whether to return a continuation token.
|
||||
}
|
||||
|
||||
rows, err := sb.QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
var modelIDs []string
|
||||
var modelID string
|
||||
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&modelID)
|
||||
if err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
modelIDs = append(modelIDs, modelID)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
var token []byte
|
||||
numModelIDs := len(modelIDs)
|
||||
if len(modelIDs) > opts.PageSize {
|
||||
numModelIDs = opts.PageSize
|
||||
token, err = json.Marshal(sqlcommon.NewContToken(modelID, ""))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make this concurrent with a maximum of 5 goroutines. This may be helpful:
|
||||
// https://stackoverflow.com/questions/25306073/always-have-x-number-of-goroutines-running-at-any-time
|
||||
models := make([]*openfgav1.AuthorizationModel, 0, numModelIDs)
|
||||
// We use numModelIDs here to avoid retrieving possibly one extra model.
|
||||
for i := 0; i < numModelIDs; i++ {
|
||||
model, err := m.ReadAuthorizationModel(ctx, store, modelIDs[i])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
models = append(models, model)
|
||||
}
|
||||
|
||||
return models, token, nil
|
||||
}
|
||||
|
||||
// FindLatestAuthorizationModel see [storage.AuthorizationModelReadBackend].FindLatestAuthorizationModel.
|
||||
func (m *SQLite) FindLatestAuthorizationModel(ctx context.Context, store string) (*openfgav1.AuthorizationModel, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.FindLatestAuthorizationModel")
|
||||
defer span.End()
|
||||
|
||||
return sqlcommon.FindLatestAuthorizationModel(ctx, m.dbInfo, store)
|
||||
}
|
||||
|
||||
// MaxTypesPerAuthorizationModel see [storage.TypeDefinitionWriteBackend].MaxTypesPerAuthorizationModel.
|
||||
func (m *SQLite) MaxTypesPerAuthorizationModel() int {
|
||||
return m.cfg.MaxTypesPerModelField
|
||||
}
|
||||
|
||||
// WriteAuthorizationModel see [storage.TypeDefinitionWriteBackend].WriteAuthorizationModel.
|
||||
func (m *SQLite) WriteAuthorizationModel(ctx context.Context, store string, model *openfgav1.AuthorizationModel) error {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.WriteAuthorizationModel")
|
||||
defer span.End()
|
||||
|
||||
typeDefinitions := model.GetTypeDefinitions()
|
||||
|
||||
if len(typeDefinitions) > m.MaxTypesPerAuthorizationModel() {
|
||||
return storage.ExceededMaxTypeDefinitionsLimitError(m.MaxTypesPerAuthorizationModel())
|
||||
}
|
||||
|
||||
return m.busyRetry(func() error {
|
||||
return sqlcommon.WriteAuthorizationModel(ctx, m.dbInfo, store, model)
|
||||
})
|
||||
}
|
||||
|
||||
// CreateStore adds a new store to the SQLite storage.
|
||||
func (m *SQLite) CreateStore(ctx context.Context, store *openfgav1.Store) (*openfgav1.Store, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.CreateStore")
|
||||
defer span.End()
|
||||
|
||||
txn, err := m.db.BeginTx(ctx, &sql.TxOptions{})
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = txn.Rollback()
|
||||
}()
|
||||
|
||||
_, err = m.stbl.
|
||||
Insert("store").
|
||||
Columns("id", "name", "created_at", "updated_at").
|
||||
Values(store.GetId(), store.GetName(), sq.Expr("datetime('subsec')"), sq.Expr("datetime('subsec')")).
|
||||
RunWith(txn).
|
||||
ExecContext(ctx)
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
var createdAt time.Time
|
||||
var id, name string
|
||||
err = m.stbl.
|
||||
Select("id", "name", "created_at").
|
||||
From("store").
|
||||
Where(sq.Eq{"id": store.GetId()}).
|
||||
RunWith(txn).
|
||||
QueryRowContext(ctx).
|
||||
Scan(&id, &name, &createdAt)
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
err = txn.Commit()
|
||||
if err != nil {
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
return &openfgav1.Store{
|
||||
Id: id,
|
||||
Name: name,
|
||||
CreatedAt: timestamppb.New(createdAt),
|
||||
UpdatedAt: timestamppb.New(createdAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetStore retrieves the details of a specific store from the SQLite using its storeID.
|
||||
func (m *SQLite) GetStore(ctx context.Context, id string) (*openfgav1.Store, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.GetStore")
|
||||
defer span.End()
|
||||
|
||||
row := m.stbl.
|
||||
Select("id", "name", "created_at", "updated_at").
|
||||
From("store").
|
||||
Where(sq.Eq{
|
||||
"id": id,
|
||||
"deleted_at": nil,
|
||||
}).
|
||||
QueryRowContext(ctx)
|
||||
|
||||
var storeID, name string
|
||||
var createdAt, updatedAt time.Time
|
||||
err := row.Scan(&storeID, &name, &createdAt, &updatedAt)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, storage.ErrNotFound
|
||||
}
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
return &openfgav1.Store{
|
||||
Id: storeID,
|
||||
Name: name,
|
||||
CreatedAt: timestamppb.New(createdAt),
|
||||
UpdatedAt: timestamppb.New(updatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListStores provides a paginated list of all stores present in the SQLite storage.
|
||||
func (m *SQLite) ListStores(ctx context.Context, opts storage.PaginationOptions) ([]*openfgav1.Store, []byte, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ListStores")
|
||||
defer span.End()
|
||||
|
||||
sb := m.stbl.
|
||||
Select("id", "name", "created_at", "updated_at").
|
||||
From("store").
|
||||
Where(sq.Eq{"deleted_at": nil}).
|
||||
OrderBy("id")
|
||||
|
||||
if opts.From != "" {
|
||||
token, err := sqlcommon.UnmarshallContToken(opts.From)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sb = sb.Where(sq.GtOrEq{"id": token.Ulid})
|
||||
}
|
||||
if opts.PageSize > 0 {
|
||||
sb = sb.Limit(uint64(opts.PageSize + 1)) // + 1 is used to determine whether to return a continuation token.
|
||||
}
|
||||
|
||||
rows, err := sb.QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
var stores []*openfgav1.Store
|
||||
var id string
|
||||
for rows.Next() {
|
||||
var name string
|
||||
var createdAt, updatedAt time.Time
|
||||
err := rows.Scan(&id, &name, &createdAt, &updatedAt)
|
||||
if err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
stores = append(stores, &openfgav1.Store{
|
||||
Id: id,
|
||||
Name: name,
|
||||
CreatedAt: timestamppb.New(createdAt),
|
||||
UpdatedAt: timestamppb.New(updatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
if len(stores) > opts.PageSize {
|
||||
contToken, err := json.Marshal(sqlcommon.NewContToken(id, ""))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return stores[:opts.PageSize], contToken, nil
|
||||
}
|
||||
|
||||
return stores, nil, nil
|
||||
}
|
||||
|
||||
// DeleteStore removes a store from the SQLite storage.
|
||||
func (m *SQLite) DeleteStore(ctx context.Context, id string) error {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.DeleteStore")
|
||||
defer span.End()
|
||||
|
||||
_, err := m.stbl.
|
||||
Update("store").
|
||||
Set("deleted_at", sq.Expr("datetime('subsec')")).
|
||||
Where(sq.Eq{"id": id}).
|
||||
ExecContext(ctx)
|
||||
if err != nil {
|
||||
return handleSQLError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteAssertions see [storage.AssertionsBackend].WriteAssertions.
|
||||
func (m *SQLite) WriteAssertions(ctx context.Context, store, modelID string, assertions []*openfgav1.Assertion) error {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.WriteAssertions")
|
||||
defer span.End()
|
||||
|
||||
marshalledAssertions, err := proto.Marshal(&openfgav1.Assertions{Assertions: assertions})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.busyRetry(func() error {
|
||||
_, err = m.stbl.
|
||||
Insert("assertion").
|
||||
Columns("store", "authorization_model_id", "assertions").
|
||||
Values(store, modelID, marshalledAssertions).
|
||||
Suffix("ON CONFLICT(store,authorization_model_id) DO UPDATE SET assertions = ?", marshalledAssertions).
|
||||
ExecContext(ctx)
|
||||
if err != nil {
|
||||
return handleSQLError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ReadAssertions see [storage.AssertionsBackend].ReadAssertions.
|
||||
func (m *SQLite) ReadAssertions(ctx context.Context, store, modelID string) ([]*openfgav1.Assertion, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadAssertions")
|
||||
defer span.End()
|
||||
|
||||
var marshalledAssertions []byte
|
||||
err := m.stbl.
|
||||
Select("assertions").
|
||||
From("assertion").
|
||||
Where(sq.Eq{
|
||||
"store": store,
|
||||
"authorization_model_id": modelID,
|
||||
}).
|
||||
QueryRowContext(ctx).
|
||||
Scan(&marshalledAssertions)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return []*openfgav1.Assertion{}, nil
|
||||
}
|
||||
return nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
var assertions openfgav1.Assertions
|
||||
err = proto.Unmarshal(marshalledAssertions, &assertions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return assertions.GetAssertions(), nil
|
||||
}
|
||||
|
||||
// ReadChanges see [storage.ChangelogBackend].ReadChanges.
|
||||
func (m *SQLite) ReadChanges(
|
||||
ctx context.Context,
|
||||
store, objectTypeFilter string,
|
||||
opts storage.PaginationOptions,
|
||||
horizonOffset time.Duration,
|
||||
) ([]*openfgav1.TupleChange, []byte, error) {
|
||||
ctx, span := tracer.Start(ctx, "sqlite.ReadChanges")
|
||||
defer span.End()
|
||||
|
||||
sb := m.stbl.
|
||||
Select(
|
||||
"ulid", "object_type", "object_id", "relation", "_user", "operation",
|
||||
"condition_name", "condition_context", "inserted_at",
|
||||
).
|
||||
From("changelog").
|
||||
Where(sq.Eq{"store": store}).
|
||||
Where(fmt.Sprintf("inserted_at <= datetime('subsec','-%f seconds')", horizonOffset.Seconds())).
|
||||
OrderBy("ulid asc")
|
||||
|
||||
if objectTypeFilter != "" {
|
||||
sb = sb.Where(sq.Eq{"object_type": objectTypeFilter})
|
||||
}
|
||||
if opts.From != "" {
|
||||
token, err := sqlcommon.UnmarshallContToken(opts.From)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if token.ObjectType != objectTypeFilter {
|
||||
return nil, nil, storage.ErrMismatchObjectType
|
||||
}
|
||||
|
||||
sb = sb.Where(sq.Gt{"ulid": token.Ulid}) // > as we always return a continuation token.
|
||||
}
|
||||
if opts.PageSize > 0 {
|
||||
sb = sb.Limit(uint64(opts.PageSize)) // + 1 is NOT used here as we always return a continuation token.
|
||||
}
|
||||
|
||||
rows, err := sb.QueryContext(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
var changes []*openfgav1.TupleChange
|
||||
var ulid string
|
||||
for rows.Next() {
|
||||
var objectType, objectID, relation, user string
|
||||
var operation int
|
||||
var insertedAt time.Time
|
||||
var conditionName sql.NullString
|
||||
var conditionContext []byte
|
||||
|
||||
err = rows.Scan(
|
||||
&ulid,
|
||||
&objectType,
|
||||
&objectID,
|
||||
&relation,
|
||||
&user,
|
||||
&operation,
|
||||
&conditionName,
|
||||
&conditionContext,
|
||||
&insertedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, handleSQLError(err)
|
||||
}
|
||||
|
||||
var conditionContextStruct structpb.Struct
|
||||
if conditionName.String != "" {
|
||||
if conditionContext != nil {
|
||||
if err := proto.Unmarshal(conditionContext, &conditionContextStruct); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tk := tupleUtils.NewTupleKeyWithCondition(
|
||||
tupleUtils.BuildObject(objectType, objectID),
|
||||
relation,
|
||||
user,
|
||||
conditionName.String,
|
||||
&conditionContextStruct,
|
||||
)
|
||||
|
||||
changes = append(changes, &openfgav1.TupleChange{
|
||||
TupleKey: tk,
|
||||
Operation: openfgav1.TupleOperation(operation),
|
||||
Timestamp: timestamppb.New(insertedAt.UTC()),
|
||||
})
|
||||
}
|
||||
|
||||
if len(changes) == 0 {
|
||||
return nil, nil, storage.ErrNotFound
|
||||
}
|
||||
|
||||
contToken, err := json.Marshal(sqlcommon.NewContToken(ulid, objectTypeFilter))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return changes, contToken, nil
|
||||
}
|
||||
|
||||
func (m *SQLite) IsReady(ctx context.Context) (storage.ReadinessStatus, error) {
|
||||
if err := m.db.PingContext(ctx); err != nil {
|
||||
return storage.ReadinessStatus{}, err
|
||||
}
|
||||
return storage.ReadinessStatus{
|
||||
IsReady: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SQLite will return an SQLITE_BUSY error when the database is locked rather than waiting for the lock.
|
||||
// This function retries the operation up to 5 times before returning the error.
|
||||
func (m *SQLite) busyRetry(fn func() error) error {
|
||||
for retries := 0; ; retries++ {
|
||||
err := fn()
|
||||
if err == nil || retries == m.cfg.QueryRetries {
|
||||
return err
|
||||
}
|
||||
|
||||
var sqliteErr *sqlite3.Error
|
||||
if errors.As(err, &sqliteErr) && (sqliteErr.Code == sqlite3.ErrLocked || sqliteErr.Code == sqlite3.ErrBusy) {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func handleSQLError(err error, args ...any) error {
|
||||
if strings.Contains(err.Error(), "UNIQUE constraint failed:") {
|
||||
if len(args) > 0 {
|
||||
if tk, ok := args[0].(*openfgav1.TupleKey); ok {
|
||||
return storage.InvalidWriteInputError(tk, openfgav1.TupleOperation_TUPLE_OPERATION_WRITE)
|
||||
}
|
||||
}
|
||||
return storage.ErrCollision
|
||||
}
|
||||
|
||||
return sqlcommon.HandleSQLError(err, args...)
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/oklog/ulid/v2"
|
||||
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/openfga/openfga/pkg/storage"
|
||||
"github.com/openfga/openfga/pkg/storage/sqlcommon"
|
||||
"github.com/openfga/openfga/pkg/storage/test"
|
||||
"github.com/openfga/openfga/pkg/tuple"
|
||||
"github.com/openfga/openfga/pkg/typesystem"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/tests/testsuite"
|
||||
|
||||
zassets "github.com/grafana/grafana/pkg/services/authz/zanzana/store/assets"
|
||||
"github.com/grafana/grafana/pkg/services/authz/zanzana/store/migration"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testsuite.Run(m)
|
||||
}
|
||||
|
||||
// TestIntegrationDatastore runs open fga default datastore test suite
|
||||
func TestIntegrationDatastore(t *testing.T) {
|
||||
db := sqliteIntegrationTest(t)
|
||||
ds, err := NewWithDB(db, NewConfig())
|
||||
require.NoError(t, err)
|
||||
test.RunAllTests(t, ds)
|
||||
}
|
||||
|
||||
// TestIntegrationReadEnsureNoOrder asserts that the read response is not ordered by ulid.
|
||||
func TestIntegrationReadEnsureNoOrder(t *testing.T) {
|
||||
db := sqliteIntegrationTest(t)
|
||||
|
||||
ds, err := NewWithDB(db, NewConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
store := "store"
|
||||
firstTuple := tuple.NewTupleKey("doc:object_id_1", "relation", "user:user_1")
|
||||
secondTuple := tuple.NewTupleKey("doc:object_id_2", "relation", "user:user_2")
|
||||
|
||||
err = sqlcommon.Write(ctx,
|
||||
sqlcommon.NewDBInfo(ds.db, ds.stbl, sq.Expr("datetime('subsec')")),
|
||||
store,
|
||||
[]*openfgav1.TupleKeyWithoutCondition{},
|
||||
[]*openfgav1.TupleKey{firstTuple},
|
||||
time.Now())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Tweak time so that ULID is smaller.
|
||||
err = sqlcommon.Write(ctx,
|
||||
sqlcommon.NewDBInfo(ds.db, ds.stbl, sq.Expr("datetime('subsec')")),
|
||||
store,
|
||||
[]*openfgav1.TupleKeyWithoutCondition{},
|
||||
[]*openfgav1.TupleKey{secondTuple},
|
||||
time.Now().Add(time.Minute*-1))
|
||||
require.NoError(t, err)
|
||||
|
||||
iter, err := ds.Read(ctx,
|
||||
store,
|
||||
tuple.NewTupleKey("doc:", "relation", ""))
|
||||
defer iter.Stop()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
// We expect that objectID1 will return first because it is inserted first.
|
||||
curTuple, err := iter.Next(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, firstTuple, curTuple.GetKey())
|
||||
|
||||
curTuple, err = iter.Next(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, secondTuple, curTuple.GetKey())
|
||||
}
|
||||
|
||||
// TestIntegrationReadPageEnsureNoOrder asserts that the read page is ordered by ulid.
|
||||
func TestIntegrationReadPageEnsureOrder(t *testing.T) {
|
||||
db := sqliteIntegrationTest(t)
|
||||
|
||||
ds, err := NewWithDB(db, NewConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
store := "store"
|
||||
firstTuple := tuple.NewTupleKey("doc:object_id_1", "relation", "user:user_1")
|
||||
secondTuple := tuple.NewTupleKey("doc:object_id_2", "relation", "user:user_2")
|
||||
|
||||
err = sqlcommon.Write(ctx,
|
||||
sqlcommon.NewDBInfo(ds.db, ds.stbl, sq.Expr("datetime('subsec')")),
|
||||
store,
|
||||
[]*openfgav1.TupleKeyWithoutCondition{},
|
||||
[]*openfgav1.TupleKey{firstTuple},
|
||||
time.Now())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Tweak time so that ULID is smaller.
|
||||
err = sqlcommon.Write(ctx,
|
||||
sqlcommon.NewDBInfo(ds.db, ds.stbl, sq.Expr("datetime('subsec')")),
|
||||
store,
|
||||
[]*openfgav1.TupleKeyWithoutCondition{},
|
||||
[]*openfgav1.TupleKey{secondTuple},
|
||||
time.Now().Add(time.Minute*-1))
|
||||
require.NoError(t, err)
|
||||
|
||||
tuples, _, err := ds.ReadPage(ctx,
|
||||
store,
|
||||
tuple.NewTupleKey("doc:", "relation", ""),
|
||||
storage.NewPaginationOptions(0, ""))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, tuples, 2)
|
||||
// We expect that objectID2 will return first because it has a smaller ulid.
|
||||
require.Equal(t, secondTuple, tuples[0].GetKey())
|
||||
require.Equal(t, firstTuple, tuples[1].GetKey())
|
||||
}
|
||||
|
||||
func TestIntegrationReadAuthorizationModelUnmarshallError(t *testing.T) {
|
||||
db := sqliteIntegrationTest(t)
|
||||
|
||||
ds, err := NewWithDB(db, NewConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
store := "store"
|
||||
modelID := "foo"
|
||||
schemaVersion := typesystem.SchemaVersion1_0
|
||||
|
||||
bytes, err := proto.Marshal(&openfgav1.TypeDefinition{Type: "document"})
|
||||
require.NoError(t, err)
|
||||
pbdata := []byte{0x01, 0x02, 0x03}
|
||||
|
||||
_, err = ds.db.ExecContext(ctx, "INSERT INTO authorization_model (store, authorization_model_id, schema_version, type, type_definition, serialized_protobuf) VALUES (?, ?, ?, ?, ?, ?)", store, modelID, schemaVersion, "document", bytes, pbdata)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = ds.ReadAuthorizationModel(ctx, store, modelID)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "cannot parse invalid wire-format data")
|
||||
}
|
||||
|
||||
// TestIntegrationAllowNullCondition tests that tuple and changelog rows existing before
|
||||
// migration 005_add_conditions_to_tuples can be successfully read.
|
||||
func TestIntegrationAllowNullCondition(t *testing.T) {
|
||||
db := sqliteIntegrationTest(t)
|
||||
|
||||
ds, err := NewWithDB(db, NewConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
stmt := `
|
||||
INSERT INTO tuple (
|
||||
store, object_type, object_id, relation, _user, user_type, ulid,
|
||||
condition_name, condition_context, inserted_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('subsec'));
|
||||
`
|
||||
_, err = ds.db.ExecContext(
|
||||
ctx, stmt, "store", "folder", "2021-budget", "owner", "user:anne", "user",
|
||||
ulid.Make().String(), nil, nil,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
tk := tuple.NewTupleKey("folder:2021-budget", "owner", "user:anne")
|
||||
iter, err := ds.Read(ctx, "store", tk)
|
||||
require.NoError(t, err)
|
||||
defer iter.Stop()
|
||||
|
||||
curTuple, err := iter.Next(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tk, curTuple.GetKey())
|
||||
|
||||
tuples, _, err := ds.ReadPage(ctx, "store", &openfgav1.TupleKey{}, storage.PaginationOptions{
|
||||
PageSize: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tuples, 1)
|
||||
require.Equal(t, tk, tuples[0].GetKey())
|
||||
|
||||
userTuple, err := ds.ReadUserTuple(ctx, "store", tk)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tk, userTuple.GetKey())
|
||||
|
||||
tk2 := tuple.NewTupleKey("folder:2022-budget", "viewer", "user:anne")
|
||||
_, err = ds.db.ExecContext(
|
||||
ctx, stmt, "store", "folder", "2022-budget", "viewer", "user:anne", "userset",
|
||||
ulid.Make().String(), nil, nil,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
iter, err = ds.ReadUsersetTuples(ctx, "store", storage.ReadUsersetTuplesFilter{Object: "folder:2022-budget"})
|
||||
require.NoError(t, err)
|
||||
defer iter.Stop()
|
||||
|
||||
curTuple, err = iter.Next(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tk2, curTuple.GetKey())
|
||||
|
||||
iter, err = ds.ReadStartingWithUser(ctx, "store", storage.ReadStartingWithUserFilter{
|
||||
ObjectType: "folder",
|
||||
Relation: "owner",
|
||||
UserFilter: []*openfgav1.ObjectRelation{
|
||||
{Object: "user:anne"},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer iter.Stop()
|
||||
|
||||
curTuple, err = iter.Next(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tk, curTuple.GetKey())
|
||||
|
||||
stmt = `
|
||||
INSERT INTO changelog (
|
||||
store, object_type, object_id, relation, _user, ulid,
|
||||
condition_name, condition_context, inserted_at, operation
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('subsec'), ?);
|
||||
`
|
||||
_, err = ds.db.ExecContext(
|
||||
ctx, stmt, "store", "folder", "2021-budget", "owner", "user:anne",
|
||||
ulid.Make().String(), nil, nil, openfgav1.TupleOperation_TUPLE_OPERATION_WRITE,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = ds.db.ExecContext(
|
||||
ctx, stmt, "store", "folder", "2021-budget", "owner", "user:anne",
|
||||
ulid.Make().String(), nil, nil, openfgav1.TupleOperation_TUPLE_OPERATION_DELETE,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
changes, _, err := ds.ReadChanges(ctx, "store", "folder", storage.PaginationOptions{}, 0)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, changes, 2)
|
||||
require.Equal(t, tk, changes[0].GetTupleKey())
|
||||
require.Equal(t, tk, changes[1].GetTupleKey())
|
||||
}
|
||||
|
||||
// TestIntegrationMarshalledAssertions tests that previously persisted marshalled
|
||||
// assertions can be read back. In any case where the Assertions proto model
|
||||
// needs to change, we'll likely need to introduce a series of data migrations.
|
||||
func TestIntegrationMarshalledAssertions(t *testing.T) {
|
||||
db := sqliteIntegrationTest(t)
|
||||
|
||||
ds, err := NewWithDB(db, NewConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
// Note: this represents an assertion written on v1.3.7.
|
||||
stmt := `
|
||||
INSERT INTO assertion (
|
||||
store, authorization_model_id, assertions
|
||||
) VALUES (?, ?, UNHEX('0A2B0A270A12666F6C6465723A323032312D62756467657412056F776E65721A0A757365723A616E6E657A1001'));
|
||||
`
|
||||
_, err = ds.db.ExecContext(ctx, stmt, "store", "model")
|
||||
require.NoError(t, err)
|
||||
|
||||
assertions, err := ds.ReadAssertions(ctx, "store", "model")
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedAssertions := []*openfgav1.Assertion{
|
||||
{
|
||||
TupleKey: &openfgav1.AssertionTupleKey{
|
||||
Object: "folder:2021-budget",
|
||||
Relation: "owner",
|
||||
User: "user:annez",
|
||||
},
|
||||
Expectation: true,
|
||||
},
|
||||
}
|
||||
require.Equal(t, expectedAssertions, assertions)
|
||||
}
|
||||
|
||||
func sqliteIntegrationTest(tb testing.TB) *sql.DB {
|
||||
if testing.Short() || !db.IsTestDbSQLite() {
|
||||
tb.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
db, cfg := db.InitTestDBWithCfg(tb)
|
||||
|
||||
m := migrator.NewMigrator(db.GetEngine(), cfg)
|
||||
err := migration.RunWithMigrator(m, cfg, zassets.EmbedMigrations, zassets.SQLiteMigrationDir)
|
||||
require.NoError(tb, err)
|
||||
|
||||
return db.GetEngine().DB().DB
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/oklog/ulid/v2"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||
"github.com/openfga/openfga/pkg/storage"
|
||||
tupleUtils "github.com/openfga/openfga/pkg/tuple"
|
||||
)
|
||||
|
||||
// write is copied from https://github.com/openfga/openfga/blob/main/pkg/storage/sqlcommon/sqlcommon.go#L330-L456
|
||||
// but uses custom handleSQLError.
|
||||
func write(
|
||||
ctx context.Context,
|
||||
db *sql.DB,
|
||||
stbl sq.StatementBuilderType,
|
||||
sqlTime any,
|
||||
store string,
|
||||
deletes storage.Deletes,
|
||||
writes storage.Writes,
|
||||
now time.Time,
|
||||
) error {
|
||||
txn, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return handleSQLError(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = txn.Rollback()
|
||||
}()
|
||||
|
||||
changelogBuilder := stbl.
|
||||
Insert("changelog").
|
||||
Columns(
|
||||
"store", "object_type", "object_id", "relation", "_user",
|
||||
"condition_name", "condition_context", "operation", "ulid", "inserted_at",
|
||||
)
|
||||
|
||||
deleteBuilder := stbl.Delete("tuple")
|
||||
|
||||
for _, tk := range deletes {
|
||||
id := ulid.MustNew(ulid.Timestamp(now), ulid.DefaultEntropy()).String()
|
||||
objectType, objectID := tupleUtils.SplitObject(tk.GetObject())
|
||||
|
||||
res, err := deleteBuilder.
|
||||
Where(sq.Eq{
|
||||
"store": store,
|
||||
"object_type": objectType,
|
||||
"object_id": objectID,
|
||||
"relation": tk.GetRelation(),
|
||||
"_user": tk.GetUser(),
|
||||
"user_type": tupleUtils.GetUserTypeFromUser(tk.GetUser()),
|
||||
}).
|
||||
RunWith(txn). // Part of a txn.
|
||||
ExecContext(ctx)
|
||||
if err != nil {
|
||||
return handleSQLError(err, tk)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return handleSQLError(err)
|
||||
}
|
||||
|
||||
if rowsAffected != 1 {
|
||||
return storage.InvalidWriteInputError(
|
||||
tk,
|
||||
openfgav1.TupleOperation_TUPLE_OPERATION_DELETE,
|
||||
)
|
||||
}
|
||||
|
||||
changelogBuilder = changelogBuilder.Values(
|
||||
store, objectType, objectID,
|
||||
tk.GetRelation(), tk.GetUser(),
|
||||
"", nil, // Redact condition info for deletes since we only need the base triplet (object, relation, user).
|
||||
openfgav1.TupleOperation_TUPLE_OPERATION_DELETE,
|
||||
id, sqlTime,
|
||||
)
|
||||
}
|
||||
|
||||
insertBuilder := stbl.
|
||||
Insert("tuple").
|
||||
Columns(
|
||||
"store", "object_type", "object_id", "relation", "_user", "user_type",
|
||||
"condition_name", "condition_context", "ulid", "inserted_at",
|
||||
)
|
||||
|
||||
for _, tk := range writes {
|
||||
id := ulid.MustNew(ulid.Timestamp(now), ulid.DefaultEntropy()).String()
|
||||
objectType, objectID := tupleUtils.SplitObject(tk.GetObject())
|
||||
|
||||
conditionName, conditionContext, err := marshalRelationshipCondition(tk.GetCondition())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = insertBuilder.
|
||||
Values(
|
||||
store,
|
||||
objectType,
|
||||
objectID,
|
||||
tk.GetRelation(),
|
||||
tk.GetUser(),
|
||||
tupleUtils.GetUserTypeFromUser(tk.GetUser()),
|
||||
conditionName,
|
||||
conditionContext,
|
||||
id,
|
||||
sqlTime,
|
||||
).
|
||||
RunWith(txn). // Part of a txn.
|
||||
ExecContext(ctx)
|
||||
if err != nil {
|
||||
return handleSQLError(err, tk)
|
||||
}
|
||||
|
||||
changelogBuilder = changelogBuilder.Values(
|
||||
store,
|
||||
objectType,
|
||||
objectID,
|
||||
tk.GetRelation(),
|
||||
tk.GetUser(),
|
||||
conditionName,
|
||||
conditionContext,
|
||||
openfgav1.TupleOperation_TUPLE_OPERATION_WRITE,
|
||||
id,
|
||||
sqlTime,
|
||||
)
|
||||
}
|
||||
|
||||
if len(writes) > 0 || len(deletes) > 0 {
|
||||
_, err := changelogBuilder.RunWith(txn).ExecContext(ctx) // Part of a txn.
|
||||
if err != nil {
|
||||
return handleSQLError(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := txn.Commit(); err != nil {
|
||||
return handleSQLError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// copied from https://github.com/openfga/openfga/blob/main/pkg/storage/sqlcommon/encoding.go#L8-L24
|
||||
func marshalRelationshipCondition(
|
||||
rel *openfgav1.RelationshipCondition,
|
||||
) (name string, context []byte, err error) {
|
||||
if rel != nil {
|
||||
if rel.GetContext() != nil && len(rel.GetContext().GetFields()) > 0 {
|
||||
context, err = proto.Marshal(rel.GetContext())
|
||||
if err != nil {
|
||||
return name, context, err
|
||||
}
|
||||
}
|
||||
|
||||
return rel.GetName(), context, err
|
||||
}
|
||||
|
||||
return name, context, err
|
||||
}
|
||||
@@ -2,15 +2,15 @@ package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm"
|
||||
|
||||
"github.com/openfga/openfga/assets"
|
||||
"github.com/openfga/openfga/pkg/storage"
|
||||
"github.com/openfga/openfga/pkg/storage/mysql"
|
||||
"github.com/openfga/openfga/pkg/storage/postgres"
|
||||
"github.com/openfga/openfga/pkg/storage/sqlcommon"
|
||||
"github.com/openfga/openfga/pkg/storage/sqlite"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -19,9 +19,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
|
||||
zlogger "github.com/grafana/grafana/pkg/services/authz/zanzana/logger"
|
||||
zassets "github.com/grafana/grafana/pkg/services/authz/zanzana/store/assets"
|
||||
"github.com/grafana/grafana/pkg/services/authz/zanzana/store/migration"
|
||||
"github.com/grafana/grafana/pkg/services/authz/zanzana/store/sqlite"
|
||||
)
|
||||
|
||||
func NewStore(cfg *setting.Cfg, logger log.Logger) (storage.OpenFGADatastore, error) {
|
||||
@@ -32,22 +30,12 @@ func NewStore(cfg *setting.Cfg, logger log.Logger) (storage.OpenFGADatastore, er
|
||||
|
||||
switch grafanaDBCfg.Type {
|
||||
case migrator.SQLite:
|
||||
connStr := grafanaDBCfg.ConnectionString
|
||||
// Initilize connection using xorm engine so we can reuse it for both migrations and data store
|
||||
engine, err := xorm.NewEngine(grafanaDBCfg.Type, connStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to database: %w", err)
|
||||
}
|
||||
|
||||
m := migrator.NewMigrator(engine, cfg)
|
||||
if err := migration.RunWithMigrator(m, cfg, zassets.EmbedMigrations, zassets.SQLiteMigrationDir); err != nil {
|
||||
connStr := sqliteConnectionString(grafanaDBCfg.ConnectionString)
|
||||
if err := migration.Run(cfg, migrator.SQLite, connStr, assets.EmbedMigrations, assets.SqliteMigrationDir); err != nil {
|
||||
return nil, fmt.Errorf("failed to run migrations: %w", err)
|
||||
}
|
||||
|
||||
return sqlite.NewWithDB(engine.DB().DB, &sqlite.Config{
|
||||
Config: zanzanaDBCfg,
|
||||
QueryRetries: grafanaDBCfg.QueryRetries,
|
||||
})
|
||||
return sqlite.New(connStr, zanzanaDBCfg)
|
||||
case migrator.MySQL:
|
||||
// For mysql we need to pass parseTime parameter in connection string
|
||||
connStr := grafanaDBCfg.ConnectionString + "&parseTime=true"
|
||||
@@ -75,20 +63,16 @@ func NewEmbeddedStore(cfg *setting.Cfg, db db.DB, logger log.Logger) (storage.Op
|
||||
return nil, fmt.Errorf("failed to parse database config: %w", err)
|
||||
}
|
||||
|
||||
m := migrator.NewMigrator(db.GetEngine(), cfg)
|
||||
|
||||
switch grafanaDBCfg.Type {
|
||||
case migrator.SQLite:
|
||||
if err := migration.RunWithMigrator(m, cfg, zassets.EmbedMigrations, zassets.SQLiteMigrationDir); err != nil {
|
||||
grafanaDBCfg.ConnectionString = sqliteConnectionString(grafanaDBCfg.ConnectionString)
|
||||
if err := migration.Run(cfg, migrator.SQLite, grafanaDBCfg.ConnectionString, assets.EmbedMigrations, assets.SqliteMigrationDir); err != nil {
|
||||
return nil, fmt.Errorf("failed to run migrations: %w", err)
|
||||
}
|
||||
|
||||
// FIXME(kalleep): We should work on getting sqlite implemtation merged upstream and replace this one
|
||||
return sqlite.NewWithDB(db.GetEngine().DB().DB, &sqlite.Config{
|
||||
Config: zanzanaDBCfg,
|
||||
QueryRetries: grafanaDBCfg.QueryRetries,
|
||||
})
|
||||
return sqlite.New(grafanaDBCfg.ConnectionString, zanzanaDBCfg)
|
||||
case migrator.MySQL:
|
||||
m := migrator.NewMigrator(db.GetEngine(), cfg)
|
||||
if err := migration.RunWithMigrator(m, cfg, assets.EmbedMigrations, assets.MySQLMigrationDir); err != nil {
|
||||
return nil, fmt.Errorf("failed to run migrations: %w", err)
|
||||
}
|
||||
@@ -96,6 +80,7 @@ func NewEmbeddedStore(cfg *setting.Cfg, db db.DB, logger log.Logger) (storage.Op
|
||||
// For mysql we need to pass parseTime parameter in connection string
|
||||
return mysql.New(grafanaDBCfg.ConnectionString+"&parseTime=true", zanzanaDBCfg)
|
||||
case migrator.Postgres:
|
||||
m := migrator.NewMigrator(db.GetEngine(), cfg)
|
||||
if err := migration.RunWithMigrator(m, cfg, assets.EmbedMigrations, assets.PostgresMigrationDir); err != nil {
|
||||
return nil, fmt.Errorf("failed to run migrations: %w", err)
|
||||
}
|
||||
@@ -126,3 +111,8 @@ func parseConfig(cfg *setting.Cfg, logger log.Logger) (*sqlstore.DatabaseConfig,
|
||||
|
||||
return grafanaDBCfg, zanzanaDBCfg, nil
|
||||
}
|
||||
|
||||
func sqliteConnectionString(v string) string {
|
||||
// hardcode zanzana.db for now
|
||||
return v[0:strings.LastIndex(v, "/")+1] + "zanzana.db"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user