From 8d122454dee3e77988ac7aaf3c8fcc45d9111771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Mon, 27 Nov 2023 14:10:19 +0000 Subject: [PATCH 01/49] exposes backupformat package --- internal/cmd/backup.go | 2 +- internal/cmd/restore.go | 2 +- {internal => pkg}/backupformat/backupformat_test.go | 0 {internal => pkg}/backupformat/decoder.go | 0 {internal => pkg}/backupformat/encoder.go | 0 {internal => pkg}/backupformat/schema.go | 0 6 files changed, 2 insertions(+), 2 deletions(-) rename {internal => pkg}/backupformat/backupformat_test.go (100%) rename {internal => pkg}/backupformat/decoder.go (100%) rename {internal => pkg}/backupformat/encoder.go (100%) rename {internal => pkg}/backupformat/schema.go (100%) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index d4d07965..9ff6a30c 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -13,8 +13,8 @@ import ( "github.com/schollz/progressbar/v3" "github.com/spf13/cobra" - "github.com/authzed/zed/internal/backupformat" "github.com/authzed/zed/internal/client" + "github.com/authzed/zed/pkg/backupformat" ) func registerBackupCmd(rootCmd *cobra.Command) { diff --git a/internal/cmd/restore.go b/internal/cmd/restore.go index d6082045..7a270d0f 100644 --- a/internal/cmd/restore.go +++ b/internal/cmd/restore.go @@ -13,8 +13,8 @@ import ( "github.com/schollz/progressbar/v3" "github.com/spf13/cobra" - "github.com/authzed/zed/internal/backupformat" "github.com/authzed/zed/internal/client" + "github.com/authzed/zed/pkg/backupformat" ) func registerRestoreCmd(rootCmd *cobra.Command) { diff --git a/internal/backupformat/backupformat_test.go b/pkg/backupformat/backupformat_test.go similarity index 100% rename from internal/backupformat/backupformat_test.go rename to pkg/backupformat/backupformat_test.go diff --git a/internal/backupformat/decoder.go b/pkg/backupformat/decoder.go similarity index 100% rename from internal/backupformat/decoder.go rename to pkg/backupformat/decoder.go diff --git a/internal/backupformat/encoder.go b/pkg/backupformat/encoder.go similarity index 100% rename from internal/backupformat/encoder.go rename to pkg/backupformat/encoder.go diff --git a/internal/backupformat/schema.go b/pkg/backupformat/schema.go similarity index 100% rename from internal/backupformat/schema.go rename to pkg/backupformat/schema.go From 6e62b4248403b6ee12dc943ca3725f5188082a8e Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Tue, 5 Dec 2023 18:14:56 -0500 Subject: [PATCH 02/49] Fix panic on backup call if the SpiceDB version is unsupported --- internal/cmd/backup.go | 4 ++++ pkg/backupformat/encoder.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 9ff6a30c..28bf91f7 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -74,6 +74,10 @@ func backupCmdFunc(cmd *cobra.Command, args []string) error { hasProgressbar = true } + if schemaResp.ReadAt == nil { + return fmt.Errorf("`backup` is not supported on this version of SpiceDB") + } + encoder, err := backupformat.NewEncoder(relWriter, schemaResp.SchemaText, schemaResp.ReadAt) if err != nil { return fmt.Errorf("error creating backup file encoder: %w", err) diff --git a/pkg/backupformat/encoder.go b/pkg/backupformat/encoder.go index b892dda8..60eb42f5 100644 --- a/pkg/backupformat/encoder.go +++ b/pkg/backupformat/encoder.go @@ -1,6 +1,7 @@ package backupformat import ( + "errors" "fmt" "io" @@ -15,6 +16,10 @@ func NewEncoder(w io.Writer, schema string, token *v1.ZedToken) (*Encoder, error return nil, fmt.Errorf("unable to create avro schema: %w", err) } + if token == nil { + return nil, errors.New("missing expected token") + } + md := map[string][]byte{ metadataKeyZT: []byte(token.Token), } From a870c1f4228fd6876f087841c8520bd1d6a5581f Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Fri, 8 Dec 2023 10:53:44 -0500 Subject: [PATCH 03/49] backup: add prefix-filtering for schemas & rels --- go.mod | 74 +++-- go.sum | 548 +++++++----------------------------- internal/cmd/backup.go | 68 ++++- internal/cmd/restore.go | 20 +- internal/cmd/schema.go | 5 +- pkg/backupformat/decoder.go | 12 +- 6 files changed, 232 insertions(+), 495 deletions(-) diff --git a/go.mod b/go.mod index 2cfbad53..c3f1fe5c 100644 --- a/go.mod +++ b/go.mod @@ -10,27 +10,26 @@ require ( github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 github.com/authzed/authzed-go v0.10.1 github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 - github.com/authzed/spicedb v1.27.0-rc1 + github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da github.com/brianvoe/gofakeit/v6 v6.22.0 github.com/charmbracelet/lipgloss v0.7.1 github.com/gookit/color v1.5.4 - github.com/hamba/avro/v2 v2.13.0 - github.com/jzelinskie/cobrautil v0.0.12 + github.com/hamba/avro/v2 v2.18.0 github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a github.com/jzelinskie/stringz v0.0.2 - github.com/mattn/go-isatty v0.0.19 + github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/rs/zerolog v1.31.0 - github.com/schollz/progressbar/v3 v3.13.1 - github.com/spf13/cobra v1.7.0 + github.com/schollz/progressbar/v3 v3.14.1 + github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 github.com/xlab/treeprint v1.2.0 - golang.org/x/mod v0.13.0 - golang.org/x/sync v0.4.0 - golang.org/x/term v0.13.0 - google.golang.org/grpc v1.58.3 + golang.org/x/mod v0.14.0 + golang.org/x/sync v0.5.0 + golang.org/x/term v0.15.0 + google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -42,6 +41,8 @@ require ( github.com/authzed/cel-go v0.17.5 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/bits-and-blooms/bloom/v3 v3.6.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -55,9 +56,9 @@ require ( github.com/ecordell/optgen v0.0.10-0.20230609182709-018141bf9698 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect - github.com/fatih/color v1.15.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/golang/protobuf v1.5.3 // indirect @@ -65,11 +66,12 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v43 v43.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-memdb v1.3.4 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect @@ -85,7 +87,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -98,43 +100,35 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/sagikazarmark/locafero v0.3.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/samber/lo v1.38.1 // indirect github.com/scylladb/go-set v1.0.2 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.10.0 // indirect - github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/viper v1.17.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/viper v1.18.1 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect - go.opentelemetry.io/contrib/propagators/b3 v1.20.0 // indirect - go.opentelemetry.io/contrib/propagators/ot v1.20.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/jaeger v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/sdk v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 08e7c40f..3e17dee6 100644 --- a/go.sum +++ b/go.sum @@ -3,57 +3,20 @@ buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.31.0-20210810001428-4df00b2 buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.31.0-20231010075520-899dbbfd2c07.1 h1:8sro2hoT2tEgwixyAFJnj+54LbyXjWU3kt6/lcNTDNY= buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.31.0-20231010075520-899dbbfd2c07.1/go.mod h1:iqW5nSujn3ZJ9ISZQX3K/uWwjckAp8hz0J4/wNgFBZo= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v1.1.2 h1:gacbrBdWcoVmGLozRuStX45YKvJtzIjJdAolzUs1sm4= -cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/spanner v1.51.0 h1:l3exhhsVMKsx1E7Xd1QajYSvHmI1KZoWPW5tRxIIdvQ= -cloud.google.com/go/spanner v1.51.0/go.mod h1:c5KNo5LQ1X5tJwma9rSQZsXNBDNvj4/n8BVc3LNahq0= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= +cloud.google.com/go/spanner v1.53.0 h1:/NzWQJ1MEhdRcffiutRKbW/AIGVKhcTeivWTDjEyCCo= +cloud.google.com/go/spanner v1.53.0/go.mod h1:liG4iCeLqm5L3fFLU5whFITqP0e0orsAW1uUSrd4rws= contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= @@ -61,7 +24,6 @@ github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTB github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/IBM/pgxpoolprometheus v1.1.1 h1:xkWNUe87TIuBj/ypdSiDgNYktsuM7MoZCT8a+kjhh2s= github.com/IBM/pgxpoolprometheus v1.1.1/go.mod h1:GFJDkHbidFfB2APbhBTSy2X4PKH3bLWsEMBhmzK1ipo= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= @@ -80,8 +42,8 @@ github.com/authzed/consistent v0.1.0 h1:tlh1wvKoRbjRhMm2P+X5WQQyR54SRoS4MyjLOg17 github.com/authzed/consistent v0.1.0/go.mod h1:plwHlrN/EJUCwQ+Bca0MhM1KnisPs7HEkZI5giCXrcc= github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 h1:bQeIwWWRI9bl93poTqpix4sYHi+gnXUPK7N6bMtXzBE= github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403/go.mod h1:s3qC7V7XIbiNWERv7Lfljy/Lx25/V1Qlexb0WJuA8uQ= -github.com/authzed/spicedb v1.27.0-rc1 h1:0LzBRvvo74yOMtqlGcB/NGtwtysA0IISF764tzHAkng= -github.com/authzed/spicedb v1.27.0-rc1/go.mod h1:0E/tE/YV8+7w6I2sIUv0kOETIyWmWXdNGnTqfXvdXBo= +github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da h1:eH0+PGHu6A3S3OYsIG7kNu5VLeUHdcPsZOk92rGPn30= +github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da/go.mod h1:U5rAjDSuv3Vk6vQKHCaUrL+UZrH2A16KNzpzxKQuE1Y= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -89,6 +51,10 @@ github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bloom/v3 v3.6.0 h1:dTU0OVLJSoOhz9m68FTXMFfA39nR8U/nTCs1zb26mOI= +github.com/bits-and-blooms/bloom/v3 v3.6.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg= github.com/brianvoe/gofakeit/v6 v6.22.0 h1:BzOsDot1o3cufTfOk+fWKE9nFYojyDV+XHdCWL2+uyE= github.com/brianvoe/gofakeit/v6 v6.22.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= @@ -102,21 +68,16 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudspannerecosystem/spanner-change-streams-tail v0.3.1 h1:76zSbhqkgwt8LXoWBzZqvnKq0gfDeDrQRwMvaLfp3bM= github.com/cloudspannerecosystem/spanner-change-streams-tail v0.3.1/go.mod h1:Fb3cQgYCLKQfjsJcw+wsalU2l/eJpbtHu2UKt12p+Mk= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -145,8 +106,6 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -154,19 +113,16 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBF github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/exaring/otelpgx v0.5.2 h1:joqpJoz/HJD2hP4Rdk6CVM9O7oCQ5zWAkTalTen0ShE= github.com/exaring/otelpgx v0.5.2/go.mod h1:4dBiAqwzDNmpj3TwX5Syti1/Nw2bIoDQItdLvWTklQU= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= @@ -174,8 +130,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zerologr v1.2.3 h1:up5N9vcH9Xck3jJkXzgyOxozT14R47IyDODz8LM1KSs= @@ -195,52 +151,23 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -251,32 +178,14 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -289,10 +198,10 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8 github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/hamba/avro/v2 v2.13.0 h1:QY2uX2yvJTW0OoMKelGShvq4v1hqab6CxJrPwh0fnj0= -github.com/hamba/avro/v2 v2.13.0/go.mod h1:Q9YK+qxAhtVrNqOhwlZTATLgLA8qxG2vtvkhK8fJ7Jo= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hamba/avro/v2 v2.18.0 h1:U7T0xI8MGw9+m3SS48E2KHUxas/Hb0EvS0CpkmVcLoI= +github.com/hamba/avro/v2 v2.18.0/go.mod h1:dEG+AHrykTpkXvBYsc+XXTuRlvGC645Ix5d2qR8EdEs= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -303,7 +212,6 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -312,8 +220,6 @@ github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 h1:nqAlWFEdqI0ClbTDrhDvE/8LeQ4pftrqKUX9w5k0j3s= github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY= @@ -336,10 +242,6 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jzelinskie/cobrautil v0.0.12 h1:NEfbvkSqvHqcH384mG4JtJb/4AmTfHYM+eV99h+t9bo= -github.com/jzelinskie/cobrautil v0.0.12/go.mod h1:9tPpSZKwXyHMxcrIGH+u+8J3YiRlqqfpe4esM0ZYJzI= github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a h1:fSIkpfPYnaOLAkci6UX5fXLFpufLlLtV+0Qd87pknEQ= github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a/go.mod h1:6EEEGUlDNdP2DJ0S2gtrJ2Q/6guT3NKc2HdnadKPvRk= github.com/jzelinskie/stringz v0.0.2 h1:OSjMEYvz8tjhovgZ/6cGcPID736ubeukr35mu6RYAmg= @@ -352,7 +254,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -377,16 +278,15 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= @@ -425,7 +325,6 @@ github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdU github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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= @@ -434,17 +333,16 @@ github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+L github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= @@ -453,14 +351,14 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= -github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE= -github.com/schollz/progressbar/v3 v3.13.1/go.mod h1:xvrbki8kfT1fzWzBT/UZd9L6GA+jdL7HAgq2RFnO6fQ= +github.com/schollz/progressbar/v3 v3.14.1 h1:VD+MJPCr4s3wdhTc7OEJ/Z3dAeBzJ7yKH/P4lC5yRTI= +github.com/schollz/progressbar/v3 v3.14.1/go.mod h1:Zc9xXneTzWXF81TGoqL71u0sBPjULtEHYtj/WVgVy8E= github.com/scylladb/go-set v1.0.2 h1:SkvlMCKhP0wyyct6j+0IHJkBkSZL+TDzZ4E7f7BCcRE= github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/sysexits v1.0.0 h1:FLf1xcUTBzTqUI1Nc77UwYPcoWgDM09lyMTt8+QCpbE= @@ -470,16 +368,16 @@ github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= -github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= -github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +github.com/spf13/viper v1.18.1 h1:rmuU42rScKWlhhJDyXZRKJQHXFX02chSVW1IvkPGiVM= +github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -491,7 +389,6 @@ github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdr github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -502,47 +399,39 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= +github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 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.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 h1:1eHu3/pUSWaOgltNK3WJFaywKsTIr/PwvHyDmi0lQA0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0/go.mod h1:HyABWq60Uy1kjJSa2BVOxUVao8Cdick5AWSKPutqy6U= go.opentelemetry.io/contrib/propagators/b3 v1.20.0 h1:Yty9Vs4F3D6/liF1o6FNt0PvN85h/BJJ6DQKJ3nrcM0= go.opentelemetry.io/contrib/propagators/b3 v1.20.0/go.mod h1:On4VgbkqYL18kbJlWsa18+cMNe6rYpBnPi1ARI/BrsU= go.opentelemetry.io/contrib/propagators/ot v1.20.0 h1:duH7mgL6VGQH7e7QEAVOFkCQXWpCb4PjTtrhdrYrJRQ= go.opentelemetry.io/contrib/propagators/ot v1.20.0/go.mod h1:gijQzxOq0JLj9lyZhTvqjDddGV/zaNagpPIn+2r8CEI= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/exporters/jaeger v1.16.0 h1:YhxxmXZ011C0aDZKoNw+juVWAmEfv/0W2XBOv9aHTaA= -go.opentelemetry.io/otel/exporters/jaeger v1.16.0/go.mod h1:grYbBo/5afWlPpdPZYhyn78Bk04hnvxn2+hvxQhKIQM= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM= +go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -556,230 +445,86 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8= +golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= 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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -787,106 +532,28 @@ 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-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= -google.golang.org/api v0.147.0/go.mod h1:pQ/9j83DcmPd/5C9e2nFOdjjNkDZ1G+zkbK2uvdkJMs= +google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= 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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a h1:fwgW9j3vHirt4ObdHoYNwuO24BEZjSzbh+zPaNWoiY8= -google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:EMfReVxb80Dq1hhioy0sOsY9jCE46YDgHlJ7fWVUWRE= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -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= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -896,7 +563,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= @@ -910,12 +576,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= @@ -930,9 +591,6 @@ k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrC k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= resenje.org/singleflight v0.4.0 h1:NdOEhCxEikK2S2WxGjZV9EGSsItolQKslOOi6pE1tJc= resenje.org/singleflight v0.4.0/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 28bf91f7..d325fa66 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -5,9 +5,14 @@ import ( "fmt" "io" "os" + "regexp" + "strings" "time" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/authzed/spicedb/pkg/schemadsl/compiler" + "github.com/authzed/spicedb/pkg/schemadsl/generator" + "github.com/jzelinskie/cobrautil/v2" "github.com/mattn/go-isatty" "github.com/rs/zerolog/log" "github.com/schollz/progressbar/v3" @@ -19,6 +24,7 @@ import ( func registerBackupCmd(rootCmd *cobra.Command) { rootCmd.AddCommand(backupCmd) + backupCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") } var backupCmd = &cobra.Command{ @@ -48,6 +54,52 @@ func createBackupFile(filename string) (*os.File, error) { return f, nil } +var ( + missingAllowedTypes = regexp.MustCompile(`(\s*)(relation)(.+)(\/\* missing allowed types \*\/)(.*)`) + shortRelations = regexp.MustCompile(`(\s*)relation [a-z][a-z0-9_]:(.+)`) +) + +func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) { + // Remove any invalid relations generated from old, backwards-incompat + // Serverless permission systems. + schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) + schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) + + compiledSchema, err := compiler.Compile(compiler.InputSchema{Source: "schema", SchemaString: schema}, compiler.SkipValidation()) + if err != nil { + return "", fmt.Errorf("error reading schema: %w", err) + } + + var prefixedDefs []compiler.SchemaDefinition + for _, def := range compiledSchema.ObjectDefinitions { + if strings.HasPrefix(def.Name, prefix) { + prefixedDefs = append(prefixedDefs, def) + } + } + + for _, def := range compiledSchema.CaveatDefinitions { + if strings.HasPrefix(def.Name, prefix) { + prefixedDefs = append(prefixedDefs, def) + } + } + + if len(prefixedDefs) == 0 { + return "", errors.New("filtered all definitions from schema") + } + + filteredSchema, _, err = generator.GenerateSchema(prefixedDefs) + if err != nil { + return "", fmt.Errorf("error generating filtered schema: %w", err) + } + return +} + +func hasRelPrefix(rel *v1.Relationship, prefix string) bool { + // Skip any relationships without the prefix on either side. + return strings.HasPrefix(rel.Resource.ObjectType, prefix) || + strings.HasPrefix(rel.Subject.Object.ObjectType, prefix) +} + func backupCmdFunc(cmd *cobra.Command, args []string) error { f, err := createBackupFile(args[0]) if err != nil { @@ -78,7 +130,17 @@ func backupCmdFunc(cmd *cobra.Command, args []string) error { return fmt.Errorf("`backup` is not supported on this version of SpiceDB") } - encoder, err := backupformat.NewEncoder(relWriter, schemaResp.SchemaText, schemaResp.ReadAt) + // Skip any definitions without the provided prefix + schema := schemaResp.SchemaText + prefixFilter := cobrautil.MustGetString(cmd, "prefix-filter") + if prefixFilter != "" { + schema, err = filterSchemaDefs(schema, prefixFilter) + if err != nil { + return err + } + } + + encoder, err := backupformat.NewEncoder(relWriter, schema, schemaResp.ReadAt) if err != nil { return fmt.Errorf("error creating backup file encoder: %w", err) } @@ -111,6 +173,10 @@ func backupCmdFunc(cmd *cobra.Command, args []string) error { } for _, rel := range relsResp.Relationships { + if !hasRelPrefix(rel, prefixFilter) { + continue + } + if err := encoder.Append(rel); err != nil { return fmt.Errorf("error storing relationship: %w", err) } diff --git a/internal/cmd/restore.go b/internal/cmd/restore.go index 7a270d0f..1cc19e46 100644 --- a/internal/cmd/restore.go +++ b/internal/cmd/restore.go @@ -22,6 +22,7 @@ func registerRestoreCmd(rootCmd *cobra.Command) { restoreCmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") restoreCmd.Flags().Int("batches-per-transaction", 10, "number of batches per transaction") restoreCmd.Flags().Bool("print-zedtoken-only", false, "just print the zedtoken and stop") + restoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") } var restoreCmd = &cobra.Command{ @@ -95,14 +96,23 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { ctx := cmd.Context() + schema := decoder.Schema() + prefixFilter := cobrautil.MustGetString(cmd, "prefix-filter") + if prefixFilter != "" { + schema, err = filterSchemaDefs(schema, prefixFilter) + if err != nil { + return err + } + } + + log.Debug().Str("schema", schema).Msg("writing schema") + if _, err := client.WriteSchema(ctx, &v1.WriteSchemaRequest{ - Schema: decoder.Schema(), + Schema: schema, }); err != nil { return fmt.Errorf("unable to write schema: %w", err) } - log.Debug().Msg("schema written") - relationshipWriteStart := time.Now() relationshipWriter, err := client.BulkImportRelationships(ctx) @@ -121,6 +131,10 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { return fmt.Errorf("aborted restore: %w", err) } + if !hasRelPrefix(rel, prefixFilter) { + continue + } + batch = append(batch, rel) if len(batch)%batchSize == 0 { diff --git a/internal/cmd/schema.go b/internal/cmd/schema.go index db42f949..75da0379 100644 --- a/internal/cmd/schema.go +++ b/internal/cmd/schema.go @@ -187,7 +187,7 @@ func rewriteSchema(existingSchemaText string, definitionPrefix string) (string, compiled, err := compiler.Compile(compiler.InputSchema{ Source: input.Source("schema"), SchemaString: existingSchemaText, - }, &definitionPrefix) + }, compiler.ObjectTypePrefix(&definitionPrefix), compiler.SkipValidation()) if err != nil { return "", err } @@ -223,10 +223,9 @@ func determinePrefixForSchema(ctx context.Context, specifiedPrefix string, clien } // Otherwise, compile the schema and grab the prefixes of the namespaces defined. - empty := "" found, err := compiler.Compile(compiler.InputSchema{ Source: input.Source("schema"), SchemaString: schemaText, - }, &empty) + }, compiler.SkipValidation()) if err != nil { return "", err } diff --git a/pkg/backupformat/decoder.go b/pkg/backupformat/decoder.go index 53c9a368..66d23e64 100644 --- a/pkg/backupformat/decoder.go +++ b/pkg/backupformat/decoder.go @@ -4,14 +4,21 @@ import ( "errors" "fmt" "io" - "reflect" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/hamba/avro/v2" "github.com/hamba/avro/v2/ocf" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" ) +func init() { + // This defaults to a 1MiB limit, but large schemas can exceed this size. + avro.DefaultConfig = avro.Config{ + MaxByteSliceSize: 1024 * 1024 * 100, // 100 MiB + }.Freeze() +} + func NewDecoder(r io.Reader) (*Decoder, error) { dec, err := ocf.NewDecoder(r) if err != nil { @@ -36,8 +43,7 @@ func NewDecoder(r io.Reader) (*Decoder, error) { schema, ok := decodedSchema.(SchemaV1) if !ok { - schemaType := reflect.TypeOf(decodedSchema) - return nil, fmt.Errorf("received schema object of wrong type: %s", schemaType.Name()) + return nil, fmt.Errorf("received schema object of wrong type: %T", decodedSchema) } schemaText = schema.SchemaText } else { From ff9c3cdb97427cc02c1e77251a9a9486fcb97d07 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Fri, 8 Dec 2023 11:38:23 -0500 Subject: [PATCH 04/49] cmd: reorg commands under backup, add parsing --- go.mod | 2 +- go.sum | 4 +- internal/cmd/backup.go | 304 ++++++++++++++++++++++++++++++++++++++-- internal/cmd/cmd.go | 1 - internal/cmd/restore.go | 203 --------------------------- 5 files changed, 293 insertions(+), 221 deletions(-) delete mode 100644 internal/cmd/restore.go diff --git a/go.mod b/go.mod index c3f1fe5c..4fb003e1 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/gookit/color v1.5.4 github.com/hamba/avro/v2 v2.18.0 github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a - github.com/jzelinskie/stringz v0.0.2 + github.com/jzelinskie/stringz v0.0.3 github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.5 diff --git a/go.sum b/go.sum index 3e17dee6..89ec8693 100644 --- a/go.sum +++ b/go.sum @@ -244,8 +244,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a h1:fSIkpfPYnaOLAkci6UX5fXLFpufLlLtV+0Qd87pknEQ= github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a/go.mod h1:6EEEGUlDNdP2DJ0S2gtrJ2Q/6guT3NKc2HdnadKPvRk= -github.com/jzelinskie/stringz v0.0.2 h1:OSjMEYvz8tjhovgZ/6cGcPID736ubeukr35mu6RYAmg= -github.com/jzelinskie/stringz v0.0.2/go.mod h1:hHYbgxJuNLRw91CmpuFsYEOyQqpDVFg8pvEh23vy4P0= +github.com/jzelinskie/stringz v0.0.3 h1:0GhG3lVMYrYtIvRbxvQI6zqRTT1P1xyQlpa0FhfUXas= +github.com/jzelinskie/stringz v0.0.3/go.mod h1:hHYbgxJuNLRw91CmpuFsYEOyQqpDVFg8pvEh23vy4P0= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index d325fa66..3e68aef1 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -22,16 +22,36 @@ import ( "github.com/authzed/zed/pkg/backupformat" ) +var backupCmd = &cobra.Command{ + Use: "backup ", + Short: "create, restore, and inspect Permissions System backups", +} + func registerBackupCmd(rootCmd *cobra.Command) { rootCmd.AddCommand(backupCmd) - backupCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") + + backupCmd.AddCommand(backupCreateCmd) + backupCreateCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") + backupCreateCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") + + backupCmd.AddCommand(backupRestoreCmd) + backupRestoreCmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") + backupRestoreCmd.Flags().Int("batches-per-transaction", 10, "number of batches per transaction") + backupRestoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") + backupRestoreCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") + + backupCmd.AddCommand(backupParseSchemaCmd) + backupParseSchemaCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") + backupParseSchemaCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") + + backupCmd.AddCommand(backupParseRevisionCmd) } -var backupCmd = &cobra.Command{ - Use: "backup ", +var backupCreateCmd = &cobra.Command{ + Use: "create ", Short: "Backup a permission system to a file", Args: cobra.ExactArgs(1), - RunE: backupCmdFunc, + RunE: backupCreateCmdFunc, } func createBackupFile(filename string) (*os.File, error) { @@ -59,12 +79,11 @@ var ( shortRelations = regexp.MustCompile(`(\s*)relation [a-z][a-z0-9_]:(.+)`) ) -func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) { - // Remove any invalid relations generated from old, backwards-incompat - // Serverless permission systems. - schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) - schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) +func partialPrefixMatch(name, prefix string) bool { + return strings.HasPrefix(name, prefix+"/") +} +func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) { compiledSchema, err := compiler.Compile(compiler.InputSchema{Source: "schema", SchemaString: schema}, compiler.SkipValidation()) if err != nil { return "", fmt.Errorf("error reading schema: %w", err) @@ -72,13 +91,12 @@ func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) var prefixedDefs []compiler.SchemaDefinition for _, def := range compiledSchema.ObjectDefinitions { - if strings.HasPrefix(def.Name, prefix) { + if partialPrefixMatch(def.Name, prefix) { prefixedDefs = append(prefixedDefs, def) } } - for _, def := range compiledSchema.CaveatDefinitions { - if strings.HasPrefix(def.Name, prefix) { + if partialPrefixMatch(def.Name, prefix) { prefixedDefs = append(prefixedDefs, def) } } @@ -100,7 +118,7 @@ func hasRelPrefix(rel *v1.Relationship, prefix string) bool { strings.HasPrefix(rel.Subject.Object.ObjectType, prefix) } -func backupCmdFunc(cmd *cobra.Command, args []string) error { +func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { f, err := createBackupFile(args[0]) if err != nil { return err @@ -129,9 +147,16 @@ func backupCmdFunc(cmd *cobra.Command, args []string) error { if schemaResp.ReadAt == nil { return fmt.Errorf("`backup` is not supported on this version of SpiceDB") } + schema := schemaResp.SchemaText + + // Remove any invalid relations generated from old, backwards-incompat + // Serverless permission systems. + if cobrautil.MustGetBool(cmd, "rewrite-legacy") { + schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) + schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) + } // Skip any definitions without the provided prefix - schema := schemaResp.SchemaText prefixFilter := cobrautil.MustGetString(cmd, "prefix-filter") if prefixFilter != "" { schema, err = filterSchemaDefs(schema, prefixFilter) @@ -213,3 +238,254 @@ func backupCmdFunc(cmd *cobra.Command, args []string) error { return nil } + +var backupRestoreCmd = &cobra.Command{ + Use: "restore ", + Short: "Restore a permission system from a file", + Args: cobra.MaximumNArgs(1), + RunE: restoreCmdFunc, +} + +func openRestoreFile(filename string) (*os.File, int64, error) { + if filename == "" { + log.Trace().Str("filename", "(stdin)").Send() + return os.Stdin, -1, nil + } + + log.Trace().Str("filename", filename).Send() + + stats, err := os.Stat(filename) + if err != nil { + return nil, 0, fmt.Errorf("unable to stat restore file: %w", err) + } + + f, err := os.Open(filename) + if err != nil { + return nil, 0, fmt.Errorf("unable to open restore file: %w", err) + } + + return f, stats.Size(), nil +} + +func restoreCmdFunc(cmd *cobra.Command, args []string) error { + filename := "" // Default to stdin. + if len(args) > 0 { + filename = args[0] + } + + f, fSize, err := openRestoreFile(filename) + if err != nil { + return err + } + + var hasProgressbar bool + var restoreReader io.Reader = f + if isatty.IsTerminal(os.Stderr.Fd()) { + bar := progressbar.DefaultBytes(fSize, "restoring") + restoreReader = io.TeeReader(f, bar) + hasProgressbar = true + } + + decoder, err := backupformat.NewDecoder(restoreReader) + if err != nil { + return fmt.Errorf("error creating restore file decoder: %w", err) + } + + if loadedToken := decoder.ZedToken(); loadedToken != nil { + log.Debug().Str("revision", loadedToken.Token).Msg("parsed revision") + } + + schema := decoder.Schema() + + // Remove any invalid relations generated from old, backwards-incompat + // Serverless permission systems. + if cobrautil.MustGetBool(cmd, "rewrite-legacy") { + schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) + schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) + } + + // Skip any definitions without the provided prefix + prefixFilter := cobrautil.MustGetString(cmd, "prefix-filter") + if prefixFilter != "" { + schema, err = filterSchemaDefs(schema, prefixFilter) + if err != nil { + return err + } + } + log.Debug().Str("schema", schema).Bool("filtered", prefixFilter != "").Msg("parsed schema") + + client, err := client.NewClient(cmd) + if err != nil { + return fmt.Errorf("unable to initialize client: %w", err) + } + + ctx := cmd.Context() + if _, err := client.WriteSchema(ctx, &v1.WriteSchemaRequest{ + Schema: schema, + }); err != nil { + return fmt.Errorf("unable to write schema: %w", err) + } + + relationshipWriteStart := time.Now() + + relationshipWriter, err := client.BulkImportRelationships(ctx) + if err != nil { + return fmt.Errorf("error creating writer stream: %w", err) + } + + batchSize := cobrautil.MustGetInt(cmd, "batch-size") + batchesPerTransaction := cobrautil.MustGetInt(cmd, "batches-per-transaction") + + batch := make([]*v1.Relationship, 0, batchSize) + var written uint64 + var batchesWritten int + for rel, err := decoder.Next(); rel != nil && err == nil; rel, err = decoder.Next() { + if err := ctx.Err(); err != nil { + return fmt.Errorf("aborted restore: %w", err) + } + + if !hasRelPrefix(rel, prefixFilter) { + continue + } + + batch = append(batch, rel) + + if len(batch)%batchSize == 0 { + if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ + Relationships: batch, + }); err != nil { + return fmt.Errorf("error sending batch to server: %w", err) + } + + // Reset the relationships in the batch + batch = batch[:0] + + batchesWritten++ + + if batchesWritten%batchesPerTransaction == 0 { + resp, err := relationshipWriter.CloseAndRecv() + if err != nil { + return fmt.Errorf("error finalizing write of %d batches: %w", batchesPerTransaction, err) + } + if !hasProgressbar { + log.Debug().Uint64("relationships", written).Msg("relationships written") + } + written += resp.NumLoaded + + relationshipWriter, err = client.BulkImportRelationships(ctx) + if err != nil { + return fmt.Errorf("error creating new writer stream: %w", err) + } + } + } + } + + // Write the last batch + if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ + Relationships: batch, + }); err != nil { + return fmt.Errorf("error sending last batch to server: %w", err) + } + + // Finish the stream + resp, err := relationshipWriter.CloseAndRecv() + if err != nil { + return fmt.Errorf("error finalizing last write: %w", err) + } + + written += resp.NumLoaded + + totalTime := time.Since(relationshipWriteStart) + relsPerSec := float64(written) / totalTime.Seconds() + + log.Info(). + Uint64("relationships", written). + Stringer("duration", totalTime). + Float64("perSecond", relsPerSec). + Msg("finished restore") + + if err := decoder.Close(); err != nil { + return fmt.Errorf("error closing restore encoder: %w", err) + } + + if err := f.Close(); err != nil { + return fmt.Errorf("error closing restore file: %w", err) + } + + return nil +} + +var backupParseSchemaCmd = &cobra.Command{ + Use: "parse-schema ", + Short: "Extract the schema from a backup file", + Args: cobra.ExactArgs(1), + RunE: backupParseSchemaCmdFunc, +} + +func backupParseSchemaCmdFunc(cmd *cobra.Command, args []string) error { + filename := "" // Default to stdin. + if len(args) > 0 { + filename = args[0] + } + + f, _, err := openRestoreFile(filename) + if err != nil { + return err + } + + decoder, err := backupformat.NewDecoder(f) + if err != nil { + return fmt.Errorf("error creating restore file decoder: %w", err) + } + schema := decoder.Schema() + + // Remove any invalid relations generated from old, backwards-incompat + // Serverless permission systems. + if cobrautil.MustGetBool(cmd, "rewrite-legacy") { + schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) + schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) + } + + // Skip any definitions without the provided prefix + if prefixFilter := cobrautil.MustGetString(cmd, "prefix-filter"); prefixFilter != "" { + schema, err = filterSchemaDefs(schema, prefixFilter) + if err != nil { + return err + } + } + + fmt.Println(schema) + return nil +} + +var backupParseRevisionCmd = &cobra.Command{ + Use: "parse-revision ", + Short: "Extract the revision from a backup file", + Args: cobra.ExactArgs(1), + RunE: backupParseRevisionCmdFunc, +} + +func backupParseRevisionCmdFunc(_ *cobra.Command, args []string) error { + filename := "" // Default to stdin. + if len(args) > 0 { + filename = args[0] + } + + f, _, err := openRestoreFile(filename) + if err != nil { + return err + } + + decoder, err := backupformat.NewDecoder(f) + if err != nil { + return fmt.Errorf("error creating restore file decoder: %w", err) + } + + loadedToken := decoder.ZedToken() + if loadedToken == nil { + return fmt.Errorf("failed to parse decoded revision") + } + + fmt.Println(loadedToken.Token) + return nil +} diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 1112993d..ceeea7fe 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -63,7 +63,6 @@ func Run() { registerImportCmd(rootCmd) registerValidateCmd(rootCmd) registerBackupCmd(rootCmd) - registerRestoreCmd(rootCmd) // Register shared commands. commands.RegisterPermissionCmd(rootCmd) diff --git a/internal/cmd/restore.go b/internal/cmd/restore.go deleted file mode 100644 index 1cc19e46..00000000 --- a/internal/cmd/restore.go +++ /dev/null @@ -1,203 +0,0 @@ -package cmd - -import ( - "fmt" - "io" - "os" - "time" - - v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" - "github.com/jzelinskie/cobrautil" - "github.com/mattn/go-isatty" - "github.com/rs/zerolog/log" - "github.com/schollz/progressbar/v3" - "github.com/spf13/cobra" - - "github.com/authzed/zed/internal/client" - "github.com/authzed/zed/pkg/backupformat" -) - -func registerRestoreCmd(rootCmd *cobra.Command) { - rootCmd.AddCommand(restoreCmd) - restoreCmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") - restoreCmd.Flags().Int("batches-per-transaction", 10, "number of batches per transaction") - restoreCmd.Flags().Bool("print-zedtoken-only", false, "just print the zedtoken and stop") - restoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") -} - -var restoreCmd = &cobra.Command{ - Use: "restore ", - Short: "Restore a permission system from a file", - Args: cobra.MaximumNArgs(1), - RunE: restoreCmdFunc, -} - -func openRestoreFile(filename string) (*os.File, int64, error) { - if filename == "" { - log.Trace().Str("filename", "(stdin)").Send() - return os.Stdin, -1, nil - } - - log.Trace().Str("filename", filename).Send() - - stats, err := os.Stat(filename) - if err != nil { - return nil, 0, fmt.Errorf("unable to stat restore file: %w", err) - } - - f, err := os.Open(filename) - if err != nil { - return nil, 0, fmt.Errorf("unable to open restore file: %w", err) - } - - return f, stats.Size(), nil -} - -func restoreCmdFunc(cmd *cobra.Command, args []string) error { - filename := "" // Default to stdin. - - if len(args) > 0 { - filename = args[0] - } - - f, fSize, err := openRestoreFile(filename) - if err != nil { - return err - } - - printZTOnly := cobrautil.MustGetBool(cmd, "print-zedtoken-only") - - var hasProgressbar bool - var restoreReader io.Reader = f - if isatty.IsTerminal(os.Stderr.Fd()) && !printZTOnly { - bar := progressbar.DefaultBytes(fSize, "restoring") - restoreReader = io.TeeReader(f, bar) - hasProgressbar = true - } - - decoder, err := backupformat.NewDecoder(restoreReader) - if err != nil { - return fmt.Errorf("error creating restore file decoder: %w", err) - } - - if loadedToken := decoder.ZedToken(); loadedToken != nil { - log.Info().Str("token", loadedToken.Token).Msg("printing ZedToken to stdout") - fmt.Println(loadedToken.Token) - } - - if printZTOnly { - return nil - } - - client, err := client.NewClient(cmd) - if err != nil { - return fmt.Errorf("unable to initialize client: %w", err) - } - - ctx := cmd.Context() - - schema := decoder.Schema() - prefixFilter := cobrautil.MustGetString(cmd, "prefix-filter") - if prefixFilter != "" { - schema, err = filterSchemaDefs(schema, prefixFilter) - if err != nil { - return err - } - } - - log.Debug().Str("schema", schema).Msg("writing schema") - - if _, err := client.WriteSchema(ctx, &v1.WriteSchemaRequest{ - Schema: schema, - }); err != nil { - return fmt.Errorf("unable to write schema: %w", err) - } - - relationshipWriteStart := time.Now() - - relationshipWriter, err := client.BulkImportRelationships(ctx) - if err != nil { - return fmt.Errorf("error creating writer stream: %w", err) - } - - batchSize := cobrautil.MustGetInt(cmd, "batch-size") - batchesPerTransaction := cobrautil.MustGetInt(cmd, "batches-per-transaction") - - batch := make([]*v1.Relationship, 0, batchSize) - var written uint64 - var batchesWritten int - for rel, err := decoder.Next(); rel != nil && err == nil; rel, err = decoder.Next() { - if err := ctx.Err(); err != nil { - return fmt.Errorf("aborted restore: %w", err) - } - - if !hasRelPrefix(rel, prefixFilter) { - continue - } - - batch = append(batch, rel) - - if len(batch)%batchSize == 0 { - if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ - Relationships: batch, - }); err != nil { - return fmt.Errorf("error sending batch to server: %w", err) - } - - // Reset the relationships in the batch - batch = batch[:0] - - batchesWritten++ - - if batchesWritten%batchesPerTransaction == 0 { - resp, err := relationshipWriter.CloseAndRecv() - if err != nil { - return fmt.Errorf("error finalizing write of %d batches: %w", batchesPerTransaction, err) - } - if !hasProgressbar { - log.Debug().Uint64("relationships", written).Msg("relationships written") - } - written += resp.NumLoaded - - relationshipWriter, err = client.BulkImportRelationships(ctx) - if err != nil { - return fmt.Errorf("error creating new writer stream: %w", err) - } - } - } - } - - // Write the last batch - if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ - Relationships: batch, - }); err != nil { - return fmt.Errorf("error sending last batch to server: %w", err) - } - - // Finish the stream - resp, err := relationshipWriter.CloseAndRecv() - if err != nil { - return fmt.Errorf("error finalizing last write: %w", err) - } - - written += resp.NumLoaded - - totalTime := time.Since(relationshipWriteStart) - relsPerSec := float64(written) / totalTime.Seconds() - - log.Info(). - Uint64("relationships", written). - Stringer("duration", totalTime). - Float64("perSecond", relsPerSec). - Msg("finished restore") - - if err := decoder.Close(); err != nil { - return fmt.Errorf("error closing restore encoder: %w", err) - } - - if err := f.Close(); err != nil { - return fmt.Errorf("error closing restore file: %w", err) - } - - return nil -} From cbbeaad1561798c9cd2b6af6442baec26af40a27 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Fri, 8 Dec 2023 12:05:39 -0500 Subject: [PATCH 05/49] backup: report when batches fail on restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if one of the batches sent fails, zed will hide the underlying error and just report EOF. The gRPC backend will report EOF as part of an error, which will have to eb retrieved via CloseAndRecv(). A common error that surfaced as EOF was duplicate relationships after reimporting the same backup file. Closes #310. Co-authored-by: Víctor Roldán Betancort --- internal/cmd/backup.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 3e68aef1..696eca60 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -354,7 +354,8 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ Relationships: batch, }); err != nil { - return fmt.Errorf("error sending batch to server: %w", err) + _, closeErr := relationshipWriter.CloseAndRecv() + return fmt.Errorf("error sending batch to server: %w", errors.Join(err, closeErr)) } // Reset the relationships in the batch From 1e1dcd2fe49a29493b371bd63a393e3594e829fe Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Mon, 11 Dec 2023 18:12:09 -0500 Subject: [PATCH 06/49] backup: validate typesystem of generated schemas --- internal/cmd/backup.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 696eca60..c27656cb 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "errors" "fmt" "io" @@ -12,6 +13,7 @@ import ( v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/pkg/schemadsl/compiler" "github.com/authzed/spicedb/pkg/schemadsl/generator" + "github.com/authzed/spicedb/pkg/typesystem" "github.com/jzelinskie/cobrautil/v2" "github.com/mattn/go-isatty" "github.com/rs/zerolog/log" @@ -109,6 +111,23 @@ func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) if err != nil { return "", fmt.Errorf("error generating filtered schema: %w", err) } + + // Validate that the type system for the generated schema is comprehensive. + compiledFilteredSchema, err := compiler.Compile(compiler.InputSchema{Source: "generated-schema", SchemaString: filteredSchema}) + if err != nil { + return "", fmt.Errorf("generated invalid schema: %w", err) + } + + for _, def := range compiledFilteredSchema.ObjectDefinitions { + ts, err := typesystem.NewNamespaceTypeSystem(def, typesystem.ResolverForSchema(*compiledFilteredSchema)) + if err != nil { + return "", fmt.Errorf("generated invalid schema: %w", err) + } + if _, err := ts.Validate(context.Background()); err != nil { + return "", fmt.Errorf("generated invalid schema: %w", err) + } + } + return } From 9a08a1201d2f2840b4c951f856d1d9f7a8a02264 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Tue, 12 Dec 2023 13:29:19 -0500 Subject: [PATCH 07/49] cmd/backup: add parse-relationships --- internal/cmd/backup.go | 77 +++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index c27656cb..31bc604d 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -13,6 +13,7 @@ import ( v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/pkg/schemadsl/compiler" "github.com/authzed/spicedb/pkg/schemadsl/generator" + "github.com/authzed/spicedb/pkg/tuple" "github.com/authzed/spicedb/pkg/typesystem" "github.com/jzelinskie/cobrautil/v2" "github.com/mattn/go-isatty" @@ -47,6 +48,8 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupParseSchemaCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") backupCmd.AddCommand(backupParseRevisionCmd) + backupCmd.AddCommand(backupParseRelsCmd) + backupParseRelsCmd.Flags().String("prefix-filter", "", "Include only relationships with a given prefix") } var backupCreateCmd = &cobra.Command{ @@ -132,8 +135,8 @@ func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) } func hasRelPrefix(rel *v1.Relationship, prefix string) bool { - // Skip any relationships without the prefix on either side. - return strings.HasPrefix(rel.Resource.ObjectType, prefix) || + // Skip any relationships without the prefix on both sides. + return strings.HasPrefix(rel.Resource.ObjectType, prefix) && strings.HasPrefix(rel.Subject.Object.ObjectType, prefix) } @@ -149,21 +152,10 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { } ctx := cmd.Context() - schemaResp, err := client.ReadSchema(ctx, &v1.ReadSchemaRequest{}) if err != nil { return fmt.Errorf("error reading schema: %w", err) - } - - var hasProgressbar bool - var relWriter io.Writer = f - if isatty.IsTerminal(os.Stderr.Fd()) { - bar := progressbar.DefaultBytes(-1, "backing up") - relWriter = io.MultiWriter(bar, f) - hasProgressbar = true - } - - if schemaResp.ReadAt == nil { + } else if schemaResp.ReadAt == nil { return fmt.Errorf("`backup` is not supported on this version of SpiceDB") } schema := schemaResp.SchemaText @@ -184,6 +176,14 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { } } + var hasProgressbar bool + var relWriter io.Writer = f + if isatty.IsTerminal(os.Stderr.Fd()) { + bar := progressbar.DefaultBytes(-1, "backing up") + relWriter = io.MultiWriter(bar, f) + hasProgressbar = true + } + encoder, err := backupformat.NewEncoder(relWriter, schema, schemaResp.ReadAt) if err != nil { return fmt.Errorf("error creating backup file encoder: %w", err) @@ -202,7 +202,7 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { relationshipReadStart := time.Now() - var stored uint + var processed uint for { if err := ctx.Err(); err != nil { return fmt.Errorf("aborted backup: %w", err) @@ -224,19 +224,19 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { if err := encoder.Append(rel); err != nil { return fmt.Errorf("error storing relationship: %w", err) } - stored++ + processed++ - if stored%100_000 == 0 && !hasProgressbar { - log.Trace().Uint("relationships", stored).Msg("relationships stored") + if processed%100_000 == 0 && !hasProgressbar { + log.Trace().Uint("relationships", processed).Msg("relationships stored") } } } totalTime := time.Since(relationshipReadStart) - relsPerSec := float64(stored) / totalTime.Seconds() + relsPerSec := float64(processed) / totalTime.Seconds() log.Info(). - Uint("relationships", stored). + Uint("relationships", processed). Stringer("duration", totalTime). Float64("perSecond", relsPerSec). Msg("finished backup") @@ -509,3 +509,40 @@ func backupParseRevisionCmdFunc(_ *cobra.Command, args []string) error { fmt.Println(loadedToken.Token) return nil } + +var backupParseRelsCmd = &cobra.Command{ + Use: "parse-relationships ", + Short: "Extract the relationships from a backup file", + Args: cobra.ExactArgs(1), + RunE: backupParseRelsCmdFunc, +} + +func backupParseRelsCmdFunc(cmd *cobra.Command, args []string) error { + filename := "" // Default to stdin. + if len(args) > 0 { + filename = args[0] + } + + f, _, err := openRestoreFile(filename) + if err != nil { + return err + } + + decoder, err := backupformat.NewDecoder(f) + if err != nil { + return fmt.Errorf("error creating restore file decoder: %w", err) + } + + for rel, err := decoder.Next(); rel != nil && err == nil; rel, err = decoder.Next() { + if hasRelPrefix(rel, cobrautil.MustGetString(cmd, "prefix-filter")) { + relString, err := tuple.StringRelationship(rel) + if err != nil { + return err + } + relString = strings.Replace(relString, "@", " ", 1) + relString = strings.Replace(relString, "#", " ", 1) + fmt.Println(relString) + } + } + return nil +} From 099fa3807f9e24eedf17a764840e3a5bf1833484 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 14 Dec 2023 12:26:42 -0500 Subject: [PATCH 08/49] cmd/backup: add back-compat for root commands --- internal/cmd/backup.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 31bc604d..e20801af 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -26,8 +26,11 @@ import ( ) var backupCmd = &cobra.Command{ - Use: "backup ", - Short: "create, restore, and inspect Permissions System backups", + Use: "backup ", + Short: "Create, restore, and inspect Permissions System backups", + Args: cobra.ExactArgs(1), + // Create used to be on the root, so add it here for back-compat. + RunE: backupCreateCmdFunc, } func registerBackupCmd(rootCmd *cobra.Command) { @@ -43,6 +46,15 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupRestoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") backupRestoreCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") + // Restore used to be on the root, so add it there too, but hidden. + rootCmd.AddCommand(&cobra.Command{ + Use: "restore ", + Short: "Restore a permission system from a file", + Args: cobra.MaximumNArgs(1), + RunE: restoreCmdFunc, + Hidden: true, + }) + backupCmd.AddCommand(backupParseSchemaCmd) backupParseSchemaCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") backupParseSchemaCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") From 0bb1a2779181b3c0c79e5e38fc0bdab18ca48ac4 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 14 Dec 2023 15:52:54 -0500 Subject: [PATCH 09/49] cmd/backups: minor cleanups, mostly progressbar --- internal/cmd/backup.go | 243 ++++++++++++++----------- internal/commands/relationship.go | 17 +- internal/commands/relationship_test.go | 8 +- 3 files changed, 147 insertions(+), 121 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index e20801af..78d3ebd2 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -22,16 +22,54 @@ import ( "github.com/spf13/cobra" "github.com/authzed/zed/internal/client" + "github.com/authzed/zed/internal/commands" "github.com/authzed/zed/pkg/backupformat" ) -var backupCmd = &cobra.Command{ - Use: "backup ", - Short: "Create, restore, and inspect Permissions System backups", - Args: cobra.ExactArgs(1), - // Create used to be on the root, so add it here for back-compat. - RunE: backupCreateCmdFunc, -} +var ( + backupCmd = &cobra.Command{ + Use: "backup ", + Short: "Create, restore, and inspect Permissions System backups", + Args: cobra.ExactArgs(1), + // Create used to be on the root, so add it here for back-compat. + RunE: backupCreateCmdFunc, + } + + backupCreateCmd = &cobra.Command{ + Use: "create ", + Short: "Backup a permission system to a file", + Args: cobra.ExactArgs(1), + RunE: backupCreateCmdFunc, + } + + backupRestoreCmd = &cobra.Command{ + Use: "restore ", + Short: "Restore a permission system from a file", + Args: commands.StdinOrExactArgs(1), + RunE: restoreCmdFunc, + } + + backupParseSchemaCmd = &cobra.Command{ + Use: "parse-schema ", + Short: "Extract the schema from a backup file", + Args: cobra.ExactArgs(1), + RunE: backupParseSchemaCmdFunc, + } + + backupParseRevisionCmd = &cobra.Command{ + Use: "parse-revision ", + Short: "Extract the revision from a backup file", + Args: cobra.ExactArgs(1), + RunE: backupParseRevisionCmdFunc, + } + + backupParseRelsCmd = &cobra.Command{ + Use: "parse-relationships ", + Short: "Extract the relationships from a backup file", + Args: cobra.ExactArgs(1), + RunE: backupParseRelsCmdFunc, + } +) func registerBackupCmd(rootCmd *cobra.Command) { rootCmd.AddCommand(backupCmd) @@ -42,7 +80,7 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupCmd.AddCommand(backupRestoreCmd) backupRestoreCmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") - backupRestoreCmd.Flags().Int("batches-per-transaction", 10, "number of batches per transaction") + backupRestoreCmd.Flags().Int64("batches-per-transaction", 10, "number of batches per transaction") backupRestoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") backupRestoreCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") @@ -64,13 +102,6 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupParseRelsCmd.Flags().String("prefix-filter", "", "Include only relationships with a given prefix") } -var backupCreateCmd = &cobra.Command{ - Use: "create ", - Short: "Backup a permission system to a file", - Args: cobra.ExactArgs(1), - RunE: backupCreateCmdFunc, -} - func createBackupFile(filename string) (*os.File, error) { if filename == "-" { log.Trace().Str("filename", "- (stdout)").Send() @@ -152,11 +183,37 @@ func hasRelPrefix(rel *v1.Relationship, prefix string) bool { strings.HasPrefix(rel.Subject.Object.ObjectType, prefix) } -func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { +func relProgressBar(description string) *progressbar.ProgressBar { + bar := progressbar.NewOptions(-1, + progressbar.OptionSetWidth(10), + progressbar.OptionSetRenderBlankState(true), + progressbar.OptionSetVisibility(false), + ) + if isatty.IsTerminal(os.Stderr.Fd()) { + bar = progressbar.NewOptions64(-1, + progressbar.OptionSetDescription(description), + progressbar.OptionSetWriter(os.Stderr), + progressbar.OptionSetWidth(10), + progressbar.OptionThrottle(65*time.Millisecond), + progressbar.OptionShowCount(), + progressbar.OptionShowIts(), + progressbar.OptionSetItsString("relationship"), + progressbar.OptionOnCompletion(func() { fmt.Fprint(os.Stderr, "\n") }), + progressbar.OptionSpinnerType(14), + progressbar.OptionFullWidth(), + progressbar.OptionSetRenderBlankState(true), + ) + } + return bar +} + +func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) { f, err := createBackupFile(args[0]) if err != nil { return err } + defer func(e *error) { *e = errors.Join((*e), f.Close()) }(&err) + defer func(e *error) { *e = errors.Join((*e), f.Sync()) }(&err) client, err := client.NewClient(cmd) if err != nil { @@ -188,18 +245,11 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { } } - var hasProgressbar bool - var relWriter io.Writer = f - if isatty.IsTerminal(os.Stderr.Fd()) { - bar := progressbar.DefaultBytes(-1, "backing up") - relWriter = io.MultiWriter(bar, f) - hasProgressbar = true - } - - encoder, err := backupformat.NewEncoder(relWriter, schema, schemaResp.ReadAt) + encoder, err := backupformat.NewEncoder(f, schema, schemaResp.ReadAt) if err != nil { return fmt.Errorf("error creating backup file encoder: %w", err) } + defer func(e *error) { *e = errors.Join((*e), encoder.Close()) }(&err) relationshipStream, err := client.BulkExportRelationships(ctx, &v1.BulkExportRelationshipsRequest{ Consistency: &v1.Consistency{ @@ -214,7 +264,8 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { relationshipReadStart := time.Now() - var processed uint + bar := relProgressBar("processing backup") + var relsEncoded, relsProcessed uint for { if err := ctx.Err(); err != nil { return fmt.Errorf("aborted backup: %w", err) @@ -229,54 +280,41 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) error { } for _, rel := range relsResp.Relationships { - if !hasRelPrefix(rel, prefixFilter) { - continue - } + if hasRelPrefix(rel, prefixFilter) { + if err := encoder.Append(rel); err != nil { + return fmt.Errorf("error storing relationship: %w", err) + } + relsEncoded++ - if err := encoder.Append(rel); err != nil { - return fmt.Errorf("error storing relationship: %w", err) + if relsEncoded%100_000 == 0 && !isatty.IsTerminal(os.Stderr.Fd()) { + log.Trace(). + Uint("encoded", relsEncoded). + Uint("processed", relsProcessed). + Msg("backup progress") + } } - processed++ - - if processed%100_000 == 0 && !hasProgressbar { - log.Trace().Uint("relationships", processed).Msg("relationships stored") + relsProcessed++ + if err := bar.Add(1); err != nil { + return fmt.Errorf("error incrementing progress bar: %w", err) } } } - totalTime := time.Since(relationshipReadStart) - relsPerSec := float64(processed) / totalTime.Seconds() + + if err := bar.Finish(); err != nil { + return fmt.Errorf("error finalizing progress bar: %w", err) + } log.Info(). - Uint("relationships", processed). + Uint("encoded", relsEncoded). + Uint("processed", relsProcessed). + Uint64("perSecond", perSec(uint64(relsProcessed), totalTime)). Stringer("duration", totalTime). - Float64("perSecond", relsPerSec). Msg("finished backup") - if err := encoder.Close(); err != nil { - return fmt.Errorf("error closing backup encoder: %w", err) - } - - if f != os.Stdout { - if err := f.Sync(); err != nil { - return fmt.Errorf("error syncing backup file: %w", err) - } - } - - if err := f.Close(); err != nil { - return fmt.Errorf("error closing backup file: %w", err) - } - return nil } -var backupRestoreCmd = &cobra.Command{ - Use: "restore ", - Short: "Restore a permission system from a file", - Args: cobra.MaximumNArgs(1), - RunE: restoreCmdFunc, -} - func openRestoreFile(filename string) (*os.File, int64, error) { if filename == "" { log.Trace().Str("filename", "(stdin)").Send() @@ -304,23 +342,17 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { filename = args[0] } - f, fSize, err := openRestoreFile(filename) + f, _, err := openRestoreFile(filename) if err != nil { return err } + defer func(e *error) { *e = errors.Join((*e), f.Close()) }(&err) - var hasProgressbar bool - var restoreReader io.Reader = f - if isatty.IsTerminal(os.Stderr.Fd()) { - bar := progressbar.DefaultBytes(fSize, "restoring") - restoreReader = io.TeeReader(f, bar) - hasProgressbar = true - } - - decoder, err := backupformat.NewDecoder(restoreReader) + decoder, err := backupformat.NewDecoder(f) if err != nil { return fmt.Errorf("error creating restore file decoder: %w", err) } + defer func(e *error) { *e = errors.Join((*e), decoder.Close()) }(&err) if loadedToken := decoder.ZedToken(); loadedToken != nil { log.Debug().Str("revision", loadedToken.Token).Msg("parsed revision") @@ -365,11 +397,11 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { } batchSize := cobrautil.MustGetInt(cmd, "batch-size") - batchesPerTransaction := cobrautil.MustGetInt(cmd, "batches-per-transaction") + batchesPerTransaction := cobrautil.MustGetInt64(cmd, "batches-per-transaction") batch := make([]*v1.Relationship, 0, batchSize) - var written uint64 - var batchesWritten int + var written, batchesWritten int64 + bar := relProgressBar("restoring from backup") for rel, err := decoder.Next(); rel != nil && err == nil; rel, err = decoder.Next() { if err := ctx.Err(); err != nil { return fmt.Errorf("aborted restore: %w", err) @@ -391,7 +423,6 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { // Reset the relationships in the batch batch = batch[:0] - batchesWritten++ if batchesWritten%batchesPerTransaction == 0 { @@ -399,10 +430,17 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { if err != nil { return fmt.Errorf("error finalizing write of %d batches: %w", batchesPerTransaction, err) } - if !hasProgressbar { - log.Debug().Uint64("relationships", written).Msg("relationships written") + written += int64(resp.NumLoaded) + if err := bar.Set64(written); err != nil { + return fmt.Errorf("error incrementing progress bar: %w", err) + } + + if !isatty.IsTerminal(os.Stderr.Fd()) { + log.Trace(). + Int64("batches", batchesWritten). + Int64("relationships", written). + Msg("restore progress") } - written += resp.NumLoaded relationshipWriter, err = client.BulkImportRelationships(ctx) if err != nil { @@ -424,34 +462,33 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { if err != nil { return fmt.Errorf("error finalizing last write: %w", err) } - - written += resp.NumLoaded - + batchesWritten++ + written += int64(resp.NumLoaded) + if err := bar.Set64(written); err != nil { + return fmt.Errorf("error incrementing progress bar: %w", err) + } totalTime := time.Since(relationshipWriteStart) - relsPerSec := float64(written) / totalTime.Seconds() + + if err := bar.Finish(); err != nil { + return fmt.Errorf("error finalizing progress bar: %w", err) + } log.Info(). - Uint64("relationships", written). + Int64("batches", batchesWritten). + Int64("relationships", written). + Uint64("perSecond", perSec(uint64(written), totalTime)). Stringer("duration", totalTime). - Float64("perSecond", relsPerSec). Msg("finished restore") - if err := decoder.Close(); err != nil { - return fmt.Errorf("error closing restore encoder: %w", err) - } - - if err := f.Close(); err != nil { - return fmt.Errorf("error closing restore file: %w", err) - } - return nil } -var backupParseSchemaCmd = &cobra.Command{ - Use: "parse-schema ", - Short: "Extract the schema from a backup file", - Args: cobra.ExactArgs(1), - RunE: backupParseSchemaCmdFunc, +func perSec(i uint64, d time.Duration) uint64 { + secs := uint64(d.Seconds()) + if secs == 0 { + return i + } + return i / secs } func backupParseSchemaCmdFunc(cmd *cobra.Command, args []string) error { @@ -490,13 +527,6 @@ func backupParseSchemaCmdFunc(cmd *cobra.Command, args []string) error { return nil } -var backupParseRevisionCmd = &cobra.Command{ - Use: "parse-revision ", - Short: "Extract the revision from a backup file", - Args: cobra.ExactArgs(1), - RunE: backupParseRevisionCmdFunc, -} - func backupParseRevisionCmdFunc(_ *cobra.Command, args []string) error { filename := "" // Default to stdin. if len(args) > 0 { @@ -522,13 +552,6 @@ func backupParseRevisionCmdFunc(_ *cobra.Command, args []string) error { return nil } -var backupParseRelsCmd = &cobra.Command{ - Use: "parse-relationships ", - Short: "Extract the relationships from a backup file", - Args: cobra.ExactArgs(1), - RunE: backupParseRelsCmdFunc, -} - func backupParseRelsCmdFunc(cmd *cobra.Command, args []string) error { filename := "" // Default to stdin. if len(args) > 0 { diff --git a/internal/commands/relationship.go b/internal/commands/relationship.go index ee8debee..35ec81c7 100644 --- a/internal/commands/relationship.go +++ b/internal/commands/relationship.go @@ -62,21 +62,21 @@ var relationshipCmd = &cobra.Command{ var createCmd = &cobra.Command{ Use: "create ", Short: "create a Relationship for a Subject", - Args: writeRelationshipsFromArgsOrStdin, + Args: StdinOrExactArgs(3), RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_CREATE, os.Stdin), } var touchCmd = &cobra.Command{ Use: "touch ", Short: "idempotently update a Relationship for a Subject", - Args: writeRelationshipsFromArgsOrStdin, + Args: StdinOrExactArgs(3), RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_TOUCH, os.Stdin), } var deleteCmd = &cobra.Command{ Use: "delete ", Short: "delete a Relationship", - Args: writeRelationshipsFromArgsOrStdin, + Args: StdinOrExactArgs(3), RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_DELETE, os.Stdin), } @@ -94,11 +94,14 @@ var bulkDeleteCmd = &cobra.Command{ RunE: bulkDeleteRelationships, } -func writeRelationshipsFromArgsOrStdin(cmd *cobra.Command, args []string) error { - if ok := isArgsViaFile(os.Stdin) && len(args) == 0; ok { - return nil +func StdinOrExactArgs(n int) cobra.PositionalArgs { + return func(cmd *cobra.Command, args []string) error { + if ok := isArgsViaFile(os.Stdin) && len(args) == 0; ok { + return nil + } + + return cobra.ExactArgs(n)(cmd, args) } - return cobra.ExactArgs(3)(cmd, args) } func isArgsViaFile(file *os.File) bool { diff --git a/internal/commands/relationship_test.go b/internal/commands/relationship_test.go index ee1e02d3..a704a123 100644 --- a/internal/commands/relationship_test.go +++ b/internal/commands/relationship_test.go @@ -210,15 +210,15 @@ func TestWriteRelationshipsArgs(t *testing.T) { }() // returns accepts anything if input file is not a terminal - require.Nil(t, writeRelationshipsFromArgsOrStdin(&cobra.Command{}, nil)) + require.Nil(t, StdinOrExactArgs(3)(&cobra.Command{}, nil)) // if both STDIN and CLI args are provided, CLI args take precedence - require.ErrorContains(t, writeRelationshipsFromArgsOrStdin(&cobra.Command{}, []string{"a", "b"}), "accepts 3 arg(s), received 2") + require.ErrorContains(t, StdinOrExactArgs(3)(&cobra.Command{}, []string{"a", "b"}), "accepts 3 arg(s), received 2") isTerm = true // checks there is 3 input arguments in case of tty - require.ErrorContains(t, writeRelationshipsFromArgsOrStdin(&cobra.Command{}, nil), "accepts 3 arg(s), received 0") - require.Nil(t, writeRelationshipsFromArgsOrStdin(&cobra.Command{}, []string{"a", "b", "c"})) + require.ErrorContains(t, StdinOrExactArgs(3)(&cobra.Command{}, nil), "accepts 3 arg(s), received 0") + require.Nil(t, StdinOrExactArgs(3)(&cobra.Command{}, []string{"a", "b", "c"})) } func TestWriteRelationshipCmdFuncFromTTY(t *testing.T) { From 68a7a806238ca8e9cd8cfab5c174084b8637c054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 15 Dec 2023 10:49:23 +0000 Subject: [PATCH 10/49] add filterSchemaDefs tests --- internal/cmd/backup.go | 4 ++ internal/cmd/backup_test.go | 101 ++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 internal/cmd/backup_test.go diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 78d3ebd2..430d96a3 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -132,6 +132,10 @@ func partialPrefixMatch(name, prefix string) bool { } func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) { + if schema == "" || prefix == "" { + return schema, nil + } + compiledSchema, err := compiler.Compile(compiler.InputSchema{Source: "schema", SchemaString: schema}, compiler.SkipValidation()) if err != nil { return "", fmt.Errorf("error reading schema: %w", err) diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go new file mode 100644 index 00000000..eecb8558 --- /dev/null +++ b/internal/cmd/backup_test.go @@ -0,0 +1,101 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestFilterSchemaDefs(t *testing.T) { + for _, tt := range []struct { + name string + inputSchema string + inputPrefix string + outputSchema string + err string + }{ + { + name: "empty schema returns as is", + inputSchema: "", + inputPrefix: "", + outputSchema: "", + err: "", + }, + { + name: "no input prefix matches everything", + inputSchema: "definition test {}", + inputPrefix: "", + outputSchema: "definition test {}", + err: "", + }, + { + name: "filter over schema without prefix filters everything", + inputSchema: "definition test {}", + inputPrefix: "myprefix", + outputSchema: "", + err: "filtered all definitions from schema", + }, + { + name: "filter over schema with same prefix returns schema as is", + inputSchema: "definition myprefix/test {}\n\ndefinition myprefix/test2 {}", + inputPrefix: "myprefix", + outputSchema: "definition myprefix/test {}\n\ndefinition myprefix/test2 {}", + err: "", + }, + { + name: "filter over schema with different prefixes filters non matching namespaces", + inputSchema: "definition myprefix/test {}\n\ndefinition myprefix2/test2 {}", + inputPrefix: "myprefix", + outputSchema: "definition myprefix/test {}", + err: "", + }, + { + name: "filter over schema caveats with same prefixes returns as is", + inputSchema: "caveat myprefix/one(a int) {\n\ta == 1\n}", + inputPrefix: "myprefix", + outputSchema: "caveat myprefix/one(a int) {\n\ta == 1\n}", + err: "", + }, + { + name: "filter over unprefixed schema caveats with a prefix filters out", + inputSchema: "caveat one(a int) {\n\ta == 1\n}", + inputPrefix: "myprefix", + outputSchema: "", + err: "filtered all definitions from schema", + }, + { + name: "filter over schema mixed prefixed/unprefixed caveats filters out", + inputSchema: "caveat one(a int) {\n\ta == 1\n}\n\ncaveat myprefix/two(a int) {\n\ta == 2\n}", + inputPrefix: "myprefix", + outputSchema: "caveat myprefix/two(a int) {\n\ta == 2\n}", + err: "", + }, + { + name: "filter over schema namespaces and caveats with same prefixes returns as is", + inputSchema: "definition myprefix/test {}\n\ncaveat myprefix/one(a int) {\n\ta == 1\n}", + inputPrefix: "myprefix", + outputSchema: "definition myprefix/test {}\n\ncaveat myprefix/one(a int) {\n\ta == 1\n}", + err: "", + }, + { + name: "fails on invalid schema", + inputSchema: "definition a/test {}\n\ncaveat a/one(a int) {\n\ta == 1\n}", + inputPrefix: "a", + outputSchema: "definition a/test {}\n\ncaveat a/one(a int) {\n\ta == 1\n}", + err: "value does not match regex pattern", + }, + } { + t.Run(tt.name, func(t *testing.T) { + tt := tt + t.Parallel() + + outputSchema, err := filterSchemaDefs(tt.inputSchema, tt.inputPrefix) + if tt.err != "" { + require.ErrorContains(t, err, tt.err) + } else { + require.NoError(t, err) + require.Equal(t, tt.outputSchema, outputSchema) + } + }) + } +} From 407821ad4bdd4baab81c4e65cb54dfe64e875c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 15 Dec 2023 11:57:20 +0000 Subject: [PATCH 11/49] add tests to backupParseRelsCmdFunc also does some minor refactoring on the function to make it testable and easier to follow --- internal/cmd/backup.go | 32 ++++++++++----- internal/cmd/backup_test.go | 69 +++++++++++++++++++++++++++++++++ internal/cmd/helpers_test.go | 75 ++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 internal/cmd/helpers_test.go diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 430d96a3..dd43ffbc 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -67,7 +67,9 @@ var ( Use: "parse-relationships ", Short: "Extract the relationships from a backup file", Args: cobra.ExactArgs(1), - RunE: backupParseRelsCmdFunc, + RunE: func(cmd *cobra.Command, args []string) error { + return backupParseRelsCmdFunc(cmd, os.Stdout, args) + }, } ) @@ -556,11 +558,12 @@ func backupParseRevisionCmdFunc(_ *cobra.Command, args []string) error { return nil } -func backupParseRelsCmdFunc(cmd *cobra.Command, args []string) error { +func backupParseRelsCmdFunc(cmd *cobra.Command, out *os.File, args []string) error { filename := "" // Default to stdin. if len(args) > 0 { filename = args[0] } + prefix := cobrautil.MustGetString(cmd, "prefix-filter") f, _, err := openRestoreFile(filename) if err != nil { @@ -573,15 +576,24 @@ func backupParseRelsCmdFunc(cmd *cobra.Command, args []string) error { } for rel, err := decoder.Next(); rel != nil && err == nil; rel, err = decoder.Next() { - if hasRelPrefix(rel, cobrautil.MustGetString(cmd, "prefix-filter")) { - relString, err := tuple.StringRelationship(rel) - if err != nil { - return err - } - relString = strings.Replace(relString, "@", " ", 1) - relString = strings.Replace(relString, "#", " ", 1) - fmt.Println(relString) + if !hasRelPrefix(rel, prefix) { + continue + } + + relString, err := tuple.StringRelationship(rel) + if err != nil { + return err + } + + if _, err = fmt.Fprintln(out, replaceRelString(relString)); err != nil { + return err } } + return nil } + +func replaceRelString(rel string) string { + rel = strings.Replace(rel, "@", " ", 1) + return strings.Replace(rel, "#", " ", 1) +} diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index eecb8558..bfcd8c6a 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -1,11 +1,25 @@ package cmd import ( + "os" "testing" + "github.com/rs/zerolog" "github.com/stretchr/testify/require" ) +func init() { + zerolog.SetGlobalLevel(zerolog.Disabled) +} + +const testSchema = `definition test/user {}\ndefinition resource {relation reader: test/user}\n` + +var testRelationships = []string{ + `test/user:1#reader@test/resource:1`, + `test/user:2#reader@test/resource:2`, + `test/user:3#reader@test/resource:3`, +} + func TestFilterSchemaDefs(t *testing.T) { for _, tt := range []struct { name string @@ -99,3 +113,58 @@ func TestFilterSchemaDefs(t *testing.T) { }) } } + +func TestBackupParseRelsCmdFunc(t *testing.T) { + for _, tt := range []struct { + name string + filter string + schema string + relationships []string + output []string + err string + }{ + { + name: "basic test", + filter: "test", + schema: testSchema, + relationships: testRelationships, + output: mapRelationshipTuplesToCLIOutput(t, testRelationships), + }, + { + name: "filters out", + filter: "test", + schema: testSchema, + relationships: append([]string{"foo/user:0#reader@foo/resource:0"}, testRelationships...), + output: mapRelationshipTuplesToCLIOutput(t, testRelationships), + }, + { + name: "allows empty backup", + filter: "test", + schema: testSchema, + relationships: nil, + output: nil, + }, + } { + t.Run(tt.name, func(t *testing.T) { + tt := tt + t.Parallel() + + cmd := createTestCobraCommandWithFlagValue(t, "prefix-filter", tt.filter) + backupName := createTestBackup(t, tt.schema, tt.relationships) + f, err := os.CreateTemp("", "parse-output") + require.NoError(t, err) + defer func() { + _ = f.Close() + }() + t.Cleanup(func() { + _ = os.Remove(f.Name()) + }) + + err = backupParseRelsCmdFunc(cmd, f, []string{backupName}) + require.NoError(t, err) + + lines := readLines(t, f.Name()) + require.Equal(t, tt.output, lines) + }) + } +} diff --git a/internal/cmd/helpers_test.go b/internal/cmd/helpers_test.go new file mode 100644 index 00000000..116d0686 --- /dev/null +++ b/internal/cmd/helpers_test.go @@ -0,0 +1,75 @@ +package cmd + +import ( + "bufio" + "os" + "testing" + + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/authzed/spicedb/pkg/tuple" + "github.com/samber/lo" + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" + + "github.com/authzed/zed/pkg/backupformat" +) + +func mapRelationshipTuplesToCLIOutput(t *testing.T, input []string) []string { + t.Helper() + + return lo.Map[string, string](input, func(item string, _ int) string { + return replaceRelString(item) + }) +} + +func readLines(t *testing.T, fileName string) []string { + t.Helper() + + f, err := os.Open(fileName) + require.NoError(t, err) + defer func() { + _ = f.Close() + }() + + var lines []string + scanner := bufio.NewScanner(f) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + return lines +} + +func createTestCobraCommandWithFlagValue(t *testing.T, flagName, flagValue string) *cobra.Command { + t.Helper() + + c := cobra.Command{} + c.Flags().String(flagName, flagValue, "") + + return &c +} + +func createTestBackup(t *testing.T, schema string, relationships []string) string { + t.Helper() + + f, err := os.CreateTemp("", "test-backup") + require.NoError(t, err) + defer f.Close() + t.Cleanup(func() { + _ = os.Remove(f.Name()) + }) + + avroWriter, err := backupformat.NewEncoder(f, schema, &v1.ZedToken{Token: "test"}) + require.NoError(t, err) + defer func() { + require.NoError(t, avroWriter.Close()) + }() + + for _, rel := range relationships { + r := tuple.ParseRel(rel) + require.NotNil(t, r) + require.NoError(t, avroWriter.Append(r)) + } + + return f.Name() +} From 1fdf4553ba7b4f9822c5af510d8b4dccebcea2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 15 Dec 2023 12:39:34 +0000 Subject: [PATCH 12/49] add tests to backupParseRelsCmdFunc also DRY creation of decoder, and align error handling of io.Closer values --- internal/cmd/backup.go | 85 +++++++++++++++++-------------------- internal/cmd/backup_test.go | 19 +++++++++ 2 files changed, 59 insertions(+), 45 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index dd43ffbc..027d4ce9 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -60,7 +60,9 @@ var ( Use: "parse-revision ", Short: "Extract the revision from a backup file", Args: cobra.ExactArgs(1), - RunE: backupParseRevisionCmdFunc, + RunE: func(cmd *cobra.Command, args []string) error { + return backupParseRevisionCmdFunc(cmd, os.Stdout, args) + }, } backupParseRelsCmd = &cobra.Command{ @@ -343,22 +345,13 @@ func openRestoreFile(filename string) (*os.File, int64, error) { } func restoreCmdFunc(cmd *cobra.Command, args []string) error { - filename := "" // Default to stdin. - if len(args) > 0 { - filename = args[0] - } - - f, _, err := openRestoreFile(filename) + decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { return err } - defer func(e *error) { *e = errors.Join((*e), f.Close()) }(&err) - decoder, err := backupformat.NewDecoder(f) - if err != nil { - return fmt.Errorf("error creating restore file decoder: %w", err) - } - defer func(e *error) { *e = errors.Join((*e), decoder.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, closer.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, decoder.Close()) }(&err) if loadedToken := decoder.ZedToken(); loadedToken != nil { log.Debug().Str("revision", loadedToken.Token).Msg("parsed revision") @@ -498,20 +491,14 @@ func perSec(i uint64, d time.Duration) uint64 { } func backupParseSchemaCmdFunc(cmd *cobra.Command, args []string) error { - filename := "" // Default to stdin. - if len(args) > 0 { - filename = args[0] - } - - f, _, err := openRestoreFile(filename) + decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { return err } - decoder, err := backupformat.NewDecoder(f) - if err != nil { - return fmt.Errorf("error creating restore file decoder: %w", err) - } + defer func(e *error) { *e = errors.Join(*e, closer.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, decoder.Close()) }(&err) + schema := decoder.Schema() // Remove any invalid relations generated from old, backwards-incompat @@ -533,47 +520,36 @@ func backupParseSchemaCmdFunc(cmd *cobra.Command, args []string) error { return nil } -func backupParseRevisionCmdFunc(_ *cobra.Command, args []string) error { - filename := "" // Default to stdin. - if len(args) > 0 { - filename = args[0] - } - - f, _, err := openRestoreFile(filename) +func backupParseRevisionCmdFunc(cmd *cobra.Command, out *os.File, args []string) error { + decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { return err } - decoder, err := backupformat.NewDecoder(f) - if err != nil { - return fmt.Errorf("error creating restore file decoder: %w", err) - } + defer func(e *error) { *e = errors.Join(*e, closer.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, decoder.Close()) }(&err) loadedToken := decoder.ZedToken() if loadedToken == nil { return fmt.Errorf("failed to parse decoded revision") } - fmt.Println(loadedToken.Token) + if _, err = fmt.Fprintln(out, loadedToken.Token); err != nil { + return err + } + return nil } func backupParseRelsCmdFunc(cmd *cobra.Command, out *os.File, args []string) error { - filename := "" // Default to stdin. - if len(args) > 0 { - filename = args[0] - } prefix := cobrautil.MustGetString(cmd, "prefix-filter") - - f, _, err := openRestoreFile(filename) + decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { return err } - decoder, err := backupformat.NewDecoder(f) - if err != nil { - return fmt.Errorf("error creating restore file decoder: %w", err) - } + defer func(e *error) { *e = errors.Join(*e, closer.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, decoder.Close()) }(&err) for rel, err := decoder.Next(); rel != nil && err == nil; rel, err = decoder.Next() { if !hasRelPrefix(rel, prefix) { @@ -593,6 +569,25 @@ func backupParseRelsCmdFunc(cmd *cobra.Command, out *os.File, args []string) err return nil } +func decoderFromArgs(_ *cobra.Command, args []string) (*backupformat.Decoder, io.Closer, error) { + filename := "" // Default to stdin. + if len(args) > 0 { + filename = args[0] + } + + f, _, err := openRestoreFile(filename) + if err != nil { + return nil, nil, err + } + + decoder, err := backupformat.NewDecoder(f) + if err != nil { + return nil, nil, fmt.Errorf("error creating restore file decoder: %w", err) + } + + return decoder, f, nil +} + func replaceRelString(rel string) string { rel = strings.Replace(rel, "@", " ", 1) return strings.Replace(rel, "#", " ", 1) diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index bfcd8c6a..57ba8801 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -168,3 +168,22 @@ func TestBackupParseRelsCmdFunc(t *testing.T) { }) } } + +func TestBackupParseRevisionCmdFunc(t *testing.T) { + cmd := createTestCobraCommandWithFlagValue(t, "prefix-filter", "test") + backupName := createTestBackup(t, testSchema, testRelationships) + f, err := os.CreateTemp("", "parse-output") + require.NoError(t, err) + defer func() { + _ = f.Close() + }() + t.Cleanup(func() { + _ = os.Remove(f.Name()) + }) + + err = backupParseRevisionCmdFunc(cmd, f, []string{backupName}) + require.NoError(t, err) + + lines := readLines(t, f.Name()) + require.Equal(t, []string{"test"}, lines) +} From cb9ab88aab54f8962a22b48250582feb64319e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 15 Dec 2023 13:23:20 +0000 Subject: [PATCH 13/49] add tests to backupParseSchemaCmdFunc --- internal/cmd/backup.go | 21 +++++------ internal/cmd/backup_test.go | 73 ++++++++++++++++++++++++++++++++++-- internal/cmd/helpers_test.go | 23 +++++++++++- 3 files changed, 101 insertions(+), 16 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 027d4ce9..ee4f4abe 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -53,7 +53,9 @@ var ( Use: "parse-schema ", Short: "Extract the schema from a backup file", Args: cobra.ExactArgs(1), - RunE: backupParseSchemaCmdFunc, + RunE: func(cmd *cobra.Command, args []string) error { + return backupParseSchemaCmdFunc(cmd, os.Stdout, args) + }, } backupParseRevisionCmd = &cobra.Command{ @@ -490,7 +492,7 @@ func perSec(i uint64, d time.Duration) uint64 { return i / secs } -func backupParseSchemaCmdFunc(cmd *cobra.Command, args []string) error { +func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { return err @@ -516,11 +518,11 @@ func backupParseSchemaCmdFunc(cmd *cobra.Command, args []string) error { } } - fmt.Println(schema) - return nil + _, err = fmt.Fprintln(out, schema) + return err } -func backupParseRevisionCmdFunc(cmd *cobra.Command, out *os.File, args []string) error { +func backupParseRevisionCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { return err @@ -534,14 +536,11 @@ func backupParseRevisionCmdFunc(cmd *cobra.Command, out *os.File, args []string) return fmt.Errorf("failed to parse decoded revision") } - if _, err = fmt.Fprintln(out, loadedToken.Token); err != nil { - return err - } - - return nil + _, err = fmt.Fprintln(out, loadedToken.Token) + return err } -func backupParseRelsCmdFunc(cmd *cobra.Command, out *os.File, args []string) error { +func backupParseRelsCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { prefix := cobrautil.MustGetString(cmd, "prefix-filter") decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index 57ba8801..4e2ec012 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -2,6 +2,7 @@ package cmd import ( "os" + "strings" "testing" "github.com/rs/zerolog" @@ -12,7 +13,11 @@ func init() { zerolog.SetGlobalLevel(zerolog.Disabled) } -const testSchema = `definition test/user {}\ndefinition resource {relation reader: test/user}\n` +const testSchema = `definition test/user {} + +definition test/resource { + relation reader: test/user +}` var testRelationships = []string{ `test/user:1#reader@test/resource:1`, @@ -149,7 +154,7 @@ func TestBackupParseRelsCmdFunc(t *testing.T) { tt := tt t.Parallel() - cmd := createTestCobraCommandWithFlagValue(t, "prefix-filter", tt.filter) + cmd := createTestCobraCommandWithFlagValue(t, stringFlag{"prefix-filter", tt.filter}) backupName := createTestBackup(t, tt.schema, tt.relationships) f, err := os.CreateTemp("", "parse-output") require.NoError(t, err) @@ -170,7 +175,7 @@ func TestBackupParseRelsCmdFunc(t *testing.T) { } func TestBackupParseRevisionCmdFunc(t *testing.T) { - cmd := createTestCobraCommandWithFlagValue(t, "prefix-filter", "test") + cmd := createTestCobraCommandWithFlagValue(t, stringFlag{"prefix-filter", "test"}) backupName := createTestBackup(t, testSchema, testRelationships) f, err := os.CreateTemp("", "parse-output") require.NoError(t, err) @@ -187,3 +192,65 @@ func TestBackupParseRevisionCmdFunc(t *testing.T) { lines := readLines(t, f.Name()) require.Equal(t, []string{"test"}, lines) } + +func TestBackupParseSchemaCmdFunc(t *testing.T) { + for _, tt := range []struct { + name string + filter string + rewriteLegacy bool + schema string + output []string + err string + }{ + { + name: "basic schema test", + filter: "test", + schema: testSchema, + output: strings.Split(testSchema, "\n"), + }, + { + name: "filters schema definitions", + filter: "test", + schema: "definition test/user {}\n\ndefinition foo/user {}", + output: []string{"definition test/user {}"}, + }, + { + name: "rewrites short relations", + filter: "", + rewriteLegacy: true, + schema: "definition user {relation aa: user}", + output: []string{"definition user {", "/* deleted short relation name */"}, + }, + { + name: "rewrites legacy missing allowed types", + filter: "", + rewriteLegacy: true, + schema: "definition user { relation foo /* missing allowed types */}", + output: []string{"definition user {", "/* deleted missing allowed type error */"}, + }, + } { + t.Run(tt.name, func(t *testing.T) { + tt := tt + t.Parallel() + + cmd := createTestCobraCommandWithFlagValue(t, + stringFlag{"prefix-filter", tt.filter}, + boolFlag{"rewrite-legacy", tt.rewriteLegacy}) + backupName := createTestBackup(t, tt.schema, nil) + f, err := os.CreateTemp("", "parse-output") + require.NoError(t, err) + defer func() { + _ = f.Close() + }() + t.Cleanup(func() { + _ = os.Remove(f.Name()) + }) + + err = backupParseSchemaCmdFunc(cmd, f, []string{backupName}) + require.NoError(t, err) + + lines := readLines(t, f.Name()) + require.Equal(t, tt.output, lines) + }) + } +} diff --git a/internal/cmd/helpers_test.go b/internal/cmd/helpers_test.go index 116d0686..3896c6a6 100644 --- a/internal/cmd/helpers_test.go +++ b/internal/cmd/helpers_test.go @@ -40,11 +40,30 @@ func readLines(t *testing.T, fileName string) []string { return lines } -func createTestCobraCommandWithFlagValue(t *testing.T, flagName, flagValue string) *cobra.Command { +type stringFlag struct { + flagName string + flagValue string +} + +type boolFlag struct { + flagName string + flagValue bool +} + +func createTestCobraCommandWithFlagValue(t *testing.T, flagAndValues ...any) *cobra.Command { t.Helper() c := cobra.Command{} - c.Flags().String(flagName, flagValue, "") + for _, flagAndValue := range flagAndValues { + switch f := flagAndValue.(type) { + case stringFlag: + c.Flags().String(f.flagName, f.flagValue, "") + case boolFlag: + c.Flags().Bool(f.flagName, f.flagValue, "") + default: + t.Fatalf("unknown flag type: %T", f) + } + } return &c } From ed98969115cc868f2cfab0b2c66ef659ccc43ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 15 Dec 2023 13:28:29 +0000 Subject: [PATCH 14/49] fixing some IDE warnings --- internal/cmd/backup.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index ee4f4abe..774f1296 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -129,7 +129,7 @@ func createBackupFile(filename string) (*os.File, error) { } var ( - missingAllowedTypes = regexp.MustCompile(`(\s*)(relation)(.+)(\/\* missing allowed types \*\/)(.*)`) + missingAllowedTypes = regexp.MustCompile(`(\s*)(relation)(.+)(/\* missing allowed types \*/)(.*)`) shortRelations = regexp.MustCompile(`(\s*)relation [a-z][a-z0-9_]:(.+)`) ) @@ -208,7 +208,7 @@ func relProgressBar(description string) *progressbar.ProgressBar { progressbar.OptionShowCount(), progressbar.OptionShowIts(), progressbar.OptionSetItsString("relationship"), - progressbar.OptionOnCompletion(func() { fmt.Fprint(os.Stderr, "\n") }), + progressbar.OptionOnCompletion(func() { _, _ = fmt.Fprint(os.Stderr, "\n") }), progressbar.OptionSpinnerType(14), progressbar.OptionFullWidth(), progressbar.OptionSetRenderBlankState(true), @@ -222,8 +222,8 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) { if err != nil { return err } - defer func(e *error) { *e = errors.Join((*e), f.Close()) }(&err) - defer func(e *error) { *e = errors.Join((*e), f.Sync()) }(&err) + defer func(e *error) { *e = errors.Join(*e, f.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, f.Sync()) }(&err) client, err := client.NewClient(cmd) if err != nil { @@ -259,7 +259,7 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) { if err != nil { return fmt.Errorf("error creating backup file encoder: %w", err) } - defer func(e *error) { *e = errors.Join((*e), encoder.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, encoder.Close()) }(&err) relationshipStream, err := client.BulkExportRelationships(ctx, &v1.BulkExportRelationshipsRequest{ Consistency: &v1.Consistency{ From cdc457d3adebd19ecc7954c2222bd99d68bcdfc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 15 Dec 2023 14:26:29 +0000 Subject: [PATCH 15/49] add test for backupCreateCmdFunc --- go.mod | 88 ++++++- go.sum | 456 +++++++++++++++++++++++++++++++++++ internal/cmd/backup.go | 15 +- internal/cmd/backup_test.go | 82 ++++++- internal/cmd/helpers_test.go | 54 +++++ 5 files changed, 680 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 4fb003e1..c23dda86 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da github.com/brianvoe/gofakeit/v6 v6.22.0 github.com/charmbracelet/lipgloss v0.7.1 + github.com/google/uuid v1.4.0 github.com/gookit/color v1.5.4 github.com/hamba/avro/v2 v2.18.0 github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a @@ -21,6 +22,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/rs/zerolog v1.31.0 + github.com/samber/lo v1.38.1 github.com/schollz/progressbar/v3 v3.14.1 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 @@ -35,56 +37,103 @@ require ( ) require ( + buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.31.0-20210810001428-4df00b267f94.1 // indirect + buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.31.0-20231010075520-899dbbfd2c07.1 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go/longrunning v0.5.4 // indirect + cloud.google.com/go/spanner v1.53.0 // indirect + contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/IBM/pgxpoolprometheus v1.1.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 // indirect github.com/authzed/cel-go v0.17.5 // indirect + github.com/authzed/consistent v0.1.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.6.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudspannerecosystem/spanner-change-streams-tail v0.3.1 // indirect + github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect + github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect github.com/creack/pty v1.1.18 // indirect github.com/creasty/defaults v1.7.0 // indirect github.com/dalzilio/rudd v1.1.1-0.20230806153452-9e08a6ea8170 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dlmiddlecote/sqlstats v1.0.2 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/ecordell/optgen v0.0.10-0.20230609182709-018141bf9698 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/envoyproxy/go-control-plane v0.11.1 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/exaring/otelpgx v0.5.2 // indirect github.com/fatih/color v1.16.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-logr/zerologr v1.2.3 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v43 v43.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-memdb v1.3.4 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/influxdata/tdigest v0.0.1 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx-zerolog v0.0.0-20230315001418-f978528409eb // indirect + github.com/jackc/pgx/v5 v5.4.3 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/joho/godotenv v1.5.1 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/lthibault/jitterbug v2.0.0+incompatible // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect @@ -93,20 +142,28 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mostynb/go-grpc-compression v1.2.2 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/ngrok/sqlmw v0.0.0-20220520173518-97c9c04efc79 // indirect + github.com/outcaste-io/ristretto v0.2.3 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // 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.17.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/statsd_exporter v0.22.7 // indirect github.com/rivo/uniseg v0.4.4 // indirect + github.com/rs/cors v1.10.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/samber/lo v1.38.1 // indirect github.com/scylladb/go-set v1.0.2 // indirect + github.com/sean-/sysexits v1.0.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect @@ -116,19 +173,46 @@ require ( github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.20.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.20.0 // indirect go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/sdk v1.20.0 // indirect go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/api v0.153.0 // indirect + google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/api v0.28.1 // indirect + k8s.io/apimachinery v0.28.1 // indirect + k8s.io/client-go v0.28.1 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect + k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect + resenje.org/singleflight v0.4.0 // indirect + sigs.k8s.io/controller-runtime v0.16.2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 89ec8693..f7c0d068 100644 --- a/go.sum +++ b/go.sum @@ -3,35 +3,80 @@ buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.31.0-20210810001428-4df00b2 buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.31.0-20231010075520-899dbbfd2c07.1 h1:8sro2hoT2tEgwixyAFJnj+54LbyXjWU3kt6/lcNTDNY= buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.31.0-20231010075520-899dbbfd2c07.1/go.mod h1:iqW5nSujn3ZJ9ISZQX3K/uWwjckAp8hz0J4/wNgFBZo= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/spanner v1.53.0 h1:/NzWQJ1MEhdRcffiutRKbW/AIGVKhcTeivWTDjEyCCo= cloud.google.com/go/spanner v1.53.0/go.mod h1:liG4iCeLqm5L3fFLU5whFITqP0e0orsAW1uUSrd4rws= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/IBM/pgxpoolprometheus v1.1.1 h1:xkWNUe87TIuBj/ypdSiDgNYktsuM7MoZCT8a+kjhh2s= github.com/IBM/pgxpoolprometheus v1.1.1/go.mod h1:GFJDkHbidFfB2APbhBTSy2X4PKH3bLWsEMBhmzK1ipo= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 h1:goHVqTbFX3AIo0tzGr14pgfAW2ZfPChKO21Z9MGf/gk= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/authzed/authzed-go v0.10.1 h1:0aX2Ox9PPPknID92kLs/FnmhCmfl6Ni16v3ZTLsds5M= @@ -49,6 +94,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= @@ -64,20 +111,29 @@ github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMr github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudspannerecosystem/spanner-change-streams-tail v0.3.1 h1:76zSbhqkgwt8LXoWBzZqvnKq0gfDeDrQRwMvaLfp3bM= github.com/cloudspannerecosystem/spanner-change-streams-tail v0.3.1/go.mod h1:Fb3cQgYCLKQfjsJcw+wsalU2l/eJpbtHu2UKt12p+Mk= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -91,8 +147,19 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dlmiddlecote/sqlstats v1.0.2 h1:gSU11YN23D/iY50A2zVYwgXgy072khatTsIW6UPjUtI= github.com/dlmiddlecote/sqlstats v1.0.2/go.mod h1:0CWaIh/Th+z2aI6Q9Jpfg/o21zmGxWhbByHgQSCUQvY= +github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= @@ -111,6 +178,10 @@ github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exaring/otelpgx v0.5.2 h1:joqpJoz/HJD2hP4Rdk6CVM9O7oCQ5zWAkTalTen0ShE= github.com/exaring/otelpgx v0.5.2/go.mod h1:4dBiAqwzDNmpj3TwX5Syti1/Nw2bIoDQItdLvWTklQU= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= @@ -123,17 +194,28 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-logr/zerologr v1.2.3 h1:up5N9vcH9Xck3jJkXzgyOxozT14R47IyDODz8LM1KSs= github.com/go-logr/zerologr v1.2.3/go.mod h1:BxwGo7y5zgSHYR1BjbnHPyF/5ZjVKfKxAZANVu6E8Ho= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -145,30 +227,65 @@ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v43 v43.0.0 h1:y+GL7LIsAIF2NZlJ46ZoC/D1W1ivZasT0lnWHMYPZ+U= @@ -178,12 +295,29 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= @@ -200,6 +334,7 @@ github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8 github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/hamba/avro/v2 v2.18.0 h1:U7T0xI8MGw9+m3SS48E2KHUxas/Hb0EvS0CpkmVcLoI= github.com/hamba/avro/v2 v2.18.0/go.mod h1:dEG+AHrykTpkXvBYsc+XXTuRlvGC645Ix5d2qR8EdEs= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -212,6 +347,7 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -220,6 +356,9 @@ github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 h1:nqAlWFEdqI0ClbTDrhDvE/8LeQ4pftrqKUX9w5k0j3s= github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY= @@ -240,8 +379,17 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a h1:fSIkpfPYnaOLAkci6UX5fXLFpufLlLtV+0Qd87pknEQ= github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a/go.mod h1:6EEEGUlDNdP2DJ0S2gtrJ2Q/6guT3NKc2HdnadKPvRk= github.com/jzelinskie/stringz v0.0.3 h1:0GhG3lVMYrYtIvRbxvQI6zqRTT1P1xyQlpa0FhfUXas= @@ -254,7 +402,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -285,6 +436,9 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= @@ -295,9 +449,13 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mostynb/go-grpc-compression v1.2.2 h1:XaDbnRvt2+1vgr0b/l0qh4mJAfIxE0bKXtz2Znl3GGI= @@ -310,31 +468,72 @@ github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ngrok/sqlmw v0.0.0-20220520173518-97c9c04efc79 h1:Dmx8g2747UTVPzSkmohk84S3g/uWqd6+f4SSLPhLcfA= github.com/ngrok/sqlmw v0.0.0-20220520173518-97c9c04efc79/go.mod h1:E26fwEtRNigBfFfHDWsklmo0T7Ixbg0XXgck+Hq4O9k= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= +github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= @@ -343,6 +542,7 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= @@ -365,7 +565,11 @@ github.com/sean-/sysexits v1.0.0 h1:FLf1xcUTBzTqUI1Nc77UwYPcoWgDM09lyMTt8+QCpbE= github.com/sean-/sysexits v1.0.0/go.mod h1:yRz1mwglmPHOlAm3+WGr40EV8qFg4hn8GE9MoNwoecg= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -397,17 +601,32 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 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.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= @@ -435,6 +654,7 @@ go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+ go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= @@ -444,19 +664,48 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= +go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8= golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -464,38 +713,110 @@ golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -508,39 +829,135 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca h1:PupagGYwj8+I4ubCxcmcBRk3VlUWtTg5huQpZR9flmE= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= 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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= @@ -548,27 +965,54 @@ google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -576,13 +1020,22 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8= k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE= +k8s.io/component-base v0.28.1 h1:LA4AujMlK2mr0tZbQDZkjWbdhTV5bRyEyAFe0TJxlWg= +k8s.io/component-base v0.28.1/go.mod h1:jI11OyhbX21Qtbav7JkhehyBsIRfnO8oEgoAR12ArIU= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= @@ -591,6 +1044,9 @@ k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrC k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= resenje.org/singleflight v0.4.0 h1:NdOEhCxEikK2S2WxGjZV9EGSsItolQKslOOi6pE1tJc= resenje.org/singleflight v0.4.0/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 774f1296..1cf03ee6 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -222,6 +222,7 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) { if err != nil { return err } + defer func(e *error) { *e = errors.Join(*e, f.Close()) }(&err) defer func(e *error) { *e = errors.Join(*e, f.Sync()) }(&err) @@ -242,8 +243,7 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) { // Remove any invalid relations generated from old, backwards-incompat // Serverless permission systems. if cobrautil.MustGetBool(cmd, "rewrite-legacy") { - schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) - schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) + schema = rewriteLegacy(schema) } // Skip any definitions without the provided prefix @@ -364,8 +364,7 @@ func restoreCmdFunc(cmd *cobra.Command, args []string) error { // Remove any invalid relations generated from old, backwards-incompat // Serverless permission systems. if cobrautil.MustGetBool(cmd, "rewrite-legacy") { - schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) - schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) + schema = rewriteLegacy(schema) } // Skip any definitions without the provided prefix @@ -506,8 +505,7 @@ func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) // Remove any invalid relations generated from old, backwards-incompat // Serverless permission systems. if cobrautil.MustGetBool(cmd, "rewrite-legacy") { - schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) - schema = string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) + schema = rewriteLegacy(schema) } // Skip any definitions without the provided prefix @@ -591,3 +589,8 @@ func replaceRelString(rel string) string { rel = strings.Replace(rel, "@", " ", 1) return strings.Replace(rel, "#", " ", 1) } + +func rewriteLegacy(schema string) string { + schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */"))) + return string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */"))) +} diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index 4e2ec012..a719084f 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -1,10 +1,17 @@ package cmd import ( + "context" "os" + "path/filepath" "strings" "testing" + "github.com/authzed/zed/internal/client" + + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/authzed/spicedb/pkg/tuple" + "github.com/google/uuid" "github.com/rs/zerolog" "github.com/stretchr/testify/require" ) @@ -13,16 +20,16 @@ func init() { zerolog.SetGlobalLevel(zerolog.Disabled) } -const testSchema = `definition test/user {} - -definition test/resource { +const testSchema = `definition test/resource { relation reader: test/user -}` +} + +definition test/user {}` var testRelationships = []string{ - `test/user:1#reader@test/resource:1`, - `test/user:2#reader@test/resource:2`, - `test/user:3#reader@test/resource:3`, + `test/resource:1#reader@test/user:1`, + `test/resource:2#reader@test/user:2`, + `test/resource:3#reader@test/user:3`, } func TestFilterSchemaDefs(t *testing.T) { @@ -254,3 +261,64 @@ func TestBackupParseSchemaCmdFunc(t *testing.T) { }) } } + +func TestBackupCreateCmdFunc(t *testing.T) { + cmd := createTestCobraCommandWithFlagValue(t, + stringFlag{"prefix-filter", ""}, + boolFlag{"rewrite-legacy", false}) + f := filepath.Join(os.TempDir(), uuid.NewString()) + _, err := os.Stat(f) + require.Error(t, err) + defer func() { + _ = os.Remove(f) + }() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + srv := newServer(ctx, t) + go func() { + require.NoError(t, srv.Run(ctx)) + }() + conn, err := srv.GRPCDialContext(ctx) + require.NoError(t, err) + + originalClient := client.NewClient + defer func() { + client.NewClient = originalClient + }() + + client.NewClient = clientFromConn(conn) + + c, err := clientFromConn(conn)(cmd) + require.NoError(t, err) + + _, err = c.WriteSchema(ctx, &v1.WriteSchemaRequest{Schema: testSchema}) + require.NoError(t, err) + + testRel := "test/resource:1#reader@test/user:1" + resp, err := c.WriteRelationships(ctx, &v1.WriteRelationshipsRequest{ + Updates: []*v1.RelationshipUpdate{ + { + Operation: v1.RelationshipUpdate_OPERATION_TOUCH, + Relationship: tuple.ParseRel(testRel), + }, + }, + }) + require.NoError(t, err) + + err = backupCreateCmdFunc(cmd, []string{f}) + require.NoError(t, err) + + d, closer, err := decoderFromArgs(cmd, []string{f}) + require.NoError(t, err) + defer func() { + _ = d.Close() + _ = closer.Close() + }() + + require.Equal(t, testSchema, d.Schema()) + rel, err := d.Next() + require.NoError(t, err) + require.Equal(t, testRel, tuple.MustStringRelationship(rel)) + require.Equal(t, resp.WrittenAt.Token, d.ZedToken().Token) +} diff --git a/internal/cmd/helpers_test.go b/internal/cmd/helpers_test.go index 3896c6a6..a0316a8a 100644 --- a/internal/cmd/helpers_test.go +++ b/internal/cmd/helpers_test.go @@ -2,9 +2,18 @@ package cmd import ( "bufio" + "context" "os" "testing" + "github.com/authzed/authzed-go/v1" + "github.com/authzed/spicedb/pkg/cmd/datastore" + "github.com/authzed/spicedb/pkg/cmd/server" + "github.com/authzed/spicedb/pkg/cmd/util" + "google.golang.org/grpc" + + "github.com/authzed/zed/internal/client" + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/pkg/tuple" "github.com/samber/lo" @@ -65,6 +74,7 @@ func createTestCobraCommandWithFlagValue(t *testing.T, flagAndValues ...any) *co } } + c.SetContext(context.Background()) return &c } @@ -92,3 +102,47 @@ func createTestBackup(t *testing.T, schema string, relationships []string) strin return f.Name() } + +func clientFromConn(conn *grpc.ClientConn) func(cmd *cobra.Command) (client.Client, error) { + return func(cmd *cobra.Command) (client.Client, error) { + return &authzed.ClientWithExperimental{ + Client: authzed.Client{ + SchemaServiceClient: v1.NewSchemaServiceClient(conn), + PermissionsServiceClient: v1.NewPermissionsServiceClient(conn), + WatchServiceClient: v1.NewWatchServiceClient(conn), + }, + ExperimentalServiceClient: v1.NewExperimentalServiceClient(conn), + }, nil + } +} + +func newServer(ctx context.Context, t *testing.T) server.RunnableServer { + t.Helper() + + ds, err := datastore.NewDatastore(ctx, + datastore.DefaultDatastoreConfig().ToOption(), + datastore.WithRequestHedgingEnabled(false), + ) + require.NoError(t, err, "unable to start memdb datastore") + + configOpts := []server.ConfigOption{ + server.WithGRPCServer(util.GRPCServerConfig{ + Network: util.BufferedNetwork, + Enabled: true, + }), + server.WithGRPCAuthFunc(func(ctx context.Context) (context.Context, error) { + return ctx, nil + }), + server.WithHTTPGateway(util.HTTPServerConfig{HTTPEnabled: false}), + server.WithMetricsAPI(util.HTTPServerConfig{HTTPEnabled: true}), + server.WithDispatchCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), + server.WithNamespaceCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), + server.WithClusterDispatchCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), + server.WithDatastore(ds), + } + + srv, err := server.NewConfigWithOptionsAndDefaults(configOpts...).Complete(ctx) + require.NoError(t, err) + + return srv +} From 378d545e9235d0c2ad55d67c44fcdc1b1038740e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 15 Dec 2023 14:45:59 +0000 Subject: [PATCH 16/49] add test for backupRestoreCmdFunc --- internal/cmd/backup.go | 6 ++-- internal/cmd/backup_test.go | 53 ++++++++++++++++++++++++++++++++++++ internal/cmd/helpers_test.go | 16 ++++++++++- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 1cf03ee6..0edf66ab 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -46,7 +46,7 @@ var ( Use: "restore ", Short: "Restore a permission system from a file", Args: commands.StdinOrExactArgs(1), - RunE: restoreCmdFunc, + RunE: backupRestoreCmdFunc, } backupParseSchemaCmd = &cobra.Command{ @@ -95,7 +95,7 @@ func registerBackupCmd(rootCmd *cobra.Command) { Use: "restore ", Short: "Restore a permission system from a file", Args: cobra.MaximumNArgs(1), - RunE: restoreCmdFunc, + RunE: backupRestoreCmdFunc, Hidden: true, }) @@ -346,7 +346,7 @@ func openRestoreFile(filename string) (*os.File, int64, error) { return f, stats.Size(), nil } -func restoreCmdFunc(cmd *cobra.Command, args []string) error { +func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { decoder, closer, err := decoderFromArgs(cmd, args) if err != nil { return err diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index a719084f..8a452b59 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -322,3 +322,56 @@ func TestBackupCreateCmdFunc(t *testing.T) { require.Equal(t, testRel, tuple.MustStringRelationship(rel)) require.Equal(t, resp.WrittenAt.Token, d.ZedToken().Token) } + +func TestBackupRestoreCmdFunc(t *testing.T) { + cmd := createTestCobraCommandWithFlagValue(t, + stringFlag{"prefix-filter", "test"}, + boolFlag{"rewrite-legacy", false}, + intFlag{"batch-size", 100}, + int64Flag{"batches-per-transaction", 10}, + ) + backupName := createTestBackup(t, testSchema, testRelationships) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + srv := newServer(ctx, t) + go func() { + require.NoError(t, srv.Run(ctx)) + }() + conn, err := srv.GRPCDialContext(ctx) + require.NoError(t, err) + + originalClient := client.NewClient + defer func() { + client.NewClient = originalClient + }() + + client.NewClient = clientFromConn(conn) + + c, err := clientFromConn(conn)(cmd) + require.NoError(t, err) + err = backupRestoreCmdFunc(cmd, []string{backupName}) + require.NoError(t, err) + + resp, err := c.ReadSchema(ctx, &v1.ReadSchemaRequest{}) + require.NoError(t, err) + require.Equal(t, testSchema, resp.SchemaText) + + rrCli, err := c.ReadRelationships(ctx, &v1.ReadRelationshipsRequest{ + Consistency: &v1.Consistency{ + Requirement: &v1.Consistency_FullyConsistent{ + FullyConsistent: true, + }, + }, + RelationshipFilter: &v1.RelationshipFilter{ + ResourceType: "test/resource", + }, + }) + require.NoError(t, err) + + rrResp, err := rrCli.Recv() + require.NoError(t, err) + + require.NoError(t, rrCli.CloseSend()) + require.Equal(t, "test/resource:1#reader@test/user:1", tuple.MustStringRelationship(rrResp.Relationship)) +} diff --git a/internal/cmd/helpers_test.go b/internal/cmd/helpers_test.go index a0316a8a..acc18d50 100644 --- a/internal/cmd/helpers_test.go +++ b/internal/cmd/helpers_test.go @@ -59,6 +59,16 @@ type boolFlag struct { flagValue bool } +type intFlag struct { + flagName string + flagValue int +} + +type int64Flag struct { + flagName string + flagValue int64 +} + func createTestCobraCommandWithFlagValue(t *testing.T, flagAndValues ...any) *cobra.Command { t.Helper() @@ -69,6 +79,10 @@ func createTestCobraCommandWithFlagValue(t *testing.T, flagAndValues ...any) *co c.Flags().String(f.flagName, f.flagValue, "") case boolFlag: c.Flags().Bool(f.flagName, f.flagValue, "") + case intFlag: + c.Flags().Int(f.flagName, f.flagValue, "") + case int64Flag: + c.Flags().Int64(f.flagName, f.flagValue, "") default: t.Fatalf("unknown flag type: %T", f) } @@ -134,7 +148,7 @@ func newServer(ctx context.Context, t *testing.T) server.RunnableServer { return ctx, nil }), server.WithHTTPGateway(util.HTTPServerConfig{HTTPEnabled: false}), - server.WithMetricsAPI(util.HTTPServerConfig{HTTPEnabled: true}), + server.WithMetricsAPI(util.HTTPServerConfig{HTTPEnabled: false}), server.WithDispatchCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), server.WithNamespaceCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), server.WithClusterDispatchCacheConfig(server.CacheConfig{Enabled: false, Metrics: false}), From f095dbe7123a22205498dbe75e3ad413059ac4bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:17:06 +0000 Subject: [PATCH 17/49] build(deps): bump github.com/brianvoe/gofakeit/v6 from 6.22.0 to 6.26.3 Bumps [github.com/brianvoe/gofakeit/v6](https://github.com/brianvoe/gofakeit) from 6.22.0 to 6.26.3. - [Release notes](https://github.com/brianvoe/gofakeit/releases) - [Commits](https://github.com/brianvoe/gofakeit/compare/v6.22.0...v6.26.3) --- updated-dependencies: - dependency-name: github.com/brianvoe/gofakeit/v6 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c23dda86..9f7fc63a 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/authzed/authzed-go v0.10.1 github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da - github.com/brianvoe/gofakeit/v6 v6.22.0 + github.com/brianvoe/gofakeit/v6 v6.26.3 github.com/charmbracelet/lipgloss v0.7.1 github.com/google/uuid v1.4.0 github.com/gookit/color v1.5.4 diff --git a/go.sum b/go.sum index f7c0d068..6f1d0854 100644 --- a/go.sum +++ b/go.sum @@ -102,8 +102,8 @@ github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsy github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bloom/v3 v3.6.0 h1:dTU0OVLJSoOhz9m68FTXMFfA39nR8U/nTCs1zb26mOI= github.com/bits-and-blooms/bloom/v3 v3.6.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg= -github.com/brianvoe/gofakeit/v6 v6.22.0 h1:BzOsDot1o3cufTfOk+fWKE9nFYojyDV+XHdCWL2+uyE= -github.com/brianvoe/gofakeit/v6 v6.22.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= +github.com/brianvoe/gofakeit/v6 v6.26.3 h1:3ljYrjPwsUNAUFdUIr2jVg5EhKdcke/ZLop7uVg1Er8= +github.com/brianvoe/gofakeit/v6 v6.26.3/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= From f79a690511d708bfff351532f7088222d863eb32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:24:55 +0000 Subject: [PATCH 18/49] build(deps): bump github.com/charmbracelet/lipgloss from 0.7.1 to 0.9.1 Bumps [github.com/charmbracelet/lipgloss](https://github.com/charmbracelet/lipgloss) from 0.7.1 to 0.9.1. - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v0.7.1...v0.9.1) --- updated-dependencies: - dependency-name: github.com/charmbracelet/lipgloss dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 9f7fc63a..12b34a75 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da github.com/brianvoe/gofakeit/v6 v6.26.3 - github.com/charmbracelet/lipgloss v0.7.1 + github.com/charmbracelet/lipgloss v0.9.1 github.com/google/uuid v1.4.0 github.com/gookit/color v1.5.4 github.com/hamba/avro/v2 v2.18.0 @@ -145,7 +145,7 @@ require ( github.com/mostynb/go-grpc-compression v1.2.2 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.15.1 // indirect + github.com/muesli/termenv v0.15.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ngrok/sqlmw v0.0.0-20220520173518-97c9c04efc79 // indirect github.com/outcaste-io/ristretto v0.2.3 // indirect diff --git a/go.sum b/go.sum index 6f1d0854..17527d60 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= -github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c= +github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg= +github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -464,8 +464,8 @@ github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= -github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= +github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= +github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= From 78b2a45dd403e8cbb909d3af270e0331bd1803d2 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 28 Dec 2023 17:08:35 -0500 Subject: [PATCH 19/49] Adds dynamic completion on `zed context use` Fixes #66 --- internal/cmd/context.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/internal/cmd/context.go b/internal/cmd/context.go index 7e12cd42..0f938cd0 100644 --- a/internal/cmd/context.go +++ b/internal/cmd/context.go @@ -52,10 +52,26 @@ var contextRemoveCmd = &cobra.Command{ } var contextUseCmd = &cobra.Command{ - Use: "use ", - Short: "set a context as the current context", - Args: cobra.MaximumNArgs(1), - RunE: contextUseCmdFunc, + Use: "use ", + Short: "set a context as the current context", + Args: cobra.MaximumNArgs(1), + RunE: contextUseCmdFunc, + ValidArgsFunction: ContextGet, +} + +func ContextGet(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { + _, secretStore := client.DefaultStorage() + secrets, err := secretStore.Get() + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + + names := make([]string, 0, len(secrets.Tokens)) + for _, token := range secrets.Tokens { + names = append(names, token.Name) + } + + return names, cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveKeepOrder } func contextListCmdFunc(cmd *cobra.Command, _ []string) error { From 597a939d5a027ea937d9e43b7c182d928dbfb5d0 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 28 Dec 2023 17:20:02 -0500 Subject: [PATCH 20/49] Update deps that have vulns --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 12b34a75..32adb872 100644 --- a/go.mod +++ b/go.mod @@ -71,7 +71,7 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlmiddlecote/sqlstats v1.0.2 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/ecordell/optgen v0.0.10-0.20230609182709-018141bf9698 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -188,7 +188,7 @@ require ( go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect diff --git a/go.sum b/go.sum index 17527d60..864be4c8 100644 --- a/go.sum +++ b/go.sum @@ -162,8 +162,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/ecordell/optgen v0.0.10-0.20230609182709-018141bf9698 h1:Ms2IoxhBTljF7ItN1Oj4yy9DVJHn5L4A8sydRkrxoUE= github.com/ecordell/optgen v0.0.10-0.20230609182709-018141bf9698/go.mod h1:+YZ4tk5pNGMoeH+Y4F4HeDDj0SLOlIgMMNae7az4h5g= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= @@ -673,8 +673,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= From 4fb4921fd796944dc39f24f47073c94f05a2e598 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 28 Dec 2023 19:09:41 -0500 Subject: [PATCH 21/49] Add dynamic completion for permissions and relationships commands --- internal/commands/completion.go | 154 ++++++++++++++++++++++++++++++ internal/commands/permission.go | 38 ++++---- internal/commands/relationship.go | 45 +++++---- 3 files changed, 200 insertions(+), 37 deletions(-) create mode 100644 internal/commands/completion.go diff --git a/internal/commands/completion.go b/internal/commands/completion.go new file mode 100644 index 00000000..83ab8236 --- /dev/null +++ b/internal/commands/completion.go @@ -0,0 +1,154 @@ +package commands + +import ( + "errors" + "strings" + + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/authzed/spicedb/pkg/schemadsl/compiler" + "github.com/spf13/cobra" + + "github.com/authzed/zed/internal/client" +) + +type CompletionArgumentType int + +const ( + ResourceType CompletionArgumentType = iota + ResourceID + Permission + SubjectType + SubjectID + SubjectTypeWithOptionalRelation +) + +func GetArgs(fields ...CompletionArgumentType) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // Read the current schema, if any. + schema, err := readSchema(cmd) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + + // Find the specified resource type, if any. + var resourceType string + loop: + for index, arg := range args { + field := fields[index] + switch field { + case ResourceType: + resourceType = arg + break loop + + case ResourceID: + pieces := strings.Split(arg, ":") + if len(pieces) >= 1 { + resourceType = pieces[0] + break loop + } + } + } + + // Handle : on resource and subject IDs. + if strings.HasSuffix(toComplete, ":") && (fields[len(args)] == ResourceID || fields[len(args)] == SubjectID) { + comps := []string{} + comps = cobra.AppendActiveHelp(comps, "Please enter an object ID") + return comps, cobra.ShellCompDirectiveNoFileComp + } + + // Handle # on subject types. If the toComplete contains a valid subject, + // then we should return the relation names. Note that we cannot do this + // on the # character because shell autocompletion won't send it to us. + if len(args) == len(fields)-1 && toComplete != "" && fields[len(args)] == SubjectTypeWithOptionalRelation { + for _, objDef := range schema.ObjectDefinitions { + subjectType := toComplete + if objDef.Name == subjectType { + relationNames := make([]string, 0) + relationNames = append(relationNames, subjectType) + for _, relation := range objDef.Relation { + relationNames = append(relationNames, subjectType+"#"+relation.Name) + } + return relationNames, cobra.ShellCompDirectiveNoFileComp + } + } + } + + if len(args) >= len(fields) { + // If we have all the arguments, return no completions. + return nil, cobra.ShellCompDirectiveNoFileComp + } + + // Return the completions. + currentFieldType := fields[len(args)] + switch currentFieldType { + case ResourceType: + fallthrough + + case SubjectType: + fallthrough + + case SubjectID: + fallthrough + + case SubjectTypeWithOptionalRelation: + fallthrough + + case ResourceID: + resourceTypeNames := make([]string, 0, len(schema.ObjectDefinitions)) + for _, objDef := range schema.ObjectDefinitions { + resourceTypeNames = append(resourceTypeNames, objDef.Name) + } + + flags := cobra.ShellCompDirectiveNoFileComp + if currentFieldType == ResourceID || currentFieldType == SubjectID || currentFieldType == SubjectTypeWithOptionalRelation { + flags |= cobra.ShellCompDirectiveNoSpace + } + + return resourceTypeNames, flags + + case Permission: + if resourceType == "" { + return nil, cobra.ShellCompDirectiveNoFileComp + } + + relationNames := make([]string, 0) + for _, objDef := range schema.ObjectDefinitions { + if objDef.Name == resourceType { + for _, relation := range objDef.Relation { + relationNames = append(relationNames, relation.Name) + } + } + } + return relationNames, cobra.ShellCompDirectiveNoFileComp + } + + return nil, cobra.ShellCompDirectiveDefault + } +} + +func readSchema(cmd *cobra.Command) (*compiler.CompiledSchema, error) { + // TODO: we should find a way to cache this + client, err := client.NewClient(cmd) + if err != nil { + return nil, err + } + + request := &v1.ReadSchemaRequest{} + + resp, err := client.ReadSchema(cmd.Context(), request) + if err != nil { + return nil, err + } + + schemaText := resp.SchemaText + if len(schemaText) == 0 { + return nil, errors.New("no schema defined") + } + + compiledSchema, err := compiler.Compile(compiler.InputSchema{Source: "schema", SchemaString: schemaText}, compiler.SkipValidation()) + if err != nil { + return nil, err + } + + return compiledSchema, nil +} diff --git a/internal/commands/permission.go b/internal/commands/permission.go index fac833de..14e6de23 100644 --- a/internal/commands/permission.go +++ b/internal/commands/permission.go @@ -110,10 +110,11 @@ var permissionCmd = &cobra.Command{ } var checkCmd = &cobra.Command{ - Use: "check ", - Short: "check that a Permission exists for a Subject", - Args: cobra.ExactArgs(3), - RunE: checkCmdFunc, + Use: "check ", + Short: "check that a Permission exists for a Subject", + Args: cobra.ExactArgs(3), + RunE: checkCmdFunc, + ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectID), } var expandCmd = &cobra.Command{ @@ -124,25 +125,28 @@ var expandCmd = &cobra.Command{ } var lookupResourcesCmd = &cobra.Command{ - Use: "lookup-resources ", - Short: "looks up the Resources of a given type for which the Subject has Permission", - Args: cobra.ExactArgs(3), - RunE: lookupResourcesCmdFunc, + Use: "lookup-resources ", + Short: "looks up the Resources of a given type for which the Subject has Permission", + Args: cobra.ExactArgs(3), + RunE: lookupResourcesCmdFunc, + ValidArgsFunction: GetArgs(ResourceType, Permission, SubjectID), } var lookupCmd = &cobra.Command{ - Use: "lookup ", - Short: "lookup the Resources of a given type for which the Subject has Permission", - Args: cobra.ExactArgs(3), - RunE: lookupResourcesCmdFunc, - Hidden: true, + Use: "lookup ", + Short: "lookup the Resources of a given type for which the Subject has Permission", + Args: cobra.ExactArgs(3), + RunE: lookupResourcesCmdFunc, + Hidden: true, + ValidArgsFunction: GetArgs(ResourceType, Permission, SubjectID), } var lookupSubjectsCmd = &cobra.Command{ - Use: "lookup-subjects ", - Short: "lookup the Subjects of a given type for which the Subject has Permission on the Resource", - Args: cobra.ExactArgs(3), - RunE: lookupSubjectsCmdFunc, + Use: "lookup-subjects ", + Short: "lookup the Subjects of a given type for which the Subject has Permission on the Resource", + Args: cobra.ExactArgs(3), + RunE: lookupSubjectsCmdFunc, + ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), } func checkCmdFunc(cmd *cobra.Command, args []string) error { diff --git a/internal/commands/relationship.go b/internal/commands/relationship.go index 35ec81c7..feecbe9d 100644 --- a/internal/commands/relationship.go +++ b/internal/commands/relationship.go @@ -60,38 +60,43 @@ var relationshipCmd = &cobra.Command{ } var createCmd = &cobra.Command{ - Use: "create ", - Short: "create a Relationship for a Subject", - Args: StdinOrExactArgs(3), - RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_CREATE, os.Stdin), + Use: "create ", + Short: "create a Relationship for a Subject", + Args: StdinOrExactArgs(3), + RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_CREATE, os.Stdin), + ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), } var touchCmd = &cobra.Command{ - Use: "touch ", - Short: "idempotently update a Relationship for a Subject", - Args: StdinOrExactArgs(3), - RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_TOUCH, os.Stdin), + Use: "touch ", + Short: "idempotently update a Relationship for a Subject", + Args: StdinOrExactArgs(3), + RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_TOUCH, os.Stdin), + ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), } var deleteCmd = &cobra.Command{ - Use: "delete ", - Short: "delete a Relationship", - Args: StdinOrExactArgs(3), - RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_DELETE, os.Stdin), + Use: "delete ", + Short: "delete a Relationship", + Args: StdinOrExactArgs(3), + RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_DELETE, os.Stdin), + ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), } var readCmd = &cobra.Command{ - Use: "read ", - Short: "reads Relationships", - Args: cobra.RangeArgs(1, 3), - RunE: readRelationships, + Use: "read ", + Short: "reads Relationships", + Args: cobra.RangeArgs(1, 3), + RunE: readRelationships, + ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), } var bulkDeleteCmd = &cobra.Command{ - Use: "bulk-delete ", - Short: "bulk delete Relationships", - Args: cobra.RangeArgs(1, 3), - RunE: bulkDeleteRelationships, + Use: "bulk-delete ", + Short: "bulk delete Relationships", + Args: cobra.RangeArgs(1, 3), + RunE: bulkDeleteRelationships, + ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), } func StdinOrExactArgs(n int) cobra.PositionalArgs { From 8e695d5050fccf9d353bcfaf406a1b2866550e98 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Fri, 29 Dec 2023 16:14:09 -0500 Subject: [PATCH 22/49] Support validate (and import) taking in a schema directly Fixes #287 --- internal/cmd/import.go | 2 +- internal/cmd/validate.go | 13 +++++--- internal/decode/decoder.go | 54 +++++++++++++++++++++++++++------ internal/decode/decoder_test.go | 47 ++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 14 deletions(-) diff --git a/internal/cmd/import.go b/internal/cmd/import.go index d879384e..9a50aa37 100644 --- a/internal/cmd/import.go +++ b/internal/cmd/import.go @@ -77,7 +77,7 @@ func importCmdFunc(cmd *cobra.Command, args []string) error { return err } var p decode.SchemaRelationships - if _, err := decoder(&p); err != nil { + if _, _, err := decoder(&p); err != nil { return err } diff --git a/internal/cmd/validate.go b/internal/cmd/validate.go index 4be83a9b..1cb33f27 100644 --- a/internal/cmd/validate.go +++ b/internal/cmd/validate.go @@ -40,8 +40,8 @@ func registerValidateCmd(rootCmd *cobra.Command) { } var validateCmd = &cobra.Command{ - Use: "validate ", - Short: "validate the given validation file", + Use: "validate ", + Short: "validate the given validation or schema file", Example: ` From a local file (with prefix): zed validate file:///Users/zed/Downloads/authzed-x7izWU8_2Gw3.yaml @@ -78,7 +78,7 @@ func validateCmdFunc(cmd *cobra.Command, args []string) error { // Decode the validation document. var parsed validationfile.ValidationFile - validateContents, err := decoder(&parsed) + validateContents, isOnlySchema, err := decoder(&parsed) if err != nil { var errWithSource spiceerrors.ErrorWithSource if errors.As(err, &errWithSource) { @@ -102,7 +102,12 @@ func validateCmdFunc(cmd *cobra.Command, args []string) error { return err } if devErrs != nil { - outputDeveloperErrorsWithLineOffset(validateContents, devErrs.InputErrors, 1 /* for the 'schema:' */) + schemaOffset := 1 /* for the 'schema:' */ + if isOnlySchema { + schemaOffset = 0 + } + + outputDeveloperErrorsWithLineOffset(validateContents, devErrs.InputErrors, schemaOffset) } // Run assertions. diff --git a/internal/decode/decoder.go b/internal/decode/decoder.go index 4c01fdf1..241615b9 100644 --- a/internal/decode/decoder.go +++ b/internal/decode/decoder.go @@ -10,6 +10,11 @@ import ( "regexp" "strings" + "github.com/authzed/spicedb/pkg/schemadsl/compiler" + "github.com/authzed/spicedb/pkg/schemadsl/input" + "github.com/authzed/spicedb/pkg/spiceerrors" + "github.com/authzed/spicedb/pkg/validationfile" + "github.com/authzed/spicedb/pkg/validationfile/blocks" "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" ) @@ -24,7 +29,7 @@ type SchemaRelationships struct { } // Func will decode into the supplied object. -type Func func(out interface{}) ([]byte, error) +type Func func(out interface{}) ([]byte, bool, error) // DecoderForURL returns the appropriate decoder for a given URL. // Some URLs have special handling to dereference to the actual file. @@ -43,16 +48,17 @@ func DecoderForURL(u *url.URL) (d Func, err error) { } func fileDecoder(u *url.URL) Func { - return func(out interface{}) ([]byte, error) { + return func(out interface{}) ([]byte, bool, error) { file, err := os.Open(u.Path) if err != nil { - return nil, err + return nil, false, err } data, err := io.ReadAll(file) if err != nil { - return nil, err + return nil, false, err } - return data, yaml.Unmarshal(data, out) + isOnlySchema, err := unmarshalAsYAMLOrSchema(data, out) + return data, isOnlySchema, err } } @@ -82,18 +88,48 @@ func rewriteURL(u *url.URL) { } func directHTTPDecoder(u *url.URL) Func { - return func(out interface{}) ([]byte, error) { + return func(out interface{}) ([]byte, bool, error) { log.Debug().Stringer("url", u).Send() r, err := http.Get(u.String()) if err != nil { - return nil, err + return nil, false, err } defer r.Body.Close() data, err := io.ReadAll(r.Body) if err != nil { - return nil, err + return nil, false, err } - return data, yaml.Unmarshal(data, out) + isOnlySchema, err := unmarshalAsYAMLOrSchema(data, out) + return data, isOnlySchema, err } } + +func unmarshalAsYAMLOrSchema(data []byte, out interface{}) (bool, error) { + // Check for indications of a schema-only file. + if !strings.Contains(string(data), "schema:") { + compiled, serr := compiler.Compile(compiler.InputSchema{ + Source: input.Source("schema"), SchemaString: string(data), + }) + if serr != nil { + return false, serr + } + + // If that succeeds, return the compiled schema. + vfile := *out.(*validationfile.ValidationFile) + vfile.Schema = blocks.ParsedSchema{ + CompiledSchema: compiled, + Schema: string(data), + SourcePosition: spiceerrors.SourcePosition{LineNumber: 1, ColumnPosition: 1}, + } + *out.(*validationfile.ValidationFile) = vfile + return true, nil + } + + // Try to unparse as YAML for the validation file format. + if err := yaml.Unmarshal(data, out); err != nil { + return false, err + } + + return false, nil +} diff --git a/internal/decode/decoder_test.go b/internal/decode/decoder_test.go index 06c5fcad..9d91e9ee 100644 --- a/internal/decode/decoder_test.go +++ b/internal/decode/decoder_test.go @@ -4,6 +4,7 @@ import ( "net/url" "testing" + "github.com/authzed/spicedb/pkg/validationfile" "github.com/stretchr/testify/require" ) @@ -126,3 +127,49 @@ func TestRewriteURL(t *testing.T) { }) } } + +func TestUnmarshalAsYAMLOrSchema(t *testing.T) { + tests := []struct { + name string + in []byte + isOnlySchema bool + outSchema string + wantErr bool + }{ + { + name: "valid yaml", + in: []byte(` +schema: + definition user {} +`), + outSchema: `definition user {}`, + isOnlySchema: false, + wantErr: false, + }, + { + name: "valid schema", + in: []byte(`definition user {}`), + isOnlySchema: true, + outSchema: `definition user {}`, + wantErr: false, + }, + { + name: "invalid yaml", + in: []byte(`invalid yaml`), + isOnlySchema: false, + outSchema: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + block := validationfile.ValidationFile{} + isOnlySchema, err := unmarshalAsYAMLOrSchema(tt.in, &block) + require.Equal(t, tt.wantErr, err != nil) + require.Equal(t, tt.isOnlySchema, isOnlySchema) + if !tt.wantErr { + require.Equal(t, tt.outSchema, block.Schema.Schema) + } + }) + } +} From 81ff2a74fd3ab53341d845da1fa1339268c91e41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 08:56:13 +0000 Subject: [PATCH 23/49] build(deps): bump github.com/samber/lo from 1.38.1 to 1.39.0 Bumps [github.com/samber/lo](https://github.com/samber/lo) from 1.38.1 to 1.39.0. - [Release notes](https://github.com/samber/lo/releases) - [Changelog](https://github.com/samber/lo/blob/master/CHANGELOG.md) - [Commits](https://github.com/samber/lo/compare/v1.38.1...v1.39.0) --- updated-dependencies: - dependency-name: github.com/samber/lo dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 32adb872..43b92c68 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/rs/zerolog v1.31.0 - github.com/samber/lo v1.38.1 + github.com/samber/lo v1.39.0 github.com/schollz/progressbar/v3 v3.14.1 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 864be4c8..4671e554 100644 --- a/go.sum +++ b/go.sum @@ -555,8 +555,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= -github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= +github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/schollz/progressbar/v3 v3.14.1 h1:VD+MJPCr4s3wdhTc7OEJ/Z3dAeBzJ7yKH/P4lC5yRTI= github.com/schollz/progressbar/v3 v3.14.1/go.mod h1:Zc9xXneTzWXF81TGoqL71u0sBPjULtEHYtj/WVgVy8E= github.com/scylladb/go-set v1.0.2 h1:SkvlMCKhP0wyyct6j+0IHJkBkSZL+TDzZ4E7f7BCcRE= From 298abbd666f8006dc090369b197562038e102fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Mon, 18 Dec 2023 14:20:23 +0000 Subject: [PATCH 24/49] refactor backup import to handle serialization errors and conflicts This commit refactors the logic on the backup command into a restorer type. The fundamental differences with the previous logic are: - batch conflicts are detected, and provides to handling strategies: fail, skip or touch when using touch, they will also be retried if needed - serialization errors are detected, and optionally can be retried using WithRelationships with TOUCH semantics - retry strategy uses a backoff any error on bulk import will cause the stream to close, so attempts to recover from that by retrying means retrying with another bulk import stream or using WriteRelationships. The latter was used because it normalizes retries as BulkImport does not support TOUCH semantics. --- go.mod | 2 +- internal/cmd/backup.go | 108 +-------- internal/cmd/backup_test.go | 3 + internal/cmd/restorer.go | 317 +++++++++++++++++++++++++ internal/commands/relationship_test.go | 6 +- internal/grpcutil/grpcutil.go | 87 +++---- 6 files changed, 383 insertions(+), 140 deletions(-) create mode 100644 internal/cmd/restorer.go diff --git a/go.mod b/go.mod index 32adb872..3ab09c24 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da github.com/brianvoe/gofakeit/v6 v6.26.3 + github.com/cenkalti/backoff/v4 v4.2.1 github.com/charmbracelet/lipgloss v0.9.1 github.com/google/uuid v1.4.0 github.com/gookit/color v1.5.4 @@ -57,7 +58,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.6.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 0edf66ab..9dce090b 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -87,6 +87,9 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupCmd.AddCommand(backupRestoreCmd) backupRestoreCmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") backupRestoreCmd.Flags().Int64("batches-per-transaction", 10, "number of batches per transaction") + backupRestoreCmd.Flags().Bool("skip-conflicts", false, "skips any batch found to be conflicting") + backupRestoreCmd.Flags().Bool("touch-conflicts", false, "retries writing conflicting batches with TOUCH semantics") + backupRestoreCmd.Flags().Bool("disable-retries", false, "retries when an errors is determined to be retryable (e.g. serialization errors)") backupRestoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") backupRestoreCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") @@ -377,118 +380,29 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { } log.Debug().Str("schema", schema).Bool("filtered", prefixFilter != "").Msg("parsed schema") - client, err := client.NewClient(cmd) + c, err := client.NewClient(cmd) if err != nil { return fmt.Errorf("unable to initialize client: %w", err) } ctx := cmd.Context() - if _, err := client.WriteSchema(ctx, &v1.WriteSchemaRequest{ + if _, err := c.WriteSchema(ctx, &v1.WriteSchemaRequest{ Schema: schema, }); err != nil { return fmt.Errorf("unable to write schema: %w", err) } - relationshipWriteStart := time.Now() - - relationshipWriter, err := client.BulkImportRelationships(ctx) - if err != nil { - return fmt.Errorf("error creating writer stream: %w", err) - } - batchSize := cobrautil.MustGetInt(cmd, "batch-size") batchesPerTransaction := cobrautil.MustGetInt64(cmd, "batches-per-transaction") - batch := make([]*v1.Relationship, 0, batchSize) - var written, batchesWritten int64 - bar := relProgressBar("restoring from backup") - for rel, err := decoder.Next(); rel != nil && err == nil; rel, err = decoder.Next() { - if err := ctx.Err(); err != nil { - return fmt.Errorf("aborted restore: %w", err) - } - - if !hasRelPrefix(rel, prefixFilter) { - continue - } - - batch = append(batch, rel) - - if len(batch)%batchSize == 0 { - if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ - Relationships: batch, - }); err != nil { - _, closeErr := relationshipWriter.CloseAndRecv() - return fmt.Errorf("error sending batch to server: %w", errors.Join(err, closeErr)) - } - - // Reset the relationships in the batch - batch = batch[:0] - batchesWritten++ - - if batchesWritten%batchesPerTransaction == 0 { - resp, err := relationshipWriter.CloseAndRecv() - if err != nil { - return fmt.Errorf("error finalizing write of %d batches: %w", batchesPerTransaction, err) - } - written += int64(resp.NumLoaded) - if err := bar.Set64(written); err != nil { - return fmt.Errorf("error incrementing progress bar: %w", err) - } - - if !isatty.IsTerminal(os.Stderr.Fd()) { - log.Trace(). - Int64("batches", batchesWritten). - Int64("relationships", written). - Msg("restore progress") - } - - relationshipWriter, err = client.BulkImportRelationships(ctx) - if err != nil { - return fmt.Errorf("error creating new writer stream: %w", err) - } - } - } - } - - // Write the last batch - if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ - Relationships: batch, - }); err != nil { - return fmt.Errorf("error sending last batch to server: %w", err) + skipConflicts := cobrautil.MustGetBool(cmd, "skip-conflicts") + touchConflicts := cobrautil.MustGetBool(cmd, "touch-conflicts") + disableRetries := cobrautil.MustGetBool(cmd, "disable-retries") + if touchConflicts && skipConflicts { + return errors.New("cannot use --skip-conflicts and --touch-conflicts together") } - // Finish the stream - resp, err := relationshipWriter.CloseAndRecv() - if err != nil { - return fmt.Errorf("error finalizing last write: %w", err) - } - batchesWritten++ - written += int64(resp.NumLoaded) - if err := bar.Set64(written); err != nil { - return fmt.Errorf("error incrementing progress bar: %w", err) - } - totalTime := time.Since(relationshipWriteStart) - - if err := bar.Finish(); err != nil { - return fmt.Errorf("error finalizing progress bar: %w", err) - } - - log.Info(). - Int64("batches", batchesWritten). - Int64("relationships", written). - Uint64("perSecond", perSec(uint64(written), totalTime)). - Stringer("duration", totalTime). - Msg("finished restore") - - return nil -} - -func perSec(i uint64, d time.Duration) uint64 { - secs := uint64(d.Seconds()) - if secs == 0 { - return i - } - return i / secs + return newRestorer(decoder, c, prefixFilter, batchSize, batchesPerTransaction, skipConflicts, touchConflicts, disableRetries).restoreFromDecoder(ctx) } func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index 8a452b59..de33a791 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -327,6 +327,9 @@ func TestBackupRestoreCmdFunc(t *testing.T) { cmd := createTestCobraCommandWithFlagValue(t, stringFlag{"prefix-filter", "test"}, boolFlag{"rewrite-legacy", false}, + boolFlag{"skip-conflicts", false}, + boolFlag{"touch-conflicts", false}, + boolFlag{"disable-retries", false}, intFlag{"batch-size", 100}, int64Flag{"batches-per-transaction", 10}, ) diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go new file mode 100644 index 00000000..92c5ce59 --- /dev/null +++ b/internal/cmd/restorer.go @@ -0,0 +1,317 @@ +package cmd + +import ( + "context" + "fmt" + "os" + "strings" + "time" + + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/cenkalti/backoff/v4" + "github.com/mattn/go-isatty" + "github.com/rs/zerolog/log" + "github.com/samber/lo" + "github.com/schollz/progressbar/v3" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/authzed/zed/internal/client" + "github.com/authzed/zed/pkg/backupformat" +) + +type restorer struct { + decoder *backupformat.Decoder + client client.Client + prefixFilter string + batchSize int + batchesPerTransaction int64 + skipOnConflicts bool + touchOnConflicts bool + disableRetryErrors bool + bar *progressbar.ProgressBar + + // stats + relsWritten int64 + batchesWritten int64 + relsSkipped int64 + duplicateRels int64 + totalRetries int64 +} + +func newRestorer(decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, + batchesPerTransaction int64, skipOnConflicts bool, touchOnConflicts bool, disableRetryErrors bool, +) *restorer { + return &restorer{ + decoder: decoder, + client: client, + prefixFilter: prefixFilter, + batchSize: batchSize, + batchesPerTransaction: batchesPerTransaction, + skipOnConflicts: skipOnConflicts, + touchOnConflicts: touchOnConflicts, + disableRetryErrors: disableRetryErrors, + bar: relProgressBar("restoring from backup"), + } +} + +func (r *restorer) restoreFromDecoder(ctx context.Context) error { + relationshipWriteStart := time.Now() + defer func() { + if err := r.bar.Finish(); err != nil { + log.Err(err).Msg("error finalizing progress bar") + } + }() + + relationshipWriter, err := r.client.BulkImportRelationships(ctx) + if err != nil { + return fmt.Errorf("error creating writer stream: %w", err) + } + + batch := make([]*v1.Relationship, 0, r.batchSize) + batchesToBeCommitted := make([][]*v1.Relationship, 0, r.batchesPerTransaction) + for rel, err := r.decoder.Next(); rel != nil && err == nil; rel, err = r.decoder.Next() { + if err := ctx.Err(); err != nil { + return fmt.Errorf("aborted restore: %w", err) + } + + if !hasRelPrefix(rel, r.prefixFilter) { + continue + } + + batch = append(batch, rel) + + if len(batch)%r.batchSize == 0 { + batchesToBeCommitted = append(batchesToBeCommitted, batch) + err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ + Relationships: batch, + }) + if err != nil { + r.totalRetries++ + + // It feels non-idiomatic to check for error and perform an operation, but in gRPC, when an element + // sent over the stream fails, we need to call recvAndClose() to get the error. + if err := r.commitStream(ctx, relationshipWriter, batchesToBeCommitted); err != nil { + return fmt.Errorf("error committing batches: %w", err) + } + + // after an error + relationshipWriter, err = r.client.BulkImportRelationships(ctx) + if err != nil { + return fmt.Errorf("error creating new writer stream: %w", err) + } + + batchesToBeCommitted = batchesToBeCommitted[:0] + batch = batch[:0] + continue + } + + // Reset the relationships in the batch. Do not reuse in case failure happens on subsequent batch in the tx + batch = make([]*v1.Relationship, 0, r.batchSize) + r.batchesWritten++ + + // if we've sent the maximum number of batches per transaction, proceed to commit + if r.batchesWritten%r.batchesPerTransaction != 0 { + continue + } + + if err := r.commitStream(ctx, relationshipWriter, batchesToBeCommitted); err != nil { + return fmt.Errorf("error committing batches: %w", err) + } + + relationshipWriter, err = r.client.BulkImportRelationships(ctx) + if err != nil { + return fmt.Errorf("error creating new writer stream: %w", err) + } + + batchesToBeCommitted = batchesToBeCommitted[:0] + } + } + + // Write the last batch + if len(batch) > 0 { + if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ + Relationships: batch, + }); err != nil { + return fmt.Errorf("error sending last batch to server: %w", err) + } + } + + if err := r.commitStream(ctx, relationshipWriter, batchesToBeCommitted); err != nil { + return fmt.Errorf("error committing last set of batches: %w", err) + } + + r.bar.Describe("complected import") + if err := r.bar.Finish(); err != nil { + log.Err(err).Msg("error finalizing progress bar") + } + + totalTime := time.Since(relationshipWriteStart) + log.Info(). + Int64("batches", r.batchesWritten). + Int64("relationships_loaded", r.relsWritten). + Int64("relationships_skipped", r.relsSkipped). + Int64("duplicate_relationships", r.duplicateRels). + Int64("retried_errors", r.totalRetries). + Uint64("perSecond", perSec(uint64(r.relsWritten), totalTime)). + Stringer("duration", totalTime). + Msg("finished restore") + return nil +} + +func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.ExperimentalService_BulkImportRelationshipsClient, + batchesToBeCommitted [][]*v1.Relationship, +) error { + var numLoaded, expectedLoaded, retries uint64 + for _, b := range batchesToBeCommitted { + expectedLoaded += uint64(len(b)) + } + + resp, err := bulkImportClient.CloseAndRecv() // transaction commit happens here + + // Failure to commit transaction means the stream is closed, so it can't be reused any further + // The retry will be done using WriteRelationships instead of BulkImportRelationships + // This lets us retry with TOUCH semantics in case of failure due to duplicates + retryable := isRetryableError(err) + conflict := isAlreadyExistsError(err) + unknown := !retryable && !conflict && err != nil + + switch { + case unknown: + r.bar.Describe("failed with unrecoverable error") + return fmt.Errorf("error finalizing write of %d batches: %w", len(batchesToBeCommitted), err) + case retryable && r.disableRetryErrors: + return err + case conflict && r.skipOnConflicts: + r.relsSkipped += int64(expectedLoaded) + r.duplicateRels += int64(expectedLoaded) + numLoaded = expectedLoaded + r.bar.Describe("skipping conflicting batch") + case conflict && r.touchOnConflicts: + r.bar.Describe("retrying conflicting batch") + r.duplicateRels += int64(expectedLoaded) + numLoaded, retries, err = r.writeBatchesWithRetry(ctx, batchesToBeCommitted) + if err != nil { + return fmt.Errorf("failed to write retried batch: %w", err) + } + case conflict && !r.touchOnConflicts: + r.bar.Describe("conflict detected, aborting restore") + return fmt.Errorf("duplicate relationships found") + case retryable: + r.bar.Describe("retrying after error") + numLoaded, retries, err = r.writeBatchesWithRetry(ctx, batchesToBeCommitted) + if err != nil { + return fmt.Errorf("failed to write retried batch: %w", err) + } + default: + r.bar.Describe("restoring from backup") + } + + // it was a successful transaction commit without duplicates + if resp != nil { + numLoaded = resp.NumLoaded + + var expected uint64 + for _, b := range batchesToBeCommitted { + expected += uint64(len(b)) + } + + if expected != numLoaded { + log.Warn().Uint64("loaded", numLoaded).Uint64("expected", expected).Msg("unexpected number of relationships loaded") + } + } + + r.relsWritten += int64(numLoaded) + if err := r.bar.Set64(r.relsWritten); err != nil { + return fmt.Errorf("error incrementing progress bar: %w", err) + } + + if !isatty.IsTerminal(os.Stderr.Fd()) { + log.Trace(). + Int64("batches_written", r.batchesWritten). + Int64("relationships_written", r.relsWritten). + Int64("duplicate_relationships", r.duplicateRels). + Uint64("retries", retries). + Msg("restore progress") + } + + return nil +} + +// writeBatchesWithRetry writes a set of batches using touch semantics and without transactional guarantees - +// each batch will be committed independently. If a batch fails, it will be retried up to 10 times with a backoff. +func (r *restorer) writeBatchesWithRetry(ctx context.Context, batches [][]*v1.Relationship) (uint64, uint64, error) { + backoffInterval := backoff.NewExponentialBackOff() + backoffInterval.InitialInterval = 10 * time.Millisecond + backoffInterval.MaxInterval = 2 * time.Second + backoffInterval.MaxElapsedTime = 0 + backoffInterval.Reset() + + var currentRetries, totalRetries, loadedRels uint64 + for _, batch := range batches { + updates := lo.Map[*v1.Relationship, *v1.RelationshipUpdate](batch, func(item *v1.Relationship, index int) *v1.RelationshipUpdate { + return &v1.RelationshipUpdate{ + Relationship: item, + Operation: v1.RelationshipUpdate_OPERATION_TOUCH, + } + }) + + for { + // throttle the writes so we don't overwhelm the server + time.Sleep(backoffInterval.NextBackOff()) + _, err := r.client.WriteRelationships(ctx, &v1.WriteRelationshipsRequest{Updates: updates}) + + if isRetryableError(err) && currentRetries < 10 { + currentRetries++ + r.totalRetries++ + totalRetries++ + continue + } + if err != nil { + return 0, 0, fmt.Errorf("error on attempting to WriteRelationships a previously failed batch: %w", err) + } + + currentRetries = 0 + backoffInterval.Reset() + loadedRels += uint64(len(batch)) + break + } + } + + return loadedRels, totalRetries, nil +} + +func isAlreadyExistsError(err error) bool { + if err == nil { + return false + } + + if s, ok := status.FromError(err); ok { + if s.Code() == codes.Unavailable { + return true + } + } + + // FIXME temporary hack until a proper error is exposed from the API, specific to CRDB + return strings.Contains(err.Error(), "SQLSTATE 23505") +} + +func isRetryableError(err error) bool { + if err == nil { + return false + } + + if strings.Contains(err.Error(), "RETRY_SERIALIZABLE") { // FIXME hack until SpiceDB exposes proper typed err + return true + } + + return false +} + +func perSec(i uint64, d time.Duration) uint64 { + secs := uint64(d.Seconds()) + if secs == 0 { + return i + } + return i / secs +} diff --git a/internal/commands/relationship_test.go b/internal/commands/relationship_test.go index a704a123..ca525f40 100644 --- a/internal/commands/relationship_test.go +++ b/internal/commands/relationship_test.go @@ -10,6 +10,7 @@ import ( v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/pkg/tuple" + "github.com/rs/zerolog" "github.com/spf13/cobra" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -17,6 +18,10 @@ import ( "google.golang.org/protobuf/types/known/structpb" ) +func init() { + zerolog.SetGlobalLevel(zerolog.Disabled) +} + func TestRelationshipToString(t *testing.T) { for _, tt := range []struct { rawRel string @@ -130,7 +135,6 @@ func TestArgsToRelationship(t *testing.T) { t.Run(strings.Join(tt.args, " "), func(t *testing.T) { rel, err := argsToRelationship(tt.args) require.NoError(t, err) - t.Log(rel) require.True(t, proto.Equal(rel, tt.expected)) }) } diff --git a/internal/grpcutil/grpcutil.go b/internal/grpcutil/grpcutil.go index bd4239b3..bfc7993b 100644 --- a/internal/grpcutil/grpcutil.go +++ b/internal/grpcutil/grpcutil.go @@ -4,6 +4,7 @@ import ( "context" "errors" "io" + "sync" "time" "github.com/authzed/authzed-go/pkg/requestmeta" @@ -23,6 +24,8 @@ var ( _ grpc.UnaryClientInterceptor = grpc.UnaryClientInterceptor(CheckServerVersion) ) +var once sync.Once + // CheckServerVersion implements a gRPC unary interceptor that requests the server version // from SpiceDB and, if found, compares it to the current released version. func CheckServerVersion( @@ -40,51 +43,53 @@ func CheckServerVersion( return err } - version := headerMD.Get(string(responsemeta.ServerVersion)) - if len(version) == 0 { - log.Debug().Msg("error reading server version response header; it may be disabled on the server") - } else if len(version) == 1 { - currentVersion := version[0] - - // If there is a build on the version, then do not compare. - if semver.Build(currentVersion) != "" { - log.Debug().Str("this-version", currentVersion).Msg("received build version of SpiceDB") - return nil - } + once.Do(func() { + version := headerMD.Get(string(responsemeta.ServerVersion)) + if len(version) == 0 { + log.Debug().Msg("error reading server version response header; it may be disabled on the server") + } else if len(version) == 1 { + currentVersion := version[0] + + // If there is a build on the version, then do not compare. + if semver.Build(currentVersion) != "" { + log.Debug().Str("this-version", currentVersion).Msg("received build version of SpiceDB") + return + } - rctx, cancel := context.WithTimeout(ctx, time.Second*2) - defer cancel() - - state, _, release, cerr := releases.CheckIsLatestVersion(rctx, func() (string, error) { - return currentVersion, nil - }, releases.GetLatestRelease) - if cerr != nil { - log.Debug().Err(cerr).Msg("error looking up currently released version") - } else { - switch state { - case releases.UnreleasedVersion: - log.Warn().Str("version", currentVersion).Msg("not calling a released version of SpiceDB") - return nil - - case releases.UpdateAvailable: - log.Warn().Str("this-version", currentVersion).Str("latest-released-version", release.Version).Msgf("the version of SpiceDB being called is out of date. See: %s", release.ViewURL) - return nil - - case releases.UpToDate: - log.Debug().Str("latest-released-version", release.Version).Msg("the version of SpiceDB being called is the latest released version") - return nil - - case releases.Unknown: - log.Warn().Str("unknown-released-version", release.Version).Msg("unable to check for a new SpiceDB version") - return nil - - default: - panic("Unknown state for CheckAndLogRunE") + rctx, cancel := context.WithTimeout(ctx, time.Second*2) + defer cancel() + + state, _, release, cerr := releases.CheckIsLatestVersion(rctx, func() (string, error) { + return currentVersion, nil + }, releases.GetLatestRelease) + if cerr != nil { + log.Debug().Err(cerr).Msg("error looking up currently released version") + } else { + switch state { + case releases.UnreleasedVersion: + log.Warn().Str("version", currentVersion).Msg("not calling a released version of SpiceDB") + return + + case releases.UpdateAvailable: + log.Warn().Str("this-version", currentVersion).Str("latest-released-version", release.Version).Msgf("the version of SpiceDB being called is out of date. See: %s", release.ViewURL) + return + + case releases.UpToDate: + log.Debug().Str("latest-released-version", release.Version).Msg("the version of SpiceDB being called is the latest released version") + return + + case releases.Unknown: + log.Warn().Str("unknown-released-version", release.Version).Msg("unable to check for a new SpiceDB version") + return + + default: + panic("Unknown state for CheckAndLogRunE") + } } } - } + }) - return err + return nil } // LogDispatchTrailers implements a gRPC unary interceptor that logs the From e5173274a648b32db938dd98dcd74e6aecac7108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Tue, 19 Dec 2023 10:31:48 +0000 Subject: [PATCH 25/49] introduce restorer tests and adjust implementation accordingly --- internal/cmd/backup.go | 12 +- internal/cmd/backup_test.go | 2 +- internal/cmd/restorer.go | 119 ++++++++++------ internal/cmd/restorer_test.go | 249 ++++++++++++++++++++++++++++++++++ 4 files changed, 332 insertions(+), 50 deletions(-) create mode 100644 internal/cmd/restorer_test.go diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 9dce090b..add94092 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -350,7 +350,7 @@ func openRestoreFile(filename string) (*os.File, int64, error) { } func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { - decoder, closer, err := decoderFromArgs(cmd, args) + decoder, closer, err := decoderFromArgs(args...) if err != nil { return err } @@ -406,7 +406,7 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { } func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { - decoder, closer, err := decoderFromArgs(cmd, args) + decoder, closer, err := decoderFromArgs(args...) if err != nil { return err } @@ -434,8 +434,8 @@ func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) return err } -func backupParseRevisionCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { - decoder, closer, err := decoderFromArgs(cmd, args) +func backupParseRevisionCmdFunc(_ *cobra.Command, out io.Writer, args []string) error { + decoder, closer, err := decoderFromArgs(args...) if err != nil { return err } @@ -454,7 +454,7 @@ func backupParseRevisionCmdFunc(cmd *cobra.Command, out io.Writer, args []string func backupParseRelsCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { prefix := cobrautil.MustGetString(cmd, "prefix-filter") - decoder, closer, err := decoderFromArgs(cmd, args) + decoder, closer, err := decoderFromArgs(args...) if err != nil { return err } @@ -480,7 +480,7 @@ func backupParseRelsCmdFunc(cmd *cobra.Command, out io.Writer, args []string) er return nil } -func decoderFromArgs(_ *cobra.Command, args []string) (*backupformat.Decoder, io.Closer, error) { +func decoderFromArgs(args ...string) (*backupformat.Decoder, io.Closer, error) { filename := "" // Default to stdin. if len(args) > 0 { filename = args[0] diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index de33a791..22324dca 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -309,7 +309,7 @@ func TestBackupCreateCmdFunc(t *testing.T) { err = backupCreateCmdFunc(cmd, []string{f}) require.NoError(t, err) - d, closer, err := decoderFromArgs(cmd, []string{f}) + d, closer, err := decoderFromArgs(f) require.NoError(t, err) defer func() { _ = d.Close() diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 92c5ce59..1f776c34 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -20,6 +20,12 @@ import ( "github.com/authzed/zed/pkg/backupformat" ) +// Fallback for CRDB datastore on SpiceDB < 1.29.0 not returning proper gRPC codes +var ( + txConflictCodes = []string{"SQLSTATE 23505"} + retryableErrorCodes = []string{"retryable error"} +) + type restorer struct { decoder *backupformat.Decoder client client.Client @@ -32,11 +38,14 @@ type restorer struct { bar *progressbar.ProgressBar // stats - relsWritten int64 - batchesWritten int64 - relsSkipped int64 - duplicateRels int64 - totalRetries int64 + filteredOutRels int64 + writtenRels int64 + writtenBatches int64 + skippedRels int64 + skippedBatches int64 + duplicateRels int64 + duplicateBatches int64 + totalRetries int64 } func newRestorer(decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, @@ -59,7 +68,7 @@ func (r *restorer) restoreFromDecoder(ctx context.Context) error { relationshipWriteStart := time.Now() defer func() { if err := r.bar.Finish(); err != nil { - log.Err(err).Msg("error finalizing progress bar") + log.Warn().Err(err).Msg("error finalizing progress bar") } }() @@ -72,10 +81,12 @@ func (r *restorer) restoreFromDecoder(ctx context.Context) error { batchesToBeCommitted := make([][]*v1.Relationship, 0, r.batchesPerTransaction) for rel, err := r.decoder.Next(); rel != nil && err == nil; rel, err = r.decoder.Next() { if err := ctx.Err(); err != nil { + r.bar.Describe("backup restore aborted") return fmt.Errorf("aborted restore: %w", err) } if !hasRelPrefix(rel, r.prefixFilter) { + r.filteredOutRels++ continue } @@ -87,8 +98,6 @@ func (r *restorer) restoreFromDecoder(ctx context.Context) error { Relationships: batch, }) if err != nil { - r.totalRetries++ - // It feels non-idiomatic to check for error and perform an operation, but in gRPC, when an element // sent over the stream fails, we need to call recvAndClose() to get the error. if err := r.commitStream(ctx, relationshipWriter, batchesToBeCommitted); err != nil { @@ -106,12 +115,12 @@ func (r *restorer) restoreFromDecoder(ctx context.Context) error { continue } - // Reset the relationships in the batch. Do not reuse in case failure happens on subsequent batch in the tx + // The batch just sent is kept in batchesToBeCommitted, which is used for retries. + // Therefore, we cannot reuse the batch. Batches may fail on send, or on commit (CloseAndRecv). batch = make([]*v1.Relationship, 0, r.batchSize) - r.batchesWritten++ // if we've sent the maximum number of batches per transaction, proceed to commit - if r.batchesWritten%r.batchesPerTransaction != 0 { + if int64(len(batchesToBeCommitted))%r.batchesPerTransaction != 0 { continue } @@ -130,30 +139,32 @@ func (r *restorer) restoreFromDecoder(ctx context.Context) error { // Write the last batch if len(batch) > 0 { - if err := relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{ - Relationships: batch, - }); err != nil { - return fmt.Errorf("error sending last batch to server: %w", err) - } + // Since we are going to close the stream anyway after the last batch, and given the actual error + // is only returned on CloseAndRecv(), we have to ignore the error here in order to get the actual + // underlying error that caused Send() to fail. It also gives us the opportunity to retry it + // in case it failed. + batchesToBeCommitted = append(batchesToBeCommitted, batch) + _ = relationshipWriter.Send(&v1.BulkImportRelationshipsRequest{Relationships: batch}) } if err := r.commitStream(ctx, relationshipWriter, batchesToBeCommitted); err != nil { return fmt.Errorf("error committing last set of batches: %w", err) } - r.bar.Describe("complected import") + r.bar.Describe("completed import") if err := r.bar.Finish(); err != nil { - log.Err(err).Msg("error finalizing progress bar") + log.Warn().Err(err).Msg("error finalizing progress bar") } totalTime := time.Since(relationshipWriteStart) log.Info(). - Int64("batches", r.batchesWritten). - Int64("relationships_loaded", r.relsWritten). - Int64("relationships_skipped", r.relsSkipped). + Int64("batches", r.writtenBatches). + Int64("relationships_loaded", r.writtenRels). + Int64("relationships_skipped", r.skippedRels). Int64("duplicate_relationships", r.duplicateRels). + Int64("relationships_filtered_out", r.filteredOutRels). Int64("retried_errors", r.totalRetries). - Uint64("perSecond", perSec(uint64(r.relsWritten), totalTime)). + Uint64("perSecond", perSec(uint64(r.writtenRels+r.skippedRels), totalTime)). Stringer("duration", totalTime). Msg("finished restore") return nil @@ -183,54 +194,63 @@ func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.Experim case retryable && r.disableRetryErrors: return err case conflict && r.skipOnConflicts: - r.relsSkipped += int64(expectedLoaded) + r.skippedRels += int64(expectedLoaded) + r.skippedBatches += int64(len(batchesToBeCommitted)) + r.duplicateBatches += int64(len(batchesToBeCommitted)) r.duplicateRels += int64(expectedLoaded) - numLoaded = expectedLoaded r.bar.Describe("skipping conflicting batch") case conflict && r.touchOnConflicts: r.bar.Describe("retrying conflicting batch") r.duplicateRels += int64(expectedLoaded) + r.duplicateBatches += int64(len(batchesToBeCommitted)) + r.totalRetries++ numLoaded, retries, err = r.writeBatchesWithRetry(ctx, batchesToBeCommitted) if err != nil { return fmt.Errorf("failed to write retried batch: %w", err) } - case conflict && !r.touchOnConflicts: + + retries++ // account for the initial attempt + r.writtenBatches += int64(len(batchesToBeCommitted)) + r.writtenRels += int64(numLoaded) + case conflict && (!r.touchOnConflicts && !r.skipOnConflicts): r.bar.Describe("conflict detected, aborting restore") return fmt.Errorf("duplicate relationships found") case retryable: r.bar.Describe("retrying after error") + r.totalRetries++ numLoaded, retries, err = r.writeBatchesWithRetry(ctx, batchesToBeCommitted) if err != nil { return fmt.Errorf("failed to write retried batch: %w", err) } + + retries++ // account for the initial attempt + r.writtenBatches += int64(len(batchesToBeCommitted)) + r.writtenRels += int64(numLoaded) default: r.bar.Describe("restoring from backup") + r.writtenBatches += int64(len(batchesToBeCommitted)) } // it was a successful transaction commit without duplicates if resp != nil { - numLoaded = resp.NumLoaded - - var expected uint64 - for _, b := range batchesToBeCommitted { - expected += uint64(len(b)) - } - - if expected != numLoaded { - log.Warn().Uint64("loaded", numLoaded).Uint64("expected", expected).Msg("unexpected number of relationships loaded") + r.writtenRels += int64(resp.NumLoaded) + if expectedLoaded != resp.NumLoaded { + log.Warn().Uint64("loaded", resp.NumLoaded).Uint64("expected", expectedLoaded).Msg("unexpected number of relationships loaded") } } - r.relsWritten += int64(numLoaded) - if err := r.bar.Set64(r.relsWritten); err != nil { + if err := r.bar.Set64(r.writtenRels + r.skippedRels); err != nil { return fmt.Errorf("error incrementing progress bar: %w", err) } if !isatty.IsTerminal(os.Stderr.Fd()) { log.Trace(). - Int64("batches_written", r.batchesWritten). - Int64("relationships_written", r.relsWritten). + Int64("batches_written", r.writtenBatches). + Int64("relationships_written", r.writtenRels). + Int64("duplicate_batches", r.duplicateBatches). Int64("duplicate_relationships", r.duplicateRels). + Int64("skipped_batches", r.skippedBatches). + Int64("skipped_relationships", r.skippedRels). Uint64("retries", retries). Msg("restore progress") } @@ -287,13 +307,18 @@ func isAlreadyExistsError(err error) bool { } if s, ok := status.FromError(err); ok { - if s.Code() == codes.Unavailable { + if s.Code() == codes.AlreadyExists { + return true + } + } + + for _, code := range txConflictCodes { + if strings.Contains(err.Error(), code) { return true } } - // FIXME temporary hack until a proper error is exposed from the API, specific to CRDB - return strings.Contains(err.Error(), "SQLSTATE 23505") + return false } func isRetryableError(err error) bool { @@ -301,8 +326,16 @@ func isRetryableError(err error) bool { return false } - if strings.Contains(err.Error(), "RETRY_SERIALIZABLE") { // FIXME hack until SpiceDB exposes proper typed err - return true + if s, ok := status.FromError(err); ok { + if s.Code() == codes.Unavailable { + return true + } + } + + for _, code := range retryableErrorCodes { + if strings.Contains(err.Error(), code) { + return true + } } return false diff --git a/internal/cmd/restorer_test.go b/internal/cmd/restorer_test.go new file mode 100644 index 00000000..8ddb3066 --- /dev/null +++ b/internal/cmd/restorer_test.go @@ -0,0 +1,249 @@ +package cmd + +import ( + "context" + "os" + "testing" + + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/authzed/spicedb/pkg/tuple" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + + "github.com/authzed/zed/internal/client" +) + +var ( + unrecoverableError = status.Error(codes.Internal, "unrecoverable") + retryableError = status.Error(codes.Unavailable, "serialization") + conflictError = status.Error(codes.AlreadyExists, "conflict") + oneUnrecoverableError = []error{unrecoverableError} + oneRetryableError = []error{retryableError} + oneConflictError = []error{conflictError} +) + +func TestRestorer(t *testing.T) { + for _, tt := range []struct { + name string + prefixFilter string + batchSize int + batchesPerTransaction int64 + skipOnConflicts bool + touchOnConflicts bool + disableRetryErrors bool + sendErrors []error + commitErrors []error + touchErrors []error + relationships []string + }{ + {"honors batch size = 1", "", 1, 1, false, false, false, nil, nil, nil, testRelationships}, + {"correctly handles remainder batch", "", 2, 1, false, false, false, nil, nil, nil, testRelationships}, + {"correctly handles batch size == total rels", "", 3, 1, false, false, false, nil, nil, nil, testRelationships}, + {"correctly handles batch size > total rels", "", 4, 1, false, false, false, nil, nil, nil, testRelationships}, + {"correctly handles empty set", "", 1, 1, false, false, false, nil, nil, nil, nil}, + {"skips conflicting writes when skipOnConflict is enabled", "", 1, 1, true, false, false, nil, oneConflictError, nil, testRelationships}, + {"applies touch when touchOnConflict is enabled", "", 1, 1, false, true, false, nil, oneConflictError, nil, testRelationships}, + {"skips on conflict when skipOnConflict is enabled", "", 2, 1, true, false, false, nil, oneConflictError, nil, testRelationships}, + {"failed batches are written individually when touchOnConflict is enabled", "", 1, 2, false, true, false, nil, oneConflictError, nil, testRelationships}, + {"fails on conflict if touchOnConflict=false && skipOnConflict=false", "", 1, 1, false, false, false, oneConflictError, nil, nil, testRelationships}, + {"fails on unexpected commit error", "", 1, 1, false, false, false, nil, oneUnrecoverableError, nil, testRelationships}, + {"retries commit retryable errors", "", 1, 1, false, false, false, nil, oneRetryableError, nil, testRelationships}, + {"retries on conflict when fallback WriteRelationships fails", "", 1, 1, false, true, false, nil, oneConflictError, oneRetryableError, testRelationships}, + {"returns error on retryable error if retries are disabled", "", 1, 1, false, false, true, nil, oneRetryableError, nil, testRelationships}, + {"fails fast if conflict-triggered touch fails with an unrecoverable error", "", 1, 1, false, true, false, nil, oneConflictError, oneUnrecoverableError, testRelationships}, + {"retries if error happens right after sending a batch over the stream", "", 1, 1, false, true, false, oneConflictError, oneConflictError, nil, testRelationships}, + {"filters relationships", "test", 1, 1, false, false, false, nil, nil, nil, append([]string{"foo/resource:1#reader@foo/user:1"}, testRelationships...)}, + {"handles gracefully all rels as filtered", "invalid", 1, 1, false, false, false, nil, nil, nil, testRelationships}, + } { + tt := tt + t.Run(tt.name, func(t *testing.T) { + backupFileName := createTestBackup(t, testSchema, tt.relationships) + d, closer, err := decoderFromArgs(backupFileName) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, closer.Close()) + require.NoError(t, os.Remove(backupFileName)) + }) + + expectedFilteredRels := make([]string, 0, len(tt.relationships)) + for _, rel := range tt.relationships { + if !hasRelPrefix(tuple.ParseRel(rel), tt.prefixFilter) { + continue + } + + expectedFilteredRels = append(expectedFilteredRels, rel) + } + + expectedBatches := len(expectedFilteredRels) / tt.batchSize + // there is always one extra commit, regardless there is or not a remainder batch + expectedCommits := expectedBatches/int(tt.batchesPerTransaction) + 1 + remainderBatch := false + if len(expectedFilteredRels)%tt.batchSize != 0 { + expectedBatches++ + remainderBatch = true + } + + c := &mockClient{ + t: t, + remainderBatch: remainderBatch, + expectedRels: expectedFilteredRels, + expectedBatches: expectedBatches, + requestedBatchSize: tt.batchSize, + requestedBatchesPerTransaction: tt.batchesPerTransaction, + commitErrors: tt.commitErrors, + touchErrors: tt.touchErrors, + sendErrors: tt.sendErrors, + } + + expectedConflicts := 0 + expectedRetries := 0 + var expectsError error + for _, err := range tt.commitErrors { + if isRetryableError(err) { + expectedRetries++ + if tt.disableRetryErrors { + expectsError = err + } + } else if isAlreadyExistsError(err) { + expectedConflicts++ + } else { + expectsError = err + } + } + for _, err := range tt.touchErrors { + if isRetryableError(err) { + expectedRetries++ + if tt.disableRetryErrors { + expectsError = err + } + } else { + expectsError = err + } + } + + // if skip is enabled, there will be N less relationships written, where N is the number of conflicts + expectedWrittenRels := len(expectedFilteredRels) + if tt.skipOnConflicts { + expectedWrittenRels -= expectedConflicts * tt.batchSize + } + + expectedWrittenBatches := len(expectedFilteredRels) / tt.batchSize + if tt.skipOnConflicts { + expectedWrittenBatches -= expectedConflicts + } + if remainderBatch { + expectedWrittenBatches++ + } + + expectedTouchedBatches := expectedRetries + expectedTouchedRels := expectedRetries * tt.batchSize + if tt.touchOnConflicts { + expectedTouchedBatches += expectedConflicts * int(tt.batchesPerTransaction) + expectedTouchedRels += expectedConflicts * int(tt.batchesPerTransaction) * tt.batchSize + } + + expectedSkippedBatches := 0 + expectedSkippedRels := 0 + if tt.skipOnConflicts { + expectedSkippedBatches += expectedConflicts + expectedSkippedRels += expectedConflicts * tt.batchSize + } + + r := newRestorer(d, c, tt.prefixFilter, tt.batchSize, tt.batchesPerTransaction, tt.skipOnConflicts, tt.touchOnConflicts, tt.disableRetryErrors) + err = r.restoreFromDecoder(context.Background()) + if expectsError != nil || (expectedConflicts > 0 && !tt.skipOnConflicts && !tt.touchOnConflicts) { + require.ErrorIs(t, err, expectsError) + return + } + + require.NoError(t, err) + + // assert on mock stats + require.Equal(t, expectedBatches, c.receivedBatches, "unexpected number of received batches") + require.Equal(t, expectedCommits, c.receivedCommits, "unexpected number of batch commits") + require.Equal(t, len(expectedFilteredRels), c.receivedRels, "unexpected number of received relationships") + require.Equal(t, expectedTouchedBatches, c.touchedBatches, "unexpected number of touched batches") + require.Equal(t, expectedTouchedRels, c.touchedRels, "unexpected number of touched commits") + + // assert on restorer stats + require.Equal(t, expectedWrittenRels, int(r.writtenRels), "unexpected number of written relationships") + require.Equal(t, expectedWrittenBatches, int(r.writtenBatches), "unexpected number of written relationships") + require.Equal(t, expectedSkippedBatches, int(r.skippedBatches), "unexpected number of conflicting batches skipped") + require.Equal(t, expectedSkippedRels, int(r.skippedRels), "unexpected number of conflicting relationships skipped") + require.Equal(t, int64(expectedConflicts)*tt.batchesPerTransaction, r.duplicateBatches, "unexpected number of duplicate batches detected") + require.Equal(t, expectedConflicts*int(tt.batchesPerTransaction)*tt.batchSize, int(r.duplicateRels), "unexpected number of duplicate relationships detected") + require.Equal(t, int64(expectedRetries+expectedConflicts-expectedSkippedBatches), r.totalRetries, "unexpected number of retries") + require.Equal(t, len(tt.relationships)-len(expectedFilteredRels), int(r.filteredOutRels), "unexpected number of filtered out relationships") + }) + } +} + +type mockClient struct { + client.Client + v1.ExperimentalService_BulkImportRelationshipsClient + t *testing.T + remainderBatch bool + expectedRels []string + expectedBatches int + requestedBatchSize int + requestedBatchesPerTransaction int64 + receivedBatches int + receivedCommits int + receivedRels int + touchedBatches int + touchedRels int + lastReceivedBatch []*v1.Relationship + sendErrors []error + commitErrors []error + touchErrors []error +} + +func (m *mockClient) BulkImportRelationships(_ context.Context, _ ...grpc.CallOption) (v1.ExperimentalService_BulkImportRelationshipsClient, error) { + return m, nil +} + +func (m *mockClient) Send(req *v1.BulkImportRelationshipsRequest) error { + m.receivedBatches++ + m.receivedRels += len(req.Relationships) + m.lastReceivedBatch = req.Relationships + if m.receivedBatches <= len(m.sendErrors) { + return m.sendErrors[m.receivedBatches-1] + } + + if m.receivedBatches == m.expectedBatches && m.remainderBatch { + require.Equal(m.t, len(m.expectedRels)%m.requestedBatchSize, len(req.Relationships)) + } else { + require.Equal(m.t, m.requestedBatchSize, len(req.Relationships)) + } + + for i, rel := range req.Relationships { + require.True(m.t, proto.Equal(rel, tuple.ParseRel(m.expectedRels[((m.receivedBatches-1)*m.requestedBatchSize)+i]))) + } + + return nil +} + +func (m *mockClient) WriteRelationships(_ context.Context, in *v1.WriteRelationshipsRequest, _ ...grpc.CallOption) (*v1.WriteRelationshipsResponse, error) { + m.touchedBatches++ + m.touchedRels += len(in.Updates) + if m.touchedBatches <= len(m.touchErrors) { + return nil, m.touchErrors[m.touchedBatches-1] + } + + return &v1.WriteRelationshipsResponse{}, nil +} + +func (m *mockClient) CloseAndRecv() (*v1.BulkImportRelationshipsResponse, error) { + m.receivedCommits++ + lastBatch := m.lastReceivedBatch + defer func() { m.lastReceivedBatch = nil }() + + if m.receivedCommits <= len(m.commitErrors) { + return nil, m.commitErrors[m.receivedCommits-1] + } + + return &v1.BulkImportRelationshipsResponse{NumLoaded: uint64(len(lastBatch))}, nil +} From 91ac26d8303dd4f25e067283f57e786e669a46e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Tue, 19 Dec 2023 18:03:06 +0000 Subject: [PATCH 26/49] better handling of context cancellation --- internal/cmd/restorer.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 1f776c34..990b7fc6 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "errors" "fmt" "os" "strings" @@ -188,6 +189,9 @@ func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.Experim unknown := !retryable && !conflict && err != nil switch { + case errors.Is(ctx.Err(), context.Canceled): + r.bar.Describe("backup restore aborted") + return ctx.Err() case unknown: r.bar.Describe("failed with unrecoverable error") return fmt.Errorf("error finalizing write of %d batches: %w", len(batchesToBeCommitted), err) From e7129b317e89adaa30955d83e9bcc5409cec4382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Tue, 19 Dec 2023 19:50:39 +0000 Subject: [PATCH 27/49] restore: update fallback error codes to include MySQL and Postgres --- internal/cmd/restorer.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 990b7fc6..718abc36 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -21,10 +21,17 @@ import ( "github.com/authzed/zed/pkg/backupformat" ) -// Fallback for CRDB datastore on SpiceDB < 1.29.0 not returning proper gRPC codes +// Fallback for datastore implementations on SpiceDB < 1.29.0 not returning proper gRPC codes +// Remove once https://github.com/authzed/spicedb/pull/1688 lands var ( - txConflictCodes = []string{"SQLSTATE 23505"} - retryableErrorCodes = []string{"retryable error"} + txConflictCodes = []string{ + "SQLSTATE 23505", // CockroachDB + "Error 1062 (23000)", // MySQL + } + retryableErrorCodes = []string{ + "retryable error", // CockroachDB, PostgreSQL + "try restarting transaction", "Error 1205", // MySQL + } ) type restorer struct { From 065515f86f0ead28abb91c72950eaa55e6e9e551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Tue, 19 Dec 2023 19:52:27 +0000 Subject: [PATCH 28/49] restore: add a deadline on fallback WriteRelationships since MySQL sometimes can get locked for a long time on serialization errors --- internal/cmd/backup.go | 5 ++++- internal/cmd/restorer.go | 17 +++++++++++++---- internal/cmd/restorer_test.go | 3 ++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index add94092..30115d5d 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -92,6 +92,7 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupRestoreCmd.Flags().Bool("disable-retries", false, "retries when an errors is determined to be retryable (e.g. serialization errors)") backupRestoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") backupRestoreCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") + backupRestoreCmd.Flags().Duration("request-timeout", 30*time.Second, "timeout for each request performed during restore") // Restore used to be on the root, so add it there too, but hidden. rootCmd.AddCommand(&cobra.Command{ @@ -401,8 +402,10 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { if touchConflicts && skipConflicts { return errors.New("cannot use --skip-conflicts and --touch-conflicts together") } + requestTimeout := cobrautil.MustGetDuration(cmd, "request-timeout") - return newRestorer(decoder, c, prefixFilter, batchSize, batchesPerTransaction, skipConflicts, touchConflicts, disableRetries).restoreFromDecoder(ctx) + return newRestorer(decoder, c, prefixFilter, batchSize, batchesPerTransaction, skipConflicts, touchConflicts, + disableRetries, requestTimeout).restoreFromDecoder(ctx) } func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 718abc36..60251d5e 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -54,15 +54,17 @@ type restorer struct { duplicateRels int64 duplicateBatches int64 totalRetries int64 + requestTimeout time.Duration } func newRestorer(decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, batchesPerTransaction int64, skipOnConflicts bool, touchOnConflicts bool, disableRetryErrors bool, -) *restorer { + requestTimeout time.Duration) *restorer { return &restorer{ decoder: decoder, client: client, prefixFilter: prefixFilter, + requestTimeout: requestTimeout, batchSize: batchSize, batchesPerTransaction: batchesPerTransaction, skipOnConflicts: skipOnConflicts, @@ -290,16 +292,19 @@ func (r *restorer) writeBatchesWithRetry(ctx context.Context, batches [][]*v1.Re for { // throttle the writes so we don't overwhelm the server time.Sleep(backoffInterval.NextBackOff()) - _, err := r.client.WriteRelationships(ctx, &v1.WriteRelationshipsRequest{Updates: updates}) + cancelCtx, cancel := context.WithTimeout(ctx, r.requestTimeout) + _, err := r.client.WriteRelationships(cancelCtx, &v1.WriteRelationshipsRequest{Updates: updates}) + cancel() if isRetryableError(err) && currentRetries < 10 { currentRetries++ r.totalRetries++ totalRetries++ + r.bar.Describe(fmt.Sprintf("retrying after error (attempt %d)", currentRetries+1)) continue } if err != nil { - return 0, 0, fmt.Errorf("error on attempting to WriteRelationships a previously failed batch: %w", err) + return 0, 0, err } currentRetries = 0 @@ -338,7 +343,7 @@ func isRetryableError(err error) bool { } if s, ok := status.FromError(err); ok { - if s.Code() == codes.Unavailable { + if s.Code() == codes.Unavailable || s.Code() == codes.DeadlineExceeded { return true } } @@ -349,6 +354,10 @@ func isRetryableError(err error) bool { } } + if errors.Is(err, context.DeadlineExceeded) { + return true + } + return false } diff --git a/internal/cmd/restorer_test.go b/internal/cmd/restorer_test.go index 8ddb3066..537b1937 100644 --- a/internal/cmd/restorer_test.go +++ b/internal/cmd/restorer_test.go @@ -4,6 +4,7 @@ import ( "context" "os" "testing" + "time" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/pkg/tuple" @@ -152,7 +153,7 @@ func TestRestorer(t *testing.T) { expectedSkippedRels += expectedConflicts * tt.batchSize } - r := newRestorer(d, c, tt.prefixFilter, tt.batchSize, tt.batchesPerTransaction, tt.skipOnConflicts, tt.touchOnConflicts, tt.disableRetryErrors) + r := newRestorer(d, c, tt.prefixFilter, tt.batchSize, tt.batchesPerTransaction, tt.skipOnConflicts, tt.touchOnConflicts, tt.disableRetryErrors, 0*time.Second) err = r.restoreFromDecoder(context.Background()) if expectsError != nil || (expectedConflicts > 0 && !tt.skipOnConflicts && !tt.touchOnConflicts) { require.ErrorIs(t, err, expectsError) From 2ef5ab5d618dbbfb9cdc3c9ab7f54d4e2dab72b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Wed, 20 Dec 2023 09:01:10 +0000 Subject: [PATCH 29/49] restore: better cancelation handling UX --- internal/cmd/restorer.go | 76 +++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 60251d5e..3e79aa99 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -59,7 +59,8 @@ type restorer struct { func newRestorer(decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, batchesPerTransaction int64, skipOnConflicts bool, touchOnConflicts bool, disableRetryErrors bool, - requestTimeout time.Duration) *restorer { + requestTimeout time.Duration, +) *restorer { return &restorer{ decoder: decoder, client: client, @@ -195,12 +196,13 @@ func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.Experim // This lets us retry with TOUCH semantics in case of failure due to duplicates retryable := isRetryableError(err) conflict := isAlreadyExistsError(err) - unknown := !retryable && !conflict && err != nil + canceled, cancelErr := isCanceledError(ctx.Err(), err) + unknown := !retryable && !conflict && !canceled && err != nil switch { - case errors.Is(ctx.Err(), context.Canceled): + case canceled: r.bar.Describe("backup restore aborted") - return ctx.Err() + return cancelErr case unknown: r.bar.Describe("failed with unrecoverable error") return fmt.Errorf("error finalizing write of %d batches: %w", len(batchesToBeCommitted), err) @@ -322,40 +324,72 @@ func isAlreadyExistsError(err error) bool { return false } - if s, ok := status.FromError(err); ok { - if s.Code() == codes.AlreadyExists { - return true - } + if isGRPCCode(err, codes.AlreadyExists) { + return true } - for _, code := range txConflictCodes { - if strings.Contains(err.Error(), code) { - return true + return isContainsErrorString(err, txConflictCodes...) +} + +func isRetryableError(err error) bool { + if err == nil { + return false + } + + if isGRPCCode(err, codes.Unavailable, codes.DeadlineExceeded) { + return true + } + + if isContainsErrorString(err, retryableErrorCodes...) { + return true + } + + return errors.Is(err, context.DeadlineExceeded) +} + +func isCanceledError(errs ...error) (bool, error) { + for _, err := range errs { + if err == nil { + continue + } + + if errors.Is(err, context.Canceled) { + return true, err + } + + if isGRPCCode(err, codes.Canceled) { + return true, err } } - return false + return false, nil } -func isRetryableError(err error) bool { +func isContainsErrorString(err error, errStrings ...string) bool { if err == nil { return false } - if s, ok := status.FromError(err); ok { - if s.Code() == codes.Unavailable || s.Code() == codes.DeadlineExceeded { + for _, errString := range errStrings { + if strings.Contains(err.Error(), errString) { return true } } - for _, code := range retryableErrorCodes { - if strings.Contains(err.Error(), code) { - return true - } + return false +} + +func isGRPCCode(err error, codes ...codes.Code) bool { + if err == nil { + return false } - if errors.Is(err, context.DeadlineExceeded) { - return true + if s, ok := status.FromError(err); ok { + for _, code := range codes { + if s.Code() == code { + return true + } + } } return false From b50830aa418aa33b19f43070c44960548f403a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Wed, 20 Dec 2023 09:02:42 +0000 Subject: [PATCH 30/49] restore: also handle schema writing so the restorer becomes fully self-contained and facilitate exporting it --- internal/cmd/backup.go | 12 ++---------- internal/cmd/restorer.go | 14 ++++++++++++-- internal/cmd/restorer_test.go | 9 ++++++++- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 30115d5d..df912899 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -386,16 +386,8 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { return fmt.Errorf("unable to initialize client: %w", err) } - ctx := cmd.Context() - if _, err := c.WriteSchema(ctx, &v1.WriteSchemaRequest{ - Schema: schema, - }); err != nil { - return fmt.Errorf("unable to write schema: %w", err) - } - batchSize := cobrautil.MustGetInt(cmd, "batch-size") batchesPerTransaction := cobrautil.MustGetInt64(cmd, "batches-per-transaction") - skipConflicts := cobrautil.MustGetBool(cmd, "skip-conflicts") touchConflicts := cobrautil.MustGetBool(cmd, "touch-conflicts") disableRetries := cobrautil.MustGetBool(cmd, "disable-retries") @@ -404,8 +396,8 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { } requestTimeout := cobrautil.MustGetDuration(cmd, "request-timeout") - return newRestorer(decoder, c, prefixFilter, batchSize, batchesPerTransaction, skipConflicts, touchConflicts, - disableRetries, requestTimeout).restoreFromDecoder(ctx) + return newRestorer(schema, decoder, c, prefixFilter, batchSize, batchesPerTransaction, skipConflicts, touchConflicts, + disableRetries, requestTimeout).restoreFromDecoder(cmd.Context()) } func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 3e79aa99..4fc20f1d 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -35,6 +35,7 @@ var ( ) type restorer struct { + schema string decoder *backupformat.Decoder client client.Client prefixFilter string @@ -57,12 +58,13 @@ type restorer struct { requestTimeout time.Duration } -func newRestorer(decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, +func newRestorer(schema string, decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, batchesPerTransaction int64, skipOnConflicts bool, touchOnConflicts bool, disableRetryErrors bool, requestTimeout time.Duration, ) *restorer { return &restorer{ decoder: decoder, + schema: schema, client: client, prefixFilter: prefixFilter, requestTimeout: requestTimeout, @@ -83,11 +85,19 @@ func (r *restorer) restoreFromDecoder(ctx context.Context) error { } }() + r.bar.Describe("restoring schema from backup") + if _, err := r.client.WriteSchema(ctx, &v1.WriteSchemaRequest{ + Schema: r.schema, + }); err != nil { + return fmt.Errorf("unable to write schema: %w", err) + } + relationshipWriter, err := r.client.BulkImportRelationships(ctx) if err != nil { return fmt.Errorf("error creating writer stream: %w", err) } + r.bar.Describe("restoring relationships from backup") batch := make([]*v1.Relationship, 0, r.batchSize) batchesToBeCommitted := make([][]*v1.Relationship, 0, r.batchesPerTransaction) for rel, err := r.decoder.Next(); rel != nil && err == nil; rel, err = r.decoder.Next() { @@ -242,7 +252,7 @@ func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.Experim r.writtenBatches += int64(len(batchesToBeCommitted)) r.writtenRels += int64(numLoaded) default: - r.bar.Describe("restoring from backup") + r.bar.Describe("restoring relationships from backup") r.writtenBatches += int64(len(batchesToBeCommitted)) } diff --git a/internal/cmd/restorer_test.go b/internal/cmd/restorer_test.go index 537b1937..335516bd 100644 --- a/internal/cmd/restorer_test.go +++ b/internal/cmd/restorer_test.go @@ -89,6 +89,7 @@ func TestRestorer(t *testing.T) { c := &mockClient{ t: t, + schema: testSchema, remainderBatch: remainderBatch, expectedRels: expectedFilteredRels, expectedBatches: expectedBatches, @@ -153,7 +154,7 @@ func TestRestorer(t *testing.T) { expectedSkippedRels += expectedConflicts * tt.batchSize } - r := newRestorer(d, c, tt.prefixFilter, tt.batchSize, tt.batchesPerTransaction, tt.skipOnConflicts, tt.touchOnConflicts, tt.disableRetryErrors, 0*time.Second) + r := newRestorer(testSchema, d, c, tt.prefixFilter, tt.batchSize, tt.batchesPerTransaction, tt.skipOnConflicts, tt.touchOnConflicts, tt.disableRetryErrors, 0*time.Second) err = r.restoreFromDecoder(context.Background()) if expectsError != nil || (expectedConflicts > 0 && !tt.skipOnConflicts && !tt.touchOnConflicts) { require.ErrorIs(t, err, expectsError) @@ -186,6 +187,7 @@ type mockClient struct { client.Client v1.ExperimentalService_BulkImportRelationshipsClient t *testing.T + schema string remainderBatch bool expectedRels []string expectedBatches int @@ -248,3 +250,8 @@ func (m *mockClient) CloseAndRecv() (*v1.BulkImportRelationshipsResponse, error) return &v1.BulkImportRelationshipsResponse{NumLoaded: uint64(len(lastBatch))}, nil } + +func (m *mockClient) WriteSchema(_ context.Context, wsr *v1.WriteSchemaRequest, _ ...grpc.CallOption) (*v1.WriteSchemaResponse, error) { + require.Equal(m.t, m.schema, wsr.Schema, "unexpected schema in write schema request") + return &v1.WriteSchemaResponse{}, nil +} From fe5e962a89d0a79439e46ef68760b88d35bdb5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Wed, 20 Dec 2023 09:15:17 +0000 Subject: [PATCH 31/49] PR feedback: better type for batchesPerTransaction --- internal/cmd/backup.go | 4 ++-- internal/cmd/backup_test.go | 9 ++++++++- internal/cmd/helpers_test.go | 10 ++++++---- internal/cmd/restorer.go | 6 +++--- internal/cmd/restorer_test.go | 6 +++--- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index df912899..0377cd6e 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -86,7 +86,7 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupCmd.AddCommand(backupRestoreCmd) backupRestoreCmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") - backupRestoreCmd.Flags().Int64("batches-per-transaction", 10, "number of batches per transaction") + backupRestoreCmd.Flags().Uint("batches-per-transaction", 10, "number of batches per transaction") backupRestoreCmd.Flags().Bool("skip-conflicts", false, "skips any batch found to be conflicting") backupRestoreCmd.Flags().Bool("touch-conflicts", false, "retries writing conflicting batches with TOUCH semantics") backupRestoreCmd.Flags().Bool("disable-retries", false, "retries when an errors is determined to be retryable (e.g. serialization errors)") @@ -387,7 +387,7 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { } batchSize := cobrautil.MustGetInt(cmd, "batch-size") - batchesPerTransaction := cobrautil.MustGetInt64(cmd, "batches-per-transaction") + batchesPerTransaction := cobrautil.MustGetUint(cmd, "batches-per-transaction") skipConflicts := cobrautil.MustGetBool(cmd, "skip-conflicts") touchConflicts := cobrautil.MustGetBool(cmd, "touch-conflicts") disableRetries := cobrautil.MustGetBool(cmd, "disable-retries") diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index 22324dca..5a58c2cd 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" "testing" + "time" "github.com/authzed/zed/internal/client" @@ -323,6 +324,11 @@ func TestBackupCreateCmdFunc(t *testing.T) { require.Equal(t, resp.WrittenAt.Token, d.ZedToken().Token) } +type durationFlag struct { + flagName string + flagValue time.Duration +} + func TestBackupRestoreCmdFunc(t *testing.T) { cmd := createTestCobraCommandWithFlagValue(t, stringFlag{"prefix-filter", "test"}, @@ -331,7 +337,8 @@ func TestBackupRestoreCmdFunc(t *testing.T) { boolFlag{"touch-conflicts", false}, boolFlag{"disable-retries", false}, intFlag{"batch-size", 100}, - int64Flag{"batches-per-transaction", 10}, + uintFlag{"batches-per-transaction", 10}, + durationFlag{"request-timeout", 0}, ) backupName := createTestBackup(t, testSchema, testRelationships) diff --git a/internal/cmd/helpers_test.go b/internal/cmd/helpers_test.go index acc18d50..ea82a3a0 100644 --- a/internal/cmd/helpers_test.go +++ b/internal/cmd/helpers_test.go @@ -64,9 +64,9 @@ type intFlag struct { flagValue int } -type int64Flag struct { +type uintFlag struct { flagName string - flagValue int64 + flagValue uint } func createTestCobraCommandWithFlagValue(t *testing.T, flagAndValues ...any) *cobra.Command { @@ -81,8 +81,10 @@ func createTestCobraCommandWithFlagValue(t *testing.T, flagAndValues ...any) *co c.Flags().Bool(f.flagName, f.flagValue, "") case intFlag: c.Flags().Int(f.flagName, f.flagValue, "") - case int64Flag: - c.Flags().Int64(f.flagName, f.flagValue, "") + case uintFlag: + c.Flags().Uint(f.flagName, f.flagValue, "") + case durationFlag: + c.Flags().Duration(f.flagName, f.flagValue, "") default: t.Fatalf("unknown flag type: %T", f) } diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 4fc20f1d..938e985c 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -40,7 +40,7 @@ type restorer struct { client client.Client prefixFilter string batchSize int - batchesPerTransaction int64 + batchesPerTransaction uint skipOnConflicts bool touchOnConflicts bool disableRetryErrors bool @@ -59,7 +59,7 @@ type restorer struct { } func newRestorer(schema string, decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, - batchesPerTransaction int64, skipOnConflicts bool, touchOnConflicts bool, disableRetryErrors bool, + batchesPerTransaction uint, skipOnConflicts bool, touchOnConflicts bool, disableRetryErrors bool, requestTimeout time.Duration, ) *restorer { return &restorer{ @@ -141,7 +141,7 @@ func (r *restorer) restoreFromDecoder(ctx context.Context) error { batch = make([]*v1.Relationship, 0, r.batchSize) // if we've sent the maximum number of batches per transaction, proceed to commit - if int64(len(batchesToBeCommitted))%r.batchesPerTransaction != 0 { + if uint(len(batchesToBeCommitted))%r.batchesPerTransaction != 0 { continue } diff --git a/internal/cmd/restorer_test.go b/internal/cmd/restorer_test.go index 335516bd..e8addbf0 100644 --- a/internal/cmd/restorer_test.go +++ b/internal/cmd/restorer_test.go @@ -31,7 +31,7 @@ func TestRestorer(t *testing.T) { name string prefixFilter string batchSize int - batchesPerTransaction int64 + batchesPerTransaction uint skipOnConflicts bool touchOnConflicts bool disableRetryErrors bool @@ -175,7 +175,7 @@ func TestRestorer(t *testing.T) { require.Equal(t, expectedWrittenBatches, int(r.writtenBatches), "unexpected number of written relationships") require.Equal(t, expectedSkippedBatches, int(r.skippedBatches), "unexpected number of conflicting batches skipped") require.Equal(t, expectedSkippedRels, int(r.skippedRels), "unexpected number of conflicting relationships skipped") - require.Equal(t, int64(expectedConflicts)*tt.batchesPerTransaction, r.duplicateBatches, "unexpected number of duplicate batches detected") + require.Equal(t, uint(expectedConflicts)*tt.batchesPerTransaction, uint(r.duplicateBatches), "unexpected number of duplicate batches detected") require.Equal(t, expectedConflicts*int(tt.batchesPerTransaction)*tt.batchSize, int(r.duplicateRels), "unexpected number of duplicate relationships detected") require.Equal(t, int64(expectedRetries+expectedConflicts-expectedSkippedBatches), r.totalRetries, "unexpected number of retries") require.Equal(t, len(tt.relationships)-len(expectedFilteredRels), int(r.filteredOutRels), "unexpected number of filtered out relationships") @@ -192,7 +192,7 @@ type mockClient struct { expectedRels []string expectedBatches int requestedBatchSize int - requestedBatchesPerTransaction int64 + requestedBatchesPerTransaction uint receivedBatches int receivedCommits int receivedRels int From e8f8bdef5444c907dd82843ae030b47d98cd37e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Wed, 20 Dec 2023 09:37:22 +0000 Subject: [PATCH 32/49] fix panic on deprecated zed restore command the flags were not registered in the deprecated `zed restore` command when it was added for back-compat after the command became `zed backup restore` --- internal/cmd/backup.go | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 0377cd6e..2398c2e9 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -79,29 +79,24 @@ var ( func registerBackupCmd(rootCmd *cobra.Command) { rootCmd.AddCommand(backupCmd) + registerBackupCreateFlags(backupCmd) backupCmd.AddCommand(backupCreateCmd) - backupCreateCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") - backupCreateCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") + registerBackupCreateFlags(backupCreateCmd) backupCmd.AddCommand(backupRestoreCmd) - backupRestoreCmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") - backupRestoreCmd.Flags().Uint("batches-per-transaction", 10, "number of batches per transaction") - backupRestoreCmd.Flags().Bool("skip-conflicts", false, "skips any batch found to be conflicting") - backupRestoreCmd.Flags().Bool("touch-conflicts", false, "retries writing conflicting batches with TOUCH semantics") - backupRestoreCmd.Flags().Bool("disable-retries", false, "retries when an errors is determined to be retryable (e.g. serialization errors)") - backupRestoreCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") - backupRestoreCmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") - backupRestoreCmd.Flags().Duration("request-timeout", 30*time.Second, "timeout for each request performed during restore") + registerBackupRestoreFlags(backupRestoreCmd) // Restore used to be on the root, so add it there too, but hidden. - rootCmd.AddCommand(&cobra.Command{ + restoreCmd := &cobra.Command{ Use: "restore ", Short: "Restore a permission system from a file", Args: cobra.MaximumNArgs(1), RunE: backupRestoreCmdFunc, Hidden: true, - }) + } + rootCmd.AddCommand(restoreCmd) + registerBackupRestoreFlags(restoreCmd) backupCmd.AddCommand(backupParseSchemaCmd) backupParseSchemaCmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") @@ -112,6 +107,22 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupParseRelsCmd.Flags().String("prefix-filter", "", "Include only relationships with a given prefix") } +func registerBackupRestoreFlags(cmd *cobra.Command) { + cmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") + cmd.Flags().Uint("batches-per-transaction", 10, "number of batches per transaction") + cmd.Flags().Bool("skip-conflicts", false, "skips any batch found to be conflicting") + cmd.Flags().Bool("touch-conflicts", false, "retries writing conflicting batches with TOUCH semantics") + cmd.Flags().Bool("disable-retries", false, "retries when an errors is determined to be retryable (e.g. serialization errors)") + cmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") + cmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") + cmd.Flags().Duration("request-timeout", 30*time.Second, "timeout for each request performed during restore") +} + +func registerBackupCreateFlags(cmd *cobra.Command) { + cmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") + cmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") +} + func createBackupFile(filename string) (*os.File, error) { if filename == "-" { log.Trace().Str("filename", "- (stdout)").Send() From e31deab66ee5f7b0b0b98800a8bf1f910b3915f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Wed, 20 Dec 2023 10:19:12 +0000 Subject: [PATCH 33/49] restore: refactor conflict handling flags turned into a string that can be parsed into an enum --- go.mod | 2 +- internal/cmd/backup.go | 29 ++++++++++++++------ internal/cmd/backup_test.go | 3 +-- internal/cmd/restorer.go | 30 ++++++++++++++------- internal/cmd/restorer_test.go | 51 +++++++++++++++++------------------ 5 files changed, 69 insertions(+), 46 deletions(-) diff --git a/go.mod b/go.mod index 3ab09c24..743b6de5 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 github.com/xlab/treeprint v1.2.0 + golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb golang.org/x/mod v0.14.0 golang.org/x/sync v0.5.0 golang.org/x/term v0.15.0 @@ -189,7 +190,6 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.17.0 // indirect - golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sys v0.15.0 // indirect diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 2398c2e9..d0046af0 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -20,6 +20,8 @@ import ( "github.com/rs/zerolog/log" "github.com/schollz/progressbar/v3" "github.com/spf13/cobra" + "golang.org/x/exp/constraints" + "golang.org/x/exp/maps" "github.com/authzed/zed/internal/client" "github.com/authzed/zed/internal/commands" @@ -110,8 +112,7 @@ func registerBackupCmd(rootCmd *cobra.Command) { func registerBackupRestoreFlags(cmd *cobra.Command) { cmd.Flags().Int("batch-size", 1_000, "restore relationship write batch size") cmd.Flags().Uint("batches-per-transaction", 10, "number of batches per transaction") - cmd.Flags().Bool("skip-conflicts", false, "skips any batch found to be conflicting") - cmd.Flags().Bool("touch-conflicts", false, "retries writing conflicting batches with TOUCH semantics") + cmd.Flags().String("conflict-strategy", "fail", "strategy used when a conflicting relationship is found. Possible values: fail, skip, touch") cmd.Flags().Bool("disable-retries", false, "retries when an errors is determined to be retryable (e.g. serialization errors)") cmd.Flags().String("prefix-filter", "", "include only schema and relationships with a given prefix") cmd.Flags().Bool("rewrite-legacy", false, "potentially modify the schema to exclude legacy/broken syntax") @@ -399,18 +400,30 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { batchSize := cobrautil.MustGetInt(cmd, "batch-size") batchesPerTransaction := cobrautil.MustGetUint(cmd, "batches-per-transaction") - skipConflicts := cobrautil.MustGetBool(cmd, "skip-conflicts") - touchConflicts := cobrautil.MustGetBool(cmd, "touch-conflicts") + + strategy := MustGetEnum[ConflictStrategy](cmd, "conflict-strategy", conflictStrategyMapping) disableRetries := cobrautil.MustGetBool(cmd, "disable-retries") - if touchConflicts && skipConflicts { - return errors.New("cannot use --skip-conflicts and --touch-conflicts together") - } requestTimeout := cobrautil.MustGetDuration(cmd, "request-timeout") - return newRestorer(schema, decoder, c, prefixFilter, batchSize, batchesPerTransaction, skipConflicts, touchConflicts, + return newRestorer(schema, decoder, c, prefixFilter, batchSize, batchesPerTransaction, strategy, disableRetries, requestTimeout).restoreFromDecoder(cmd.Context()) } +// MustGetEnum is a helper for getting an enum value from a string cobra flag. +func MustGetEnum[E constraints.Integer](cmd *cobra.Command, name string, mapping map[string]E) E { + value, err := cmd.Flags().GetString(name) + if err != nil { + panic("failed to find cobra flag: " + name) + } + + value = strings.TrimSpace(strings.ToLower(value)) + if enum, ok := mapping[value]; ok { + return enum + } + + panic(fmt.Sprintf("unexpected flag value %s: should be one of %v", value, maps.Keys(mapping))) +} + func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { decoder, closer, err := decoderFromArgs(args...) if err != nil { diff --git a/internal/cmd/backup_test.go b/internal/cmd/backup_test.go index 5a58c2cd..5168aa55 100644 --- a/internal/cmd/backup_test.go +++ b/internal/cmd/backup_test.go @@ -333,8 +333,7 @@ func TestBackupRestoreCmdFunc(t *testing.T) { cmd := createTestCobraCommandWithFlagValue(t, stringFlag{"prefix-filter", "test"}, boolFlag{"rewrite-legacy", false}, - boolFlag{"skip-conflicts", false}, - boolFlag{"touch-conflicts", false}, + stringFlag{"conflict-strategy", "fail"}, boolFlag{"disable-retries", false}, intFlag{"batch-size", 100}, uintFlag{"batches-per-transaction", 10}, diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 938e985c..0a173f52 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -21,6 +21,20 @@ import ( "github.com/authzed/zed/pkg/backupformat" ) +type ConflictStrategy int + +const ( + Fail ConflictStrategy = iota + Skip + Touch +) + +var conflictStrategyMapping = map[string]ConflictStrategy{ + "fail": Fail, + "skip": Skip, + "touch": Touch, +} + // Fallback for datastore implementations on SpiceDB < 1.29.0 not returning proper gRPC codes // Remove once https://github.com/authzed/spicedb/pull/1688 lands var ( @@ -41,8 +55,7 @@ type restorer struct { prefixFilter string batchSize int batchesPerTransaction uint - skipOnConflicts bool - touchOnConflicts bool + conflictStrategy ConflictStrategy disableRetryErrors bool bar *progressbar.ProgressBar @@ -59,7 +72,7 @@ type restorer struct { } func newRestorer(schema string, decoder *backupformat.Decoder, client client.Client, prefixFilter string, batchSize int, - batchesPerTransaction uint, skipOnConflicts bool, touchOnConflicts bool, disableRetryErrors bool, + batchesPerTransaction uint, conflictStrategy ConflictStrategy, disableRetryErrors bool, requestTimeout time.Duration, ) *restorer { return &restorer{ @@ -70,8 +83,7 @@ func newRestorer(schema string, decoder *backupformat.Decoder, client client.Cli requestTimeout: requestTimeout, batchSize: batchSize, batchesPerTransaction: batchesPerTransaction, - skipOnConflicts: skipOnConflicts, - touchOnConflicts: touchOnConflicts, + conflictStrategy: conflictStrategy, disableRetryErrors: disableRetryErrors, bar: relProgressBar("restoring from backup"), } @@ -218,14 +230,14 @@ func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.Experim return fmt.Errorf("error finalizing write of %d batches: %w", len(batchesToBeCommitted), err) case retryable && r.disableRetryErrors: return err - case conflict && r.skipOnConflicts: + case conflict && r.conflictStrategy == Skip: r.skippedRels += int64(expectedLoaded) r.skippedBatches += int64(len(batchesToBeCommitted)) r.duplicateBatches += int64(len(batchesToBeCommitted)) r.duplicateRels += int64(expectedLoaded) r.bar.Describe("skipping conflicting batch") - case conflict && r.touchOnConflicts: - r.bar.Describe("retrying conflicting batch") + case conflict && r.conflictStrategy == Touch: + r.bar.Describe("touching conflicting batch") r.duplicateRels += int64(expectedLoaded) r.duplicateBatches += int64(len(batchesToBeCommitted)) r.totalRetries++ @@ -237,7 +249,7 @@ func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.Experim retries++ // account for the initial attempt r.writtenBatches += int64(len(batchesToBeCommitted)) r.writtenRels += int64(numLoaded) - case conflict && (!r.touchOnConflicts && !r.skipOnConflicts): + case conflict && r.conflictStrategy == Fail: r.bar.Describe("conflict detected, aborting restore") return fmt.Errorf("duplicate relationships found") case retryable: diff --git a/internal/cmd/restorer_test.go b/internal/cmd/restorer_test.go index e8addbf0..4445ef4a 100644 --- a/internal/cmd/restorer_test.go +++ b/internal/cmd/restorer_test.go @@ -32,32 +32,31 @@ func TestRestorer(t *testing.T) { prefixFilter string batchSize int batchesPerTransaction uint - skipOnConflicts bool - touchOnConflicts bool + conflictStrategy ConflictStrategy disableRetryErrors bool sendErrors []error commitErrors []error touchErrors []error relationships []string }{ - {"honors batch size = 1", "", 1, 1, false, false, false, nil, nil, nil, testRelationships}, - {"correctly handles remainder batch", "", 2, 1, false, false, false, nil, nil, nil, testRelationships}, - {"correctly handles batch size == total rels", "", 3, 1, false, false, false, nil, nil, nil, testRelationships}, - {"correctly handles batch size > total rels", "", 4, 1, false, false, false, nil, nil, nil, testRelationships}, - {"correctly handles empty set", "", 1, 1, false, false, false, nil, nil, nil, nil}, - {"skips conflicting writes when skipOnConflict is enabled", "", 1, 1, true, false, false, nil, oneConflictError, nil, testRelationships}, - {"applies touch when touchOnConflict is enabled", "", 1, 1, false, true, false, nil, oneConflictError, nil, testRelationships}, - {"skips on conflict when skipOnConflict is enabled", "", 2, 1, true, false, false, nil, oneConflictError, nil, testRelationships}, - {"failed batches are written individually when touchOnConflict is enabled", "", 1, 2, false, true, false, nil, oneConflictError, nil, testRelationships}, - {"fails on conflict if touchOnConflict=false && skipOnConflict=false", "", 1, 1, false, false, false, oneConflictError, nil, nil, testRelationships}, - {"fails on unexpected commit error", "", 1, 1, false, false, false, nil, oneUnrecoverableError, nil, testRelationships}, - {"retries commit retryable errors", "", 1, 1, false, false, false, nil, oneRetryableError, nil, testRelationships}, - {"retries on conflict when fallback WriteRelationships fails", "", 1, 1, false, true, false, nil, oneConflictError, oneRetryableError, testRelationships}, - {"returns error on retryable error if retries are disabled", "", 1, 1, false, false, true, nil, oneRetryableError, nil, testRelationships}, - {"fails fast if conflict-triggered touch fails with an unrecoverable error", "", 1, 1, false, true, false, nil, oneConflictError, oneUnrecoverableError, testRelationships}, - {"retries if error happens right after sending a batch over the stream", "", 1, 1, false, true, false, oneConflictError, oneConflictError, nil, testRelationships}, - {"filters relationships", "test", 1, 1, false, false, false, nil, nil, nil, append([]string{"foo/resource:1#reader@foo/user:1"}, testRelationships...)}, - {"handles gracefully all rels as filtered", "invalid", 1, 1, false, false, false, nil, nil, nil, testRelationships}, + {"honors batch size = 1", "", 1, 1, Fail, false, nil, nil, nil, testRelationships}, + {"correctly handles remainder batch", "", 2, 1, Fail, false, nil, nil, nil, testRelationships}, + {"correctly handles batch size == total rels", "", 3, 1, Fail, false, nil, nil, nil, testRelationships}, + {"correctly handles batch size > total rels", "", 4, 1, Fail, false, nil, nil, nil, testRelationships}, + {"correctly handles empty set", "", 1, 1, Fail, false, nil, nil, nil, nil}, + {"skips conflicting writes when skipOnConflict is enabled", "", 1, 1, Skip, false, nil, oneConflictError, nil, testRelationships}, + {"applies touch when touchOnConflict is enabled", "", 1, 1, Touch, false, nil, oneConflictError, nil, testRelationships}, + {"skips on conflict when skipOnConflict is enabled", "", 2, 1, Skip, false, nil, oneConflictError, nil, testRelationships}, + {"failed batches are written individually when touchOnConflict is enabled", "", 1, 2, Touch, false, nil, oneConflictError, nil, testRelationships}, + {"fails on conflict if touchOnConflict=false && skipOnConflict=false", "", 1, 1, Fail, false, oneConflictError, nil, nil, testRelationships}, + {"fails on unexpected commit error", "", 1, 1, Fail, false, nil, oneUnrecoverableError, nil, testRelationships}, + {"retries commit retryable errors", "", 1, 1, Fail, false, nil, oneRetryableError, nil, testRelationships}, + {"retries on conflict when fallback WriteRelationships fails", "", 1, 1, Touch, false, nil, oneConflictError, oneRetryableError, testRelationships}, + {"returns error on retryable error if retries are disabled", "", 1, 1, Fail, true, nil, oneRetryableError, nil, testRelationships}, + {"fails fast if conflict-triggered touch fails with an unrecoverable error", "", 1, 1, Touch, false, nil, oneConflictError, oneUnrecoverableError, testRelationships}, + {"retries if error happens right after sending a batch over the stream", "", 1, 1, Touch, false, oneConflictError, oneConflictError, nil, testRelationships}, + {"filters relationships", "test", 1, 1, Fail, false, nil, nil, nil, append([]string{"foo/resource:1#reader@foo/user:1"}, testRelationships...)}, + {"handles gracefully all rels as filtered", "invalid", 1, 1, Fail, false, nil, nil, nil, testRelationships}, } { tt := tt t.Run(tt.name, func(t *testing.T) { @@ -128,12 +127,12 @@ func TestRestorer(t *testing.T) { // if skip is enabled, there will be N less relationships written, where N is the number of conflicts expectedWrittenRels := len(expectedFilteredRels) - if tt.skipOnConflicts { + if tt.conflictStrategy == Skip { expectedWrittenRels -= expectedConflicts * tt.batchSize } expectedWrittenBatches := len(expectedFilteredRels) / tt.batchSize - if tt.skipOnConflicts { + if tt.conflictStrategy == Skip { expectedWrittenBatches -= expectedConflicts } if remainderBatch { @@ -142,21 +141,21 @@ func TestRestorer(t *testing.T) { expectedTouchedBatches := expectedRetries expectedTouchedRels := expectedRetries * tt.batchSize - if tt.touchOnConflicts { + if tt.conflictStrategy == Touch { expectedTouchedBatches += expectedConflicts * int(tt.batchesPerTransaction) expectedTouchedRels += expectedConflicts * int(tt.batchesPerTransaction) * tt.batchSize } expectedSkippedBatches := 0 expectedSkippedRels := 0 - if tt.skipOnConflicts { + if tt.conflictStrategy == Skip { expectedSkippedBatches += expectedConflicts expectedSkippedRels += expectedConflicts * tt.batchSize } - r := newRestorer(testSchema, d, c, tt.prefixFilter, tt.batchSize, tt.batchesPerTransaction, tt.skipOnConflicts, tt.touchOnConflicts, tt.disableRetryErrors, 0*time.Second) + r := newRestorer(testSchema, d, c, tt.prefixFilter, tt.batchSize, tt.batchesPerTransaction, tt.conflictStrategy, tt.disableRetryErrors, 0*time.Second) err = r.restoreFromDecoder(context.Background()) - if expectsError != nil || (expectedConflicts > 0 && !tt.skipOnConflicts && !tt.touchOnConflicts) { + if expectsError != nil || (expectedConflicts > 0 && tt.conflictStrategy == Fail) { require.ErrorIs(t, err, expectsError) return } From ca68115e2d0e1f907e83096de8e2552a86a26332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Wed, 20 Dec 2023 10:36:06 +0000 Subject: [PATCH 34/49] restore: improve progress report on retries --- internal/cmd/restorer.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/internal/cmd/restorer.go b/internal/cmd/restorer.go index 0a173f52..f35daab3 100644 --- a/internal/cmd/restorer.go +++ b/internal/cmd/restorer.go @@ -27,6 +27,9 @@ const ( Fail ConflictStrategy = iota Skip Touch + + defaultBackoff = 50 * time.Millisecond + defaultMaxRetries = 10 ) var conflictStrategyMapping = map[string]ConflictStrategy{ @@ -299,7 +302,7 @@ func (r *restorer) commitStream(ctx context.Context, bulkImportClient v1.Experim // each batch will be committed independently. If a batch fails, it will be retried up to 10 times with a backoff. func (r *restorer) writeBatchesWithRetry(ctx context.Context, batches [][]*v1.Relationship) (uint64, uint64, error) { backoffInterval := backoff.NewExponentialBackOff() - backoffInterval.InitialInterval = 10 * time.Millisecond + backoffInterval.InitialInterval = defaultBackoff backoffInterval.MaxInterval = 2 * time.Second backoffInterval.MaxElapsedTime = 0 backoffInterval.Reset() @@ -314,17 +317,19 @@ func (r *restorer) writeBatchesWithRetry(ctx context.Context, batches [][]*v1.Re }) for { - // throttle the writes so we don't overwhelm the server - time.Sleep(backoffInterval.NextBackOff()) cancelCtx, cancel := context.WithTimeout(ctx, r.requestTimeout) _, err := r.client.WriteRelationships(cancelCtx, &v1.WriteRelationshipsRequest{Updates: updates}) cancel() - if isRetryableError(err) && currentRetries < 10 { + if isRetryableError(err) && currentRetries < defaultMaxRetries { + // throttle the writes so we don't overwhelm the server + bo := backoffInterval.NextBackOff() + r.bar.Describe(fmt.Sprintf("retrying write with backoff %s after error (attempt %d/%d)", bo, + currentRetries+1, defaultMaxRetries)) + time.Sleep(bo) currentRetries++ r.totalRetries++ totalRetries++ - r.bar.Describe(fmt.Sprintf("retrying after error (attempt %d)", currentRetries+1)) continue } if err != nil { From f94a5fe60e6cb7def8958aec7d64635ff58424bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Wed, 20 Dec 2023 11:23:15 +0000 Subject: [PATCH 35/49] only print help on parsing errors --- internal/cmd/cmd.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index ceeea7fe..ba65f5a9 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "errors" "os" "os/signal" "syscall" @@ -9,12 +10,16 @@ import ( "github.com/jzelinskie/cobrautil/v2" "github.com/jzelinskie/cobrautil/v2/cobrazerolog" "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/authzed/zed/internal/commands" ) -var SyncFlagsCmdFunc = cobrautil.SyncViperPreRunE("ZED") +var ( + SyncFlagsCmdFunc = cobrautil.SyncViperPreRunE("ZED") + errParsing = errors.New("parsing error") +) func Run() { zl := cobrazerolog.New(cobrazerolog.WithPreRunLevel(zerolog.DebugLevel)) @@ -27,7 +32,14 @@ func Run() { zl.RunE(), SyncFlagsCmdFunc, ), + SilenceErrors: true, + SilenceUsage: true, } + rootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error { + cmd.Println(err) + cmd.Println(cmd.UsageString()) + return errParsing + }) zl.RegisterFlags(rootCmd.PersistentFlags()) @@ -91,6 +103,10 @@ func Run() { }() if err := rootCmd.ExecuteContext(ctx); err != nil { + if !errors.Is(err, errParsing) { + log.Err(err).Msg("terminated with errors") + } + os.Exit(1) } } From 461353e6125a01781cc6e96c9c2a0f7ac4d8a281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Thu, 21 Dec 2023 09:02:11 +0000 Subject: [PATCH 36/49] PR feedback: reuse MustGetString and do not panic on unexpected flag value --- internal/cmd/backup.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index d0046af0..8e5eb935 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -401,7 +401,10 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { batchSize := cobrautil.MustGetInt(cmd, "batch-size") batchesPerTransaction := cobrautil.MustGetUint(cmd, "batches-per-transaction") - strategy := MustGetEnum[ConflictStrategy](cmd, "conflict-strategy", conflictStrategyMapping) + strategy, err := GetEnum[ConflictStrategy](cmd, "conflict-strategy", conflictStrategyMapping) + if err != nil { + return err + } disableRetries := cobrautil.MustGetBool(cmd, "disable-retries") requestTimeout := cobrautil.MustGetDuration(cmd, "request-timeout") @@ -409,19 +412,16 @@ func backupRestoreCmdFunc(cmd *cobra.Command, args []string) error { disableRetries, requestTimeout).restoreFromDecoder(cmd.Context()) } -// MustGetEnum is a helper for getting an enum value from a string cobra flag. -func MustGetEnum[E constraints.Integer](cmd *cobra.Command, name string, mapping map[string]E) E { - value, err := cmd.Flags().GetString(name) - if err != nil { - panic("failed to find cobra flag: " + name) - } - +// GetEnum is a helper for getting an enum value from a string cobra flag. +func GetEnum[E constraints.Integer](cmd *cobra.Command, name string, mapping map[string]E) (E, error) { + value := cobrautil.MustGetString(cmd, name) value = strings.TrimSpace(strings.ToLower(value)) if enum, ok := mapping[value]; ok { - return enum + return enum, nil } - panic(fmt.Sprintf("unexpected flag value %s: should be one of %v", value, maps.Keys(mapping))) + var zeroValueE E + return zeroValueE, fmt.Errorf("unexpected flag '%s' value '%s': should be one of %v", name, value, maps.Keys(mapping)) } func backupParseSchemaCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { From 720cad9a10cd7a7bb98da6be83ac63d6956148b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:32:58 +0000 Subject: [PATCH 37/49] build(deps): bump github.com/google/uuid from 1.4.0 to 1.5.0 Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/google/uuid/releases) - [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) --- updated-dependencies: - dependency-name: github.com/google/uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 743b6de5..9f51c894 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/brianvoe/gofakeit/v6 v6.26.3 github.com/cenkalti/backoff/v4 v4.2.1 github.com/charmbracelet/lipgloss v0.9.1 - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.5.0 github.com/gookit/color v1.5.4 github.com/hamba/avro/v2 v2.18.0 github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a diff --git a/go.sum b/go.sum index 864be4c8..513e05d1 100644 --- a/go.sum +++ b/go.sum @@ -312,8 +312,8 @@ github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= From 28ee2447c40872ade2cef37d064997c8645616eb Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 28 Dec 2023 16:40:30 -0500 Subject: [PATCH 38/49] Add command for redacting backups Helpful for providing community support without leaking the names, comments and/or object IDs in the permission system --- go.mod | 1 + go.sum | 3 + internal/cmd/backup.go | 96 +++++++ pkg/backupformat/redaction.go | 324 ++++++++++++++++++++++++ pkg/backupformat/redaction_test.go | 385 +++++++++++++++++++++++++++++ 5 files changed, 809 insertions(+) create mode 100644 pkg/backupformat/redaction.go create mode 100644 pkg/backupformat/redaction_test.go diff --git a/go.mod b/go.mod index 743b6de5..2ad2d4ea 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.5 + github.com/rodaine/table v1.1.0 github.com/rs/zerolog v1.31.0 github.com/samber/lo v1.38.1 github.com/schollz/progressbar/v3 v3.14.1 diff --git a/go.sum b/go.sum index 864be4c8..dcf4f3c3 100644 --- a/go.sum +++ b/go.sum @@ -286,6 +286,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v43 v43.0.0 h1:y+GL7LIsAIF2NZlJ46ZoC/D1W1ivZasT0lnWHMYPZ+U= @@ -542,6 +543,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4= +github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 8e5eb935..5181de33 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -17,6 +17,7 @@ import ( "github.com/authzed/spicedb/pkg/typesystem" "github.com/jzelinskie/cobrautil/v2" "github.com/mattn/go-isatty" + "github.com/rodaine/table" "github.com/rs/zerolog/log" "github.com/schollz/progressbar/v3" "github.com/spf13/cobra" @@ -77,6 +78,15 @@ var ( return backupParseRelsCmdFunc(cmd, os.Stdout, args) }, } + + backupRedactCmd = &cobra.Command{ + Use: "redact ", + Short: "Redact a backup file to remove sensitive information", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return backupRedactCmdFunc(cmd, args) + }, + } ) func registerBackupCmd(rootCmd *cobra.Command) { @@ -89,6 +99,11 @@ func registerBackupCmd(rootCmd *cobra.Command) { backupCmd.AddCommand(backupRestoreCmd) registerBackupRestoreFlags(backupRestoreCmd) + backupCmd.AddCommand(backupRedactCmd) + backupRedactCmd.Flags().Bool("redact-definitions", true, "redact definitions") + backupRedactCmd.Flags().Bool("redact-relations", true, "redact relations") + backupRedactCmd.Flags().Bool("redact-object-ids", true, "redact object IDs") + // Restore used to be on the root, so add it there too, but hidden. restoreCmd := &cobra.Command{ Use: "restore ", @@ -471,6 +486,87 @@ func backupParseRevisionCmdFunc(_ *cobra.Command, out io.Writer, args []string) return err } +func backupRedactCmdFunc(cmd *cobra.Command, args []string) error { + decoder, closer, err := decoderFromArgs(args...) + if err != nil { + return fmt.Errorf("error creating restore file decoder: %w", err) + } + + defer func(e *error) { *e = errors.Join(*e, closer.Close()) }(&err) + defer func(e *error) { *e = errors.Join(*e, decoder.Close()) }(&err) + + filename := args[0] + ".redacted" + writer, err := createBackupFile(filename) + if err != nil { + return err + } + + redactor, err := backupformat.NewRedactor(decoder, writer, backupformat.RedactionOptions{ + RedactDefinitions: cobrautil.MustGetBool(cmd, "redact-definitions"), + RedactRelations: cobrautil.MustGetBool(cmd, "redact-relations"), + RedactObjectIDs: cobrautil.MustGetBool(cmd, "redact-object-ids"), + }) + if err != nil { + return fmt.Errorf("error creating redactor: %w", err) + } + + bar := relProgressBar("redacting backup") + var written int64 + for { + if err := cmd.Context().Err(); err != nil { + return fmt.Errorf("aborted redaction: %w", err) + } + + err := redactor.Next() + if err != nil { + if errors.Is(err, io.EOF) { + break + } + return fmt.Errorf("error redacting: %w", err) + } + + written++ + if err := bar.Set64(written); err != nil { + return fmt.Errorf("error incrementing progress bar: %w", err) + } + } + + if err := bar.Finish(); err != nil { + return fmt.Errorf("error finalizing progress bar: %w", err) + } + + fmt.Println("Redaction map:") + fmt.Println("--------------") + fmt.Println() + + // Draw a table of definitions, caveats and relations mapped. + tbl := table.New("Definition Name", "Redacted Name") + for k, v := range redactor.RedactionMap().Definitions { + tbl.AddRow(k, v) + } + + tbl.Print() + fmt.Println() + + if len(redactor.RedactionMap().Caveats) > 0 { + tbl = table.New("Caveat Name", "Redacted Name") + for k, v := range redactor.RedactionMap().Caveats { + tbl.AddRow(k, v) + } + tbl.Print() + fmt.Println() + } + + tbl = table.New("Relation/Permission Name", "Redacted Name") + for k, v := range redactor.RedactionMap().Relations { + tbl.AddRow(k, v) + } + tbl.Print() + fmt.Println() + + return nil +} + func backupParseRelsCmdFunc(cmd *cobra.Command, out io.Writer, args []string) error { prefix := cobrautil.MustGetString(cmd, "prefix-filter") decoder, closer, err := decoderFromArgs(args...) diff --git a/pkg/backupformat/redaction.go b/pkg/backupformat/redaction.go new file mode 100644 index 00000000..6f331505 --- /dev/null +++ b/pkg/backupformat/redaction.go @@ -0,0 +1,324 @@ +package backupformat + +import ( + "fmt" + "io" + "strconv" + + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/authzed/spicedb/pkg/namespace" + core "github.com/authzed/spicedb/pkg/proto/core/v1" + "github.com/authzed/spicedb/pkg/schemadsl/compiler" + "github.com/authzed/spicedb/pkg/schemadsl/generator" + "github.com/authzed/spicedb/pkg/schemadsl/input" + "github.com/authzed/spicedb/pkg/spiceerrors" +) + +// RedactionOptions are the options to use when redacting data. +type RedactionOptions struct { + // RedactDefinitions will redact the definition names. + RedactDefinitions bool + + // RedactRelations will redact the relation names. + RedactRelations bool + + // RedactObjectIDs will redact the object IDs. + RedactObjectIDs bool +} + +// RedactionMap is the map of original names to their redacted names. +type RedactionMap struct { + // Definitions is the map of original definition names to their redacted names. + Definitions map[string]string + + // Caveats is the map of original caveat names to their redacted names. + Caveats map[string]string + + // Relations is the map of original relation names to their redacted names. + Relations map[string]string + + // ObjectIDs is the map of original object IDs to their redacted names. + ObjectIDs map[string]string +} + +// Invert returns the inverted redaction map, with the redacted names as the keys. +func (rm RedactionMap) Invert() RedactionMap { + inverted := RedactionMap{ + Definitions: make(map[string]string), + Caveats: make(map[string]string), + Relations: make(map[string]string), + ObjectIDs: make(map[string]string), + } + + for k, v := range rm.Definitions { + inverted.Definitions[v] = k + } + + for k, v := range rm.Caveats { + inverted.Caveats[v] = k + } + + for k, v := range rm.Relations { + inverted.Relations[v] = k + } + + for k, v := range rm.ObjectIDs { + inverted.ObjectIDs[v] = k + } + + return inverted +} + +// NewRedactor creates a new redactor that will redact the data as it is written. +func NewRedactor(dec *Decoder, w io.Writer, opts RedactionOptions) (*Redactor, error) { + // Rewrite the schema to redact as requested. + redactedSchema, redactionMap, err := redactSchema(dec.Schema(), opts) + if err != nil { + return nil, err + } + + // Create a new encoder with the redacted schema. + token := dec.ZedToken() + encoder, err := NewEncoder(w, redactedSchema, token) + if err != nil { + return nil, err + } + + return &Redactor{dec, opts, encoder, redactionMap}, nil +} + +type Redactor struct { + dec *Decoder + opts RedactionOptions + enc *Encoder + redactionMap RedactionMap +} + +// Next redacts the next record and writes it to the writer. +func (r *Redactor) Next() error { + // Read the next record. + rel, err := r.dec.Next() + if err != nil { + return err + } + + if rel == nil { + return io.EOF + } + + // Redact the record. + redactedRel, err := redactRelationship(rel, &r.redactionMap, r.opts) + if err != nil { + return err + } + + // Write the redacted record. + return r.enc.Append(redactedRel) +} + +// RedactionMap returns the redaction map containing the original names and their redacted names. +func (r *Redactor) RedactionMap() RedactionMap { + return r.redactionMap +} + +func (r *Redactor) Close() error { + if err := r.enc.Close(); err != nil { + return err + } + + return r.dec.Close() +} + +func redactSchema(schema string, opts RedactionOptions) (string, RedactionMap, error) { + // Parse the schema. + compiled, err := compiler.Compile(compiler.InputSchema{ + Source: input.Source("schema"), SchemaString: schema, + }) + if err != nil { + return "", RedactionMap{}, err + } + + // Create a new schema with the redacted fields. + redactionMap := RedactionMap{ + Definitions: make(map[string]string), + Caveats: make(map[string]string), + Relations: make(map[string]string), + ObjectIDs: make(map[string]string), + } + + redactionCount := 0 + + // Redact namespace and caveat names. + if opts.RedactDefinitions { + for _, nsDef := range compiled.ObjectDefinitions { + if opts.RedactDefinitions { + redactionMap.Definitions[nsDef.Name] = "def" + strconv.Itoa(redactionCount) + redactionCount++ + nsDef.Name = redactionMap.Definitions[nsDef.Name] + } + + namespace.FilterUserDefinedMetadataInPlace(nsDef) + } + + if len(compiled.CaveatDefinitions) > 0 { + fmt.Println("WARNING: Caveat parameters and comments are not currently redacted.") + } + + for _, caveatDef := range compiled.CaveatDefinitions { + if opts.RedactDefinitions { + redactionMap.Caveats[caveatDef.Name] = "cav" + strconv.Itoa(redactionCount) + redactionCount++ + caveatDef.Name = redactionMap.Caveats[caveatDef.Name] + } + + // TODO: Redact caveat parameters. + // TODO: filter caveat metadata. + } + } + + // Redact relation names. + if opts.RedactRelations { + for _, nsDef := range compiled.ObjectDefinitions { + for _, relDef := range nsDef.Relation { + if existing, ok := redactionMap.Relations[relDef.Name]; ok { + relDef.Name = existing + continue + } + + redactionMap.Relations[relDef.Name] = "rel" + strconv.Itoa(redactionCount) + redactionCount++ + relDef.Name = redactionMap.Relations[relDef.Name] + } + } + } + + // Redact type information. + if opts.RedactDefinitions || opts.RedactRelations { + for _, nsDef := range compiled.ObjectDefinitions { + for _, relDef := range nsDef.Relation { + if relDef.TypeInformation != nil { + for _, allowedDirect := range relDef.TypeInformation.AllowedDirectRelations { + if opts.RedactDefinitions { + allowedDirect.Namespace = redactionMap.Definitions[allowedDirect.Namespace] + + if allowedDirect.RequiredCaveat != nil { + allowedDirect.RequiredCaveat.CaveatName = redactionMap.Caveats[allowedDirect.RequiredCaveat.CaveatName] + } + } + + if opts.RedactRelations { + switch t := allowedDirect.RelationOrWildcard.(type) { + case *core.AllowedRelation_Relation: + t.Relation = redactionMap.Relations[t.Relation] + } + } + } + } + } + } + } + + // Redact within userset rewrites. + if opts.RedactRelations { + for _, nsDef := range compiled.ObjectDefinitions { + for _, relDef := range nsDef.Relation { + if relDef.UsersetRewrite != nil { + err := redactUsersetRewrite(relDef.UsersetRewrite, &redactionMap) + if err != nil { + return "", RedactionMap{}, err + } + } + } + } + } + + // Generate the schema string. + generated, _, err := generator.GenerateSchema(compiled.OrderedDefinitions) + return generated, redactionMap, err +} + +func redactUsersetRewrite(usersetRewrite *core.UsersetRewrite, redactionMap *RedactionMap) error { + switch t := usersetRewrite.RewriteOperation.(type) { + case *core.UsersetRewrite_Union: + return redactRewriteChildren(t.Union.Child, redactionMap) + + case *core.UsersetRewrite_Intersection: + return redactRewriteChildren(t.Intersection.Child, redactionMap) + + case *core.UsersetRewrite_Exclusion: + return redactRewriteChildren(t.Exclusion.Child, redactionMap) + + default: + return spiceerrors.MustBugf("unknown userset rewrite type: %T", t) + } +} + +func redactRewriteChildren(children []*core.SetOperation_Child, redactionMap *RedactionMap) error { + for _, child := range children { + switch t := child.ChildType.(type) { + case *core.SetOperation_Child_ComputedUserset: + t.ComputedUserset.Relation = redactionMap.Relations[t.ComputedUserset.Relation] + + case *core.SetOperation_Child_UsersetRewrite: + err := redactUsersetRewrite(t.UsersetRewrite, redactionMap) + if err != nil { + return err + } + + case *core.SetOperation_Child_TupleToUserset: + t.TupleToUserset.Tupleset.Relation = redactionMap.Relations[t.TupleToUserset.Tupleset.Relation] + t.TupleToUserset.ComputedUserset.Relation = redactionMap.Relations[t.TupleToUserset.ComputedUserset.Relation] + + case *core.SetOperation_Child_XNil: + // nothing to do + + case *core.SetOperation_Child_XThis: + // nothing to do + + default: + return spiceerrors.MustBugf("unknown child type: %T", t) + } + } + + return nil +} + +func redactRelationship(rel *v1.Relationship, redactionMap *RedactionMap, opts RedactionOptions) (*v1.Relationship, error) { + redactedRel := rel.CloneVT() + + // Redact the resource. + if opts.RedactDefinitions { + redactedRel.Resource.ObjectType = redactionMap.Definitions[redactedRel.Resource.ObjectType] + redactedRel.Subject.Object.ObjectType = redactionMap.Definitions[redactedRel.Subject.Object.ObjectType] + + if rel.OptionalCaveat != nil { + redactedRel.OptionalCaveat.CaveatName = redactionMap.Caveats[redactedRel.OptionalCaveat.CaveatName] + } + } + + // Redact the relation. + if opts.RedactRelations { + redactedRel.Relation = redactionMap.Relations[redactedRel.Relation] + + if rel.Subject.OptionalRelation != "" { + redactedRel.Subject.OptionalRelation = redactionMap.Relations[redactedRel.Subject.OptionalRelation] + } + } + + // Redact the object IDs. + if opts.RedactObjectIDs { + if _, ok := redactionMap.ObjectIDs[redactedRel.Resource.ObjectId]; !ok { + redactionMap.ObjectIDs[redactedRel.Resource.ObjectId] = "obj" + strconv.Itoa(len(redactionMap.ObjectIDs)) + } + + redactedRel.Resource.ObjectId = redactionMap.ObjectIDs[redactedRel.Resource.ObjectId] + + if _, ok := redactionMap.ObjectIDs[redactedRel.Subject.Object.ObjectId]; !ok { + redactionMap.ObjectIDs[redactedRel.Subject.Object.ObjectId] = "obj" + strconv.Itoa(len(redactionMap.ObjectIDs)) + } + + redactedRel.Subject.Object.ObjectId = redactionMap.ObjectIDs[redactedRel.Subject.Object.ObjectId] + } + + return redactedRel, nil +} diff --git a/pkg/backupformat/redaction_test.go b/pkg/backupformat/redaction_test.go new file mode 100644 index 00000000..ec4b476e --- /dev/null +++ b/pkg/backupformat/redaction_test.go @@ -0,0 +1,385 @@ +package backupformat + +import ( + "bytes" + "encoding/base64" + "io" + "testing" + + v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" + "github.com/brianvoe/gofakeit/v6" + "github.com/stretchr/testify/require" +) + +func TestRedactSchema(t *testing.T) { + tcs := []struct { + name string + opts RedactionOptions + in string + out string + redactionMap RedactionMap + }{ + { + name: "single def", + opts: RedactionOptions{ + RedactDefinitions: true, + RedactRelations: true, + RedactObjectIDs: true, + }, + in: `definition user {}`, + out: `definition def0 {}`, + redactionMap: RedactionMap{ + Definitions: map[string]string{ + "user": "def0", + }, + Caveats: map[string]string{}, + Relations: map[string]string{}, + ObjectIDs: map[string]string{}, + }, + }, + { + name: "basic with relations", + opts: RedactionOptions{ + RedactDefinitions: true, + RedactRelations: true, + RedactObjectIDs: true, + }, + in: ` + definition user {} + + definition resource { + relation viewer: user + permission view = viewer + }`, + out: "definition def0 {}\n\ndefinition def1 {\n\trelation rel2: def0\n\tpermission rel3 = rel2\n}", + redactionMap: RedactionMap{ + Definitions: map[string]string{ + "user": "def0", + "resource": "def1", + }, + Caveats: map[string]string{}, + Relations: map[string]string{ + "view": "rel3", + "viewer": "rel2", + }, + ObjectIDs: map[string]string{}, + }, + }, + { + name: "no relation rewriting", + opts: RedactionOptions{ + RedactDefinitions: true, + RedactRelations: false, + RedactObjectIDs: true, + }, + in: ` + definition user {} + + definition resource { + relation viewer: user + permission view = viewer + }`, + out: "definition def0 {}\n\ndefinition def1 {\n\trelation viewer: def0\n\tpermission view = viewer\n}", + redactionMap: RedactionMap{ + Definitions: map[string]string{ + "user": "def0", + "resource": "def1", + }, + Caveats: map[string]string{}, + Relations: map[string]string{}, + ObjectIDs: map[string]string{}, + }, + }, + { + name: "no definition rewriting", + opts: RedactionOptions{ + RedactDefinitions: false, + RedactRelations: true, + RedactObjectIDs: true, + }, + in: ` + definition user {} + + definition resource { + relation viewer: user + permission view = viewer + }`, + out: "definition user {}\n\ndefinition resource {\n\trelation rel0: user\n\tpermission rel1 = rel0\n}", + redactionMap: RedactionMap{ + Definitions: map[string]string{}, + Caveats: map[string]string{}, + Relations: map[string]string{ + "view": "rel1", + "viewer": "rel0", + }, + ObjectIDs: map[string]string{}, + }, + }, + { + name: "basic with caveats", + opts: RedactionOptions{ + RedactDefinitions: true, + RedactRelations: true, + RedactObjectIDs: true, + }, + in: ` + definition user {} + + caveat some_caveat(is_allowed bool) { + is_allowed + } + + definition resource { + relation viewer: user with some_caveat + permission view = viewer + }`, + out: "definition def0 {}\n\ncaveat cav2(is_allowed bool) {\n\tis_allowed\n}\n\ndefinition def1 {\n\trelation rel3: def0 with cav2\n\tpermission rel4 = rel3\n}", + redactionMap: RedactionMap{ + Definitions: map[string]string{ + "user": "def0", + "resource": "def1", + }, + Caveats: map[string]string{ + "some_caveat": "cav2", + }, + Relations: map[string]string{ + "view": "rel4", + "viewer": "rel3", + }, + ObjectIDs: map[string]string{}, + }, + }, + { + name: "all expressions", + opts: RedactionOptions{ + RedactDefinitions: true, + RedactRelations: true, + RedactObjectIDs: true, + }, + in: ` + definition user {} + + definition resource { + relation viewer: user + relation editor: user + + permission somethingelse = viewer->editor + nil + permission view = viewer & (viewer - editor) + }`, + out: "definition def0 {}\n\ndefinition def1 {\n\trelation rel2: def0\n\trelation rel3: def0\n\tpermission rel4 = rel2->rel3 + nil\n\tpermission rel5 = rel2 & (rel2 - rel3)\n}", + redactionMap: RedactionMap{ + Definitions: map[string]string{ + "user": "def0", + "resource": "def1", + }, + Caveats: map[string]string{}, + Relations: map[string]string{ + "editor": "rel3", + "somethingelse": "rel4", + "view": "rel5", + "viewer": "rel2", + }, + ObjectIDs: map[string]string{}, + }, + }, + { + name: "all types", + opts: RedactionOptions{ + RedactDefinitions: true, + RedactRelations: true, + RedactObjectIDs: true, + }, + in: ` + definition user {} + + definition someothertype { + relation somerel: user + } + + definition resource { + relation viewer: user | user:* | someothertype#somerel + }`, + out: "definition def0 {}\n\ndefinition def1 {\n\trelation rel3: def0\n}\n\ndefinition def2 {\n\trelation rel4: def0 | def0:* | def1#rel3\n}", + redactionMap: RedactionMap{ + Definitions: map[string]string{ + "user": "def0", + "someothertype": "def1", + "resource": "def2", + }, + Caveats: map[string]string{}, + Relations: map[string]string{ + "somerel": "rel3", + "viewer": "rel4", + }, + ObjectIDs: map[string]string{}, + }, + }, + { + name: "same relation name in different definitions", + opts: RedactionOptions{ + RedactDefinitions: true, + RedactRelations: true, + RedactObjectIDs: true, + }, + in: ` + definition user {} + + definition someothertype { + relation somerel: user + } + + definition resource { + relation somerel: user + }`, + out: "definition def0 {}\n\ndefinition def1 {\n\trelation rel3: def0\n}\n\ndefinition def2 {\n\trelation rel3: def0\n}", + redactionMap: RedactionMap{ + Definitions: map[string]string{ + "user": "def0", + "someothertype": "def1", + "resource": "def2", + }, + Caveats: map[string]string{}, + Relations: map[string]string{ + "somerel": "rel3", + }, + ObjectIDs: map[string]string{}, + }, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + out, redactionMap, err := redactSchema(tc.in, tc.opts) + require.NoError(t, err) + require.Equal(t, tc.out, out) + require.Equal(t, tc.redactionMap, redactionMap) + }) + } +} + +func TestRedactBackup(t *testing.T) { + exampleSchema := ` + definition user {} + + definition someotheresource { + relation foo: user + } + + definition resource { + relation viewer: user + permission view = viewer + }` + + exampleRelationships := []*v1.Relationship{ + { + Resource: &v1.ObjectReference{ + ObjectType: "resource", + ObjectId: "resource1", + }, + Relation: "viewer", + Subject: &v1.SubjectReference{ + Object: &v1.ObjectReference{ + ObjectType: "user", + ObjectId: "user1", + }, + }, + }, + { + Resource: &v1.ObjectReference{ + ObjectType: "resource", + ObjectId: "resource2", + }, + Relation: "viewer", + Subject: &v1.SubjectReference{ + Object: &v1.ObjectReference{ + ObjectType: "user", + ObjectId: "user2", + }, + }, + }, + { + Resource: &v1.ObjectReference{ + ObjectType: "resource", + ObjectId: "resource1", + }, + Relation: "viewer", + Subject: &v1.SubjectReference{ + Object: &v1.ObjectReference{ + ObjectType: "user", + ObjectId: "user2", + }, + }, + }, + { + Resource: &v1.ObjectReference{ + ObjectType: "someotheresource", + ObjectId: "resource1", + }, + Relation: "foo", + Subject: &v1.SubjectReference{ + Object: &v1.ObjectReference{ + ObjectType: "user", + ObjectId: "user1", + }, + }, + }, + } + + // Write some data. + buf := bytes.Buffer{} + enc, err := NewEncoder(&buf, exampleSchema, &v1.ZedToken{ + Token: base64.StdEncoding.EncodeToString(gofakeit.ImageJpeg(10, 10)), + }) + require.NoError(t, err) + + for _, rel := range exampleRelationships { + require.NoError(t, enc.Append(rel)) + } + require.NoError(t, enc.Close()) + require.NotEmpty(t, buf.Bytes()) + + // Redact it into a new buffer. + redactedBuf := bytes.Buffer{} + + decoder, err := NewDecoder(bytes.NewReader(buf.Bytes())) + require.NoError(t, err) + + r, err := NewRedactor(decoder, &redactedBuf, RedactionOptions{ + RedactDefinitions: true, + RedactRelations: true, + RedactObjectIDs: true, + }) + require.NoError(t, err) + + for { + err := r.Next() + if err != nil { + require.Equal(t, io.EOF, err) + break + } + } + + require.NoError(t, r.Close()) + + redactionMap := r.RedactionMap().Invert() + + // Validate the redacted data. + redactedDecoder, err := NewDecoder(bytes.NewReader(redactedBuf.Bytes())) + require.NoError(t, err) + + require.Equal(t, "definition def0 {}\n\ndefinition def1 {\n\trelation rel3: def0\n}\n\ndefinition def2 {\n\trelation rel4: def0\n\tpermission rel5 = rel4\n}", redactedDecoder.Schema()) + require.Equal(t, decoder.ZedToken(), redactedDecoder.ZedToken()) + + for _, expected := range exampleRelationships { + rel, err := redactedDecoder.Next() + require.NoError(t, err) + + // Validate the redacted relationship. + require.Equal(t, expected.Resource.ObjectType, redactionMap.Definitions[rel.Resource.ObjectType]) + require.Equal(t, expected.Resource.ObjectId, redactionMap.ObjectIDs[rel.Resource.ObjectId]) + require.Equal(t, expected.Relation, redactionMap.Relations[rel.Relation]) + require.Equal(t, expected.Subject.Object.ObjectType, redactionMap.Definitions[rel.Subject.Object.ObjectType]) + require.Equal(t, expected.Subject.Object.ObjectId, redactionMap.ObjectIDs[rel.Subject.Object.ObjectId]) + require.Equal(t, expected.Subject.OptionalRelation, redactionMap.Relations[rel.Subject.OptionalRelation]) + } +} From f75c8d3f59caf4dbf669180678056a2c19c4d599 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Mon, 8 Jan 2024 19:54:24 -0500 Subject: [PATCH 39/49] cmd: add autocomplete to `zed use` This shortcut was missing the autocompletion available in the longform `zed context use`. --- internal/cmd/cmd.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index ba65f5a9..a128be5e 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -64,10 +64,11 @@ func Run() { // Register root-level aliases rootCmd.AddCommand(&cobra.Command{ - Use: "use ", - Short: "an alias for `zed context use`", - Args: cobra.MaximumNArgs(1), - RunE: contextUseCmdFunc, + Use: "use ", + Short: "an alias for `zed context use`", + Args: cobra.MaximumNArgs(1), + RunE: contextUseCmdFunc, + ValidArgsFunction: ContextGet, }) // Register CLI-only commands. From 8ba4e8494a87a90036a470b121071b78172c7c5b Mon Sep 17 00:00:00 2001 From: Alec Merdler Date: Sat, 13 Jan 2024 14:55:10 -0500 Subject: [PATCH 40/49] Fix typo in helper text for --certificate-path Small typo fix. --- internal/cmd/cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index a128be5e..c4acff4c 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -46,7 +46,7 @@ func Run() { rootCmd.PersistentFlags().String("endpoint", "", "spicedb gRPC API endpoint") rootCmd.PersistentFlags().String("permissions-system", "", "permissions system to query") rootCmd.PersistentFlags().String("token", "", "token used to authenticate to SpiceDB") - rootCmd.PersistentFlags().String("certificate-path", "", "path to certificate authoriy used to verify secure connections") + rootCmd.PersistentFlags().String("certificate-path", "", "path to certificate authority used to verify secure connections") rootCmd.PersistentFlags().Bool("insecure", false, "connect over a plaintext connection") rootCmd.PersistentFlags().Bool("skip-version-check", false, "if true, no version check is performed against the server") rootCmd.PersistentFlags().Bool("no-verify-ca", false, "do not attempt to verify the server's certificate chain and host name") From 376eb90683485a37e97e6266e28569c376964b49 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Wed, 17 Jan 2024 16:12:48 -0500 Subject: [PATCH 41/49] context: add autocomplete for remove --- internal/cmd/context.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/cmd/context.go b/internal/cmd/context.go index 0f938cd0..e97dc0d2 100644 --- a/internal/cmd/context.go +++ b/internal/cmd/context.go @@ -45,10 +45,11 @@ var contextSetCmd = &cobra.Command{ } var contextRemoveCmd = &cobra.Command{ - Use: "remove ", - Short: "remove a context", - Args: cobra.ExactArgs(1), - RunE: contextRemoveCmdFunc, + Use: "remove ", + Short: "remove a context", + Args: cobra.ExactArgs(1), + RunE: contextRemoveCmdFunc, + ValidArgsFunction: ContextGet, } var contextUseCmd = &cobra.Command{ From df52f86cf36d7f0a1ac4cfe268ec5ffbc3026e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 19 Jan 2024 18:16:39 +0000 Subject: [PATCH 42/49] fixes bug where redacted files would be corrupted as the Avro encoder wasn't being flushed and the file may have been partially written --- internal/cmd/backup.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 5181de33..d19a35ec 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -501,6 +501,8 @@ func backupRedactCmdFunc(cmd *cobra.Command, args []string) error { return err } + defer func(e *error) { *e = errors.Join(*e, writer.Close()) }(&err) + redactor, err := backupformat.NewRedactor(decoder, writer, backupformat.RedactionOptions{ RedactDefinitions: cobrautil.MustGetBool(cmd, "redact-definitions"), RedactRelations: cobrautil.MustGetBool(cmd, "redact-relations"), @@ -510,6 +512,7 @@ func backupRedactCmdFunc(cmd *cobra.Command, args []string) error { return fmt.Errorf("error creating redactor: %w", err) } + defer func(e *error) { *e = errors.Join(*e, redactor.Close()) }(&err) bar := relProgressBar("redacting backup") var written int64 for { From 864c1a3ef4032efe479b9c01712e988276357212 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Fri, 19 Jan 2024 14:56:00 -0500 Subject: [PATCH 43/49] cmd: disable file completion, add ext completion --- internal/cmd/context.go | 22 ++++++++++++---------- internal/cmd/schema.go | 18 ++++++++++-------- internal/commands/completion.go | 6 ++++++ internal/commands/permission.go | 17 +++++++++-------- internal/commands/relationship.go | 10 +++++----- internal/commands/schema.go | 9 +++++---- 6 files changed, 47 insertions(+), 35 deletions(-) diff --git a/internal/cmd/context.go b/internal/cmd/context.go index e97dc0d2..83eee436 100644 --- a/internal/cmd/context.go +++ b/internal/cmd/context.go @@ -31,33 +31,35 @@ var contextCmd = &cobra.Command{ } var contextListCmd = &cobra.Command{ - Use: "list", - Short: "list all contexts", - Args: cobra.ExactArgs(0), - RunE: contextListCmdFunc, + Use: "list", + Short: "list all contexts", + Args: cobra.ExactArgs(0), + ValidArgsFunction: cobra.NoFileCompletions, + RunE: contextListCmdFunc, } var contextSetCmd = &cobra.Command{ - Use: "set ", - Short: "create or overwrite a context", - Args: cobra.ExactArgs(3), - RunE: contextSetCmdFunc, + Use: "set ", + Short: "create or overwrite a context", + Args: cobra.ExactArgs(3), + ValidArgsFunction: cobra.NoFileCompletions, + RunE: contextSetCmdFunc, } var contextRemoveCmd = &cobra.Command{ Use: "remove ", Short: "remove a context", Args: cobra.ExactArgs(1), - RunE: contextRemoveCmdFunc, ValidArgsFunction: ContextGet, + RunE: contextRemoveCmdFunc, } var contextUseCmd = &cobra.Command{ Use: "use ", Short: "set a context as the current context", Args: cobra.MaximumNArgs(1), - RunE: contextUseCmdFunc, ValidArgsFunction: ContextGet, + RunE: contextUseCmdFunc, } func ContextGet(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { diff --git a/internal/cmd/schema.go b/internal/cmd/schema.go index 75da0379..73fba4d5 100644 --- a/internal/cmd/schema.go +++ b/internal/cmd/schema.go @@ -36,17 +36,19 @@ func registerAdditionalSchemaCmds(schemaCmd *cobra.Command) { } var schemaWriteCmd = &cobra.Command{ - Use: "write ", - Args: cobra.MaximumNArgs(1), - Short: "write a Schema file (or stdin) to the current Permissions System", - RunE: schemaWriteCmdFunc, + Use: "write ", + Args: cobra.MaximumNArgs(1), + Short: "write a schema file (.zed or stdin) to the current permissions system", + ValidArgsFunction: commands.FileExtensionCompletions("zed"), + RunE: schemaWriteCmdFunc, } var schemaCopyCmd = &cobra.Command{ - Use: "copy ", - Args: cobra.ExactArgs(2), - Short: "copy a Schema from one context into another", - RunE: schemaCopyCmdFunc, + Use: "copy ", + Short: "copy a schema from one context into another", + Args: cobra.ExactArgs(2), + ValidArgsFunction: ContextGet, + RunE: schemaCopyCmdFunc, } // TODO(jschorr): support this in the client package diff --git a/internal/commands/completion.go b/internal/commands/completion.go index 83ab8236..8e4504e3 100644 --- a/internal/commands/completion.go +++ b/internal/commands/completion.go @@ -22,6 +22,12 @@ const ( SubjectTypeWithOptionalRelation ) +func FileExtensionCompletions(extension ...string) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return extension, cobra.ShellCompDirectiveFilterFileExt + } +} + func GetArgs(fields ...CompletionArgumentType) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // Read the current schema, if any. diff --git a/internal/commands/permission.go b/internal/commands/permission.go index 14e6de23..bf4fa061 100644 --- a/internal/commands/permission.go +++ b/internal/commands/permission.go @@ -113,40 +113,41 @@ var checkCmd = &cobra.Command{ Use: "check ", Short: "check that a Permission exists for a Subject", Args: cobra.ExactArgs(3), - RunE: checkCmdFunc, ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectID), + RunE: checkCmdFunc, } var expandCmd = &cobra.Command{ - Use: "expand ", - Short: "expand the structure of a Permission", - Args: cobra.ExactArgs(2), - RunE: expandCmdFunc, + Use: "expand ", + Short: "expand the structure of a Permission", + Args: cobra.ExactArgs(2), + ValidArgsFunction: cobra.NoFileCompletions, + RunE: expandCmdFunc, } var lookupResourcesCmd = &cobra.Command{ Use: "lookup-resources ", Short: "looks up the Resources of a given type for which the Subject has Permission", Args: cobra.ExactArgs(3), - RunE: lookupResourcesCmdFunc, ValidArgsFunction: GetArgs(ResourceType, Permission, SubjectID), + RunE: lookupResourcesCmdFunc, } var lookupCmd = &cobra.Command{ Use: "lookup ", Short: "lookup the Resources of a given type for which the Subject has Permission", Args: cobra.ExactArgs(3), + ValidArgsFunction: GetArgs(ResourceType, Permission, SubjectID), RunE: lookupResourcesCmdFunc, Hidden: true, - ValidArgsFunction: GetArgs(ResourceType, Permission, SubjectID), } var lookupSubjectsCmd = &cobra.Command{ Use: "lookup-subjects ", Short: "lookup the Subjects of a given type for which the Subject has Permission on the Resource", Args: cobra.ExactArgs(3), - RunE: lookupSubjectsCmdFunc, ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), + RunE: lookupSubjectsCmdFunc, } func checkCmdFunc(cmd *cobra.Command, args []string) error { diff --git a/internal/commands/relationship.go b/internal/commands/relationship.go index feecbe9d..39a56014 100644 --- a/internal/commands/relationship.go +++ b/internal/commands/relationship.go @@ -63,40 +63,40 @@ var createCmd = &cobra.Command{ Use: "create ", Short: "create a Relationship for a Subject", Args: StdinOrExactArgs(3), - RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_CREATE, os.Stdin), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), + RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_CREATE, os.Stdin), } var touchCmd = &cobra.Command{ Use: "touch ", Short: "idempotently update a Relationship for a Subject", Args: StdinOrExactArgs(3), - RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_TOUCH, os.Stdin), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), + RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_TOUCH, os.Stdin), } var deleteCmd = &cobra.Command{ Use: "delete ", Short: "delete a Relationship", Args: StdinOrExactArgs(3), - RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_DELETE, os.Stdin), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), + RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_DELETE, os.Stdin), } var readCmd = &cobra.Command{ Use: "read ", Short: "reads Relationships", Args: cobra.RangeArgs(1, 3), - RunE: readRelationships, ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), + RunE: readRelationships, } var bulkDeleteCmd = &cobra.Command{ Use: "bulk-delete ", Short: "bulk delete Relationships", Args: cobra.RangeArgs(1, 3), - RunE: bulkDeleteRelationships, ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), + RunE: bulkDeleteRelationships, } func StdinOrExactArgs(n int) cobra.PositionalArgs { diff --git a/internal/commands/schema.go b/internal/commands/schema.go index 5ed0af2b..0e56234a 100644 --- a/internal/commands/schema.go +++ b/internal/commands/schema.go @@ -31,10 +31,11 @@ var ( } schemaReadCmd = &cobra.Command{ - Use: "read", - Args: cobra.ExactArgs(0), - Short: "read the Schema of current Permissions System", - RunE: schemaReadCmdFunc, + Use: "read", + Short: "read the Schema of current Permissions System", + Args: cobra.ExactArgs(0), + ValidArgsFunction: cobra.NoFileCompletions, + RunE: schemaReadCmdFunc, } ) From 6061f4eaf597e63a003fa8ad7c24e074feaa1296 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Fri, 19 Jan 2024 17:45:30 -0500 Subject: [PATCH 44/49] cmd: fix help-text casing, more fileext completion --- internal/cmd/backup.go | 4 ++-- internal/cmd/cmd.go | 4 ++-- internal/cmd/context.go | 10 +++++----- internal/cmd/import.go | 2 +- internal/cmd/schema.go | 4 ++-- internal/cmd/validate.go | 8 +++++--- internal/commands/permission.go | 12 ++++++------ internal/commands/relationship.go | 12 ++++++------ internal/commands/schema.go | 4 ++-- internal/commands/watch.go | 2 +- 10 files changed, 32 insertions(+), 30 deletions(-) diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index d19a35ec..0117a65a 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -32,7 +32,7 @@ import ( var ( backupCmd = &cobra.Command{ Use: "backup ", - Short: "Create, restore, and inspect Permissions System backups", + Short: "Create, restore, and inspect permissions system backups", Args: cobra.ExactArgs(1), // Create used to be on the root, so add it here for back-compat. RunE: backupCreateCmdFunc, @@ -107,7 +107,7 @@ func registerBackupCmd(rootCmd *cobra.Command) { // Restore used to be on the root, so add it there too, but hidden. restoreCmd := &cobra.Command{ Use: "restore ", - Short: "Restore a permission system from a file", + Short: "Restore a permission system from a backup file", Args: cobra.MaximumNArgs(1), RunE: backupRestoreCmdFunc, Hidden: true, diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index c4acff4c..8741e036 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -55,7 +55,7 @@ func Run() { versionCmd := &cobra.Command{ Use: "version", - Short: "display zed version information", + Short: "Display zed and SpiceDB version information", RunE: versionCmdFunc, } cobrautil.RegisterVersionFlags(versionCmd.Flags()) @@ -65,7 +65,7 @@ func Run() { // Register root-level aliases rootCmd.AddCommand(&cobra.Command{ Use: "use ", - Short: "an alias for `zed context use`", + Short: "Alias for `zed context use`", Args: cobra.MaximumNArgs(1), RunE: contextUseCmdFunc, ValidArgsFunction: ContextGet, diff --git a/internal/cmd/context.go b/internal/cmd/context.go index 83eee436..d49757b2 100644 --- a/internal/cmd/context.go +++ b/internal/cmd/context.go @@ -27,12 +27,12 @@ func registerContextCmd(rootCmd *cobra.Command) { var contextCmd = &cobra.Command{ Use: "context ", - Short: "manage your machines Authzed credentials", + Short: "Manage configurations for connecting to SpiceDB deployments", } var contextListCmd = &cobra.Command{ Use: "list", - Short: "list all contexts", + Short: "Lists all available contexts", Args: cobra.ExactArgs(0), ValidArgsFunction: cobra.NoFileCompletions, RunE: contextListCmdFunc, @@ -40,7 +40,7 @@ var contextListCmd = &cobra.Command{ var contextSetCmd = &cobra.Command{ Use: "set ", - Short: "create or overwrite a context", + Short: "Creates or overwrite a context", Args: cobra.ExactArgs(3), ValidArgsFunction: cobra.NoFileCompletions, RunE: contextSetCmdFunc, @@ -48,7 +48,7 @@ var contextSetCmd = &cobra.Command{ var contextRemoveCmd = &cobra.Command{ Use: "remove ", - Short: "remove a context", + Short: "Removes a context", Args: cobra.ExactArgs(1), ValidArgsFunction: ContextGet, RunE: contextRemoveCmdFunc, @@ -56,7 +56,7 @@ var contextRemoveCmd = &cobra.Command{ var contextUseCmd = &cobra.Command{ Use: "use ", - Short: "set a context as the current context", + Short: "Sets a context as the current context", Args: cobra.MaximumNArgs(1), ValidArgsFunction: ContextGet, RunE: contextUseCmdFunc, diff --git a/internal/cmd/import.go b/internal/cmd/import.go index 9a50aa37..76c0c7b0 100644 --- a/internal/cmd/import.go +++ b/internal/cmd/import.go @@ -29,7 +29,7 @@ func registerImportCmd(rootCmd *cobra.Command) { var importCmd = &cobra.Command{ Use: "import ", - Short: "import schema and relationships from a file or url", + Short: "Imports schema and relationships from a file or url", Example: ` From a gist: zed import https://gist.github.com/ecordell/8e3b613a677e3c844742cf24421c08b6 diff --git a/internal/cmd/schema.go b/internal/cmd/schema.go index 73fba4d5..9892f07b 100644 --- a/internal/cmd/schema.go +++ b/internal/cmd/schema.go @@ -38,14 +38,14 @@ func registerAdditionalSchemaCmds(schemaCmd *cobra.Command) { var schemaWriteCmd = &cobra.Command{ Use: "write ", Args: cobra.MaximumNArgs(1), - Short: "write a schema file (.zed or stdin) to the current permissions system", + Short: "Write a schema file (.zed or stdin) to the current permissions system", ValidArgsFunction: commands.FileExtensionCompletions("zed"), RunE: schemaWriteCmdFunc, } var schemaCopyCmd = &cobra.Command{ Use: "copy ", - Short: "copy a schema from one context into another", + Short: "Copy a schema from one context into another", Args: cobra.ExactArgs(2), ValidArgsFunction: ContextGet, RunE: schemaCopyCmdFunc, diff --git a/internal/cmd/validate.go b/internal/cmd/validate.go index 1cb33f27..27141ccd 100644 --- a/internal/cmd/validate.go +++ b/internal/cmd/validate.go @@ -18,6 +18,7 @@ import ( "github.com/authzed/spicedb/pkg/validationfile" "github.com/charmbracelet/lipgloss" + "github.com/authzed/zed/internal/commands" "github.com/authzed/zed/internal/console" "github.com/authzed/zed/internal/decode" "github.com/authzed/zed/internal/printers" @@ -41,7 +42,7 @@ func registerValidateCmd(rootCmd *cobra.Command) { var validateCmd = &cobra.Command{ Use: "validate ", - Short: "validate the given validation or schema file", + Short: "Validates the given validation file (.yaml, .zaml) or schema file (.zed)", Example: ` From a local file (with prefix): zed validate file:///Users/zed/Downloads/authzed-x7izWU8_2Gw3.yaml @@ -60,8 +61,9 @@ var validateCmd = &cobra.Command{ From a devtools instance: zed validate https://localhost:8443/download`, - Args: cobra.ExactArgs(1), - RunE: validateCmdFunc, + Args: cobra.ExactArgs(1), + ValidArgsFunction: commands.FileExtensionCompletions("zed", "yaml", "zaml"), + RunE: validateCmdFunc, } func validateCmdFunc(cmd *cobra.Command, args []string) error { diff --git a/internal/commands/permission.go b/internal/commands/permission.go index bf4fa061..5d81f74c 100644 --- a/internal/commands/permission.go +++ b/internal/commands/permission.go @@ -106,12 +106,12 @@ func RegisterPermissionCmd(rootCmd *cobra.Command) *cobra.Command { var permissionCmd = &cobra.Command{ Use: "permission ", - Short: "perform queries on the Permissions in a Permissions System", + Short: "Query the permissions in a permissions system", } var checkCmd = &cobra.Command{ Use: "check ", - Short: "check that a Permission exists for a Subject", + Short: "Check that a permission exists for a subject", Args: cobra.ExactArgs(3), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectID), RunE: checkCmdFunc, @@ -119,7 +119,7 @@ var checkCmd = &cobra.Command{ var expandCmd = &cobra.Command{ Use: "expand ", - Short: "expand the structure of a Permission", + Short: "Expand the structure of a permission", Args: cobra.ExactArgs(2), ValidArgsFunction: cobra.NoFileCompletions, RunE: expandCmdFunc, @@ -127,7 +127,7 @@ var expandCmd = &cobra.Command{ var lookupResourcesCmd = &cobra.Command{ Use: "lookup-resources ", - Short: "looks up the Resources of a given type for which the Subject has Permission", + Short: "Enumerates resources of a given type for which the subject has permission", Args: cobra.ExactArgs(3), ValidArgsFunction: GetArgs(ResourceType, Permission, SubjectID), RunE: lookupResourcesCmdFunc, @@ -135,7 +135,7 @@ var lookupResourcesCmd = &cobra.Command{ var lookupCmd = &cobra.Command{ Use: "lookup ", - Short: "lookup the Resources of a given type for which the Subject has Permission", + Short: "Enumerates the resources of a given type for which the subject has permission", Args: cobra.ExactArgs(3), ValidArgsFunction: GetArgs(ResourceType, Permission, SubjectID), RunE: lookupResourcesCmdFunc, @@ -144,7 +144,7 @@ var lookupCmd = &cobra.Command{ var lookupSubjectsCmd = &cobra.Command{ Use: "lookup-subjects ", - Short: "lookup the Subjects of a given type for which the Subject has Permission on the Resource", + Short: "Enumerates the subjects of a given type for which the subject has permission on the resource", Args: cobra.ExactArgs(3), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), RunE: lookupSubjectsCmdFunc, diff --git a/internal/commands/relationship.go b/internal/commands/relationship.go index 39a56014..2a1d10ee 100644 --- a/internal/commands/relationship.go +++ b/internal/commands/relationship.go @@ -56,12 +56,12 @@ func RegisterRelationshipCmd(rootCmd *cobra.Command) *cobra.Command { var relationshipCmd = &cobra.Command{ Use: "relationship ", - Short: "perform CRUD operations on the Relationships in a Permissions System", + Short: "Query and mutate the relationships in a permissions system", } var createCmd = &cobra.Command{ Use: "create ", - Short: "create a Relationship for a Subject", + Short: "Create a relationship for a subject", Args: StdinOrExactArgs(3), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_CREATE, os.Stdin), @@ -69,7 +69,7 @@ var createCmd = &cobra.Command{ var touchCmd = &cobra.Command{ Use: "touch ", - Short: "idempotently update a Relationship for a Subject", + Short: "Idempotently updates a relationship for a subject", Args: StdinOrExactArgs(3), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_TOUCH, os.Stdin), @@ -77,7 +77,7 @@ var touchCmd = &cobra.Command{ var deleteCmd = &cobra.Command{ Use: "delete ", - Short: "delete a Relationship", + Short: "Deletes a relationship", Args: StdinOrExactArgs(3), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), RunE: writeRelationshipCmdFunc(v1.RelationshipUpdate_OPERATION_DELETE, os.Stdin), @@ -85,7 +85,7 @@ var deleteCmd = &cobra.Command{ var readCmd = &cobra.Command{ Use: "read ", - Short: "reads Relationships", + Short: "Enumerates relationships matching the provided pattern", Args: cobra.RangeArgs(1, 3), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), RunE: readRelationships, @@ -93,7 +93,7 @@ var readCmd = &cobra.Command{ var bulkDeleteCmd = &cobra.Command{ Use: "bulk-delete ", - Short: "bulk delete Relationships", + Short: "Deletes relationships matching the provided pattern en masse", Args: cobra.RangeArgs(1, 3), ValidArgsFunction: GetArgs(ResourceID, Permission, SubjectTypeWithOptionalRelation), RunE: bulkDeleteRelationships, diff --git a/internal/commands/schema.go b/internal/commands/schema.go index 0e56234a..f6c034fc 100644 --- a/internal/commands/schema.go +++ b/internal/commands/schema.go @@ -27,12 +27,12 @@ func RegisterSchemaCmd(rootCmd *cobra.Command) *cobra.Command { var ( schemaCmd = &cobra.Command{ Use: "schema ", - Short: "manages Schema for a Permissions System", + Short: "Manage schema for a permissions system", } schemaReadCmd = &cobra.Command{ Use: "read", - Short: "read the Schema of current Permissions System", + Short: "Read the schema of a permissions system", Args: cobra.ExactArgs(0), ValidArgsFunction: cobra.NoFileCompletions, RunE: schemaReadCmdFunc, diff --git a/internal/commands/watch.go b/internal/commands/watch.go index 57d09cc7..9e715cb8 100644 --- a/internal/commands/watch.go +++ b/internal/commands/watch.go @@ -31,7 +31,7 @@ func RegisterWatchCmd(rootCmd *cobra.Command) *cobra.Command { var watchCmd = &cobra.Command{ Use: "watch [object_types, ...] [start_cursor]", - Short: "watches the stream of relationship updates from the server", + Short: "Watches the stream of relationship updates from the server", Args: cobra.RangeArgs(0, 2), RunE: watchCmdFunc, } From e8468cb62e1d4733253bfc119200c89a0d7073bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Rold=C3=A1n=20Betancort?= Date: Fri, 9 Feb 2024 15:49:41 +0000 Subject: [PATCH 45/49] fix ubuntu install instructions if the file `/etc/apt/sources.list.d/fury.list` does not exist the command will fail with `Permission denied` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed9f8260..a6951e6f 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ brew install authzed/tap/zed ```command sudo apt update && sudo apt install -y curl ca-certificates gpg curl https://apt.fury.io/authzed/gpg.key | sudo apt-key add - -echo "deb https://apt.fury.io/authzed/ * *" > /etc/apt/sources.list.d/fury.list +sudo sh -c 'echo "deb https://apt.fury.io/authzed/ * *" > /etc/apt/sources.list.d/fury.list' sudo apt update && sudo apt install -y zed ``` From 5b3e8280c33759e40b90bf425c483b0fb504745d Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Fri, 9 Feb 2024 14:36:03 -0500 Subject: [PATCH 46/49] gomod: update deps including spicedb compiler --- go.mod | 101 ++++++++-------- go.sum | 206 ++++++++++++++++---------------- internal/cmd/backup.go | 11 +- internal/cmd/schema.go | 16 ++- internal/commands/completion.go | 6 +- internal/decode/decoder.go | 5 +- pkg/backupformat/redaction.go | 5 +- 7 files changed, 186 insertions(+), 164 deletions(-) diff --git a/go.mod b/go.mod index 11496a3e..211f5ac9 100644 --- a/go.mod +++ b/go.mod @@ -9,45 +9,45 @@ require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 github.com/authzed/authzed-go v0.10.1 - github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 - github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da + github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b + github.com/authzed/spicedb v1.29.1 github.com/brianvoe/gofakeit/v6 v6.26.3 github.com/cenkalti/backoff/v4 v4.2.1 github.com/charmbracelet/lipgloss v0.9.1 - github.com/google/uuid v1.5.0 + github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 - github.com/hamba/avro/v2 v2.18.0 + github.com/hamba/avro/v2 v2.19.0 github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a github.com/jzelinskie/stringz v0.0.3 github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/rodaine/table v1.1.0 - github.com/rs/zerolog v1.31.0 + github.com/rodaine/table v1.1.1 + github.com/rs/zerolog v1.32.0 github.com/samber/lo v1.39.0 github.com/schollz/progressbar/v3 v3.14.1 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 github.com/xlab/treeprint v1.2.0 - golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb - golang.org/x/mod v0.14.0 - golang.org/x/sync v0.5.0 - golang.org/x/term v0.15.0 - google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.31.0 + golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 + golang.org/x/mod v0.15.0 + golang.org/x/sync v0.6.0 + golang.org/x/term v0.17.0 + google.golang.org/grpc v1.61.0 + google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 ) require ( buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.31.0-20210810001428-4df00b267f94.1 // indirect buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.31.0-20231010075520-899dbbfd2c07.1 // indirect - cloud.google.com/go v0.110.10 // indirect - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/longrunning v0.5.4 // indirect - cloud.google.com/go/spanner v1.53.0 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/longrunning v0.5.5 // indirect + cloud.google.com/go/spanner v1.56.0 // indirect contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/IBM/pgxpoolprometheus v1.1.1 // indirect @@ -58,18 +58,18 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.6.0 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cloudspannerecosystem/spanner-change-streams-tail v0.3.1 // indirect github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect - github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect + github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 // indirect github.com/creack/pty v1.1.18 // indirect github.com/creasty/defaults v1.7.0 // indirect github.com/dalzilio/rudd v1.1.1-0.20230806153452-9e08a6ea8170 // indirect - github.com/danieljoos/wincred v1.1.2 // indirect + github.com/danieljoos/wincred v1.2.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlmiddlecote/sqlstats v1.0.2 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -78,14 +78,15 @@ require ( github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/go-control-plane v0.11.1 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/exaring/otelpgx v0.5.2 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-errors/errors v1.5.1 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zerologr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -108,13 +109,13 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-memdb v1.3.4 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -129,7 +130,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.6 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lthibault/jitterbug v2.0.0+incompatible // indirect @@ -138,8 +139,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -152,15 +152,16 @@ require ( github.com/ngrok/sqlmw v0.0.0-20220520173518-97c9c04efc79 // indirect github.com/outcaste-io/ristretto v0.2.3 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/planetscale/vtprotobuf v0.6.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/common v0.46.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/rs/cors v1.10.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -170,38 +171,38 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/viper v1.18.1 // indirect + github.com/spf13/viper v1.18.2 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.20.0 // indirect go.opentelemetry.io/contrib/propagators/ot v1.20.0 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel v1.23.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/sdk v1.20.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.23.1 // indirect + go.opentelemetry.io/otel/sdk v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.23.1 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.153.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + google.golang.org/api v0.160.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -211,7 +212,7 @@ require ( k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect - resenje.org/singleflight v0.4.0 // indirect + resenje.org/singleflight v0.4.1 // indirect sigs.k8s.io/controller-runtime v0.16.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect diff --git a/go.sum b/go.sum index 7d1db74e..ee7b6c98 100644 --- a/go.sum +++ b/go.sum @@ -17,30 +17,30 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= -cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= -cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= -cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/spanner v1.53.0 h1:/NzWQJ1MEhdRcffiutRKbW/AIGVKhcTeivWTDjEyCCo= -cloud.google.com/go/spanner v1.53.0/go.mod h1:liG4iCeLqm5L3fFLU5whFITqP0e0orsAW1uUSrd4rws= +cloud.google.com/go/spanner v1.56.0 h1:o/Cv7/zZ1WgRXVCd5g3Nc23ZI39p/1pWFqFwvg6Wcu8= +cloud.google.com/go/spanner v1.56.0/go.mod h1:DndqtUKQAt3VLuV2Le+9Y3WTnq5cNKrnLb/Piqcj+h0= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -85,10 +85,10 @@ github.com/authzed/cel-go v0.17.5 h1:lfpkNrR99B5QRHg5qdG9oLu/kguVlZC68VJuMk8tH9Y github.com/authzed/cel-go v0.17.5/go.mod h1:XL/zEq5hKGVF8aOdMbG7w+BQPihLjY2W8N+UIygDA2I= github.com/authzed/consistent v0.1.0 h1:tlh1wvKoRbjRhMm2P+X5WQQyR54SRoS4MyjLOg17Mp8= github.com/authzed/consistent v0.1.0/go.mod h1:plwHlrN/EJUCwQ+Bca0MhM1KnisPs7HEkZI5giCXrcc= -github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403 h1:bQeIwWWRI9bl93poTqpix4sYHi+gnXUPK7N6bMtXzBE= -github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403/go.mod h1:s3qC7V7XIbiNWERv7Lfljy/Lx25/V1Qlexb0WJuA8uQ= -github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da h1:eH0+PGHu6A3S3OYsIG7kNu5VLeUHdcPsZOk92rGPn30= -github.com/authzed/spicedb v1.28.1-0.20231208003000-90be4e6762da/go.mod h1:U5rAjDSuv3Vk6vQKHCaUrL+UZrH2A16KNzpzxKQuE1Y= +github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b h1:wbh8IK+aMLTCey9sZasO7b6BWLAJnHHvb79fvWCXwxw= +github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b/go.mod h1:s3qC7V7XIbiNWERv7Lfljy/Lx25/V1Qlexb0WJuA8uQ= +github.com/authzed/spicedb v1.29.1 h1:EjWpUB7FD45NjZ8tTtdHGvGuzs/amvCwRGDDi0ASLCM= +github.com/authzed/spicedb v1.29.1/go.mod h1:f/PzNHQ7k1dN/pIWTH+LkE14cfBhZ6DYcC70bJc8A7M= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -98,8 +98,9 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bloom/v3 v3.6.0 h1:dTU0OVLJSoOhz9m68FTXMFfA39nR8U/nTCs1zb26mOI= github.com/bits-and-blooms/bloom/v3 v3.6.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg= github.com/brianvoe/gofakeit/v6 v6.26.3 h1:3ljYrjPwsUNAUFdUIr2jVg5EhKdcke/ZLop7uVg1Er8= @@ -127,8 +128,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -141,8 +142,8 @@ github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdB github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= github.com/dalzilio/rudd v1.1.1-0.20230806153452-9e08a6ea8170 h1:bHEN1z3EOO/IXHTQ8ZcmGoW4gTJt+mSrH2Sd458uo0E= github.com/dalzilio/rudd v1.1.1-0.20230806153452-9e08a6ea8170/go.mod h1:IxPC4Bdi3WqUwyGBMgLrWWGx67aRtUAZmOZrkIr7qaM= -github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= -github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= +github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -176,8 +177,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= @@ -194,6 +195,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -210,8 +213,8 @@ github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNV github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= @@ -236,8 +239,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -286,7 +287,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v43 v43.0.0 h1:y+GL7LIsAIF2NZlJ46ZoC/D1W1ivZasT0lnWHMYPZ+U= @@ -313,8 +313,8 @@ github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -329,12 +329,12 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/hamba/avro/v2 v2.18.0 h1:U7T0xI8MGw9+m3SS48E2KHUxas/Hb0EvS0CpkmVcLoI= -github.com/hamba/avro/v2 v2.18.0/go.mod h1:dEG+AHrykTpkXvBYsc+XXTuRlvGC645Ix5d2qR8EdEs= +github.com/hamba/avro/v2 v2.19.0 h1:jITwvb03UMLfTFHFKdvaMyU/G96iVWS5EiMsqo3flfE= +github.com/hamba/avro/v2 v2.19.0/go.mod h1:72DkWmMmAyZA+qHoI89u4RMCQ3X54vpEb1ap80iCIBg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -349,8 +349,9 @@ github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCS github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= @@ -400,8 +401,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= +github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -440,10 +441,9 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -493,12 +493,14 @@ github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOv github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA= +github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= 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= @@ -510,8 +512,8 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= 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= @@ -526,8 +528,8 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9 github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= +github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= @@ -541,18 +543,19 @@ github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4= -github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rodaine/table v1.1.1 h1:zBliy3b4Oj6JRmncse2Z85WmoQvDrXOYuy0JXCt8Qz8= +github.com/rodaine/table v1.1.1/go.mod h1:iqTRptjn+EVcrVBYtNMlJ2wrJZa3MpULUmcXFpfcziA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= @@ -583,8 +586,8 @@ github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.1 h1:rmuU42rScKWlhhJDyXZRKJQHXFX02chSVW1IvkPGiVM= -github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -617,8 +620,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= -github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -632,28 +635,28 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 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.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 h1:1eHu3/pUSWaOgltNK3WJFaywKsTIr/PwvHyDmi0lQA0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0/go.mod h1:HyABWq60Uy1kjJSa2BVOxUVao8Cdick5AWSKPutqy6U= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= go.opentelemetry.io/contrib/propagators/b3 v1.20.0 h1:Yty9Vs4F3D6/liF1o6FNt0PvN85h/BJJ6DQKJ3nrcM0= go.opentelemetry.io/contrib/propagators/b3 v1.20.0/go.mod h1:On4VgbkqYL18kbJlWsa18+cMNe6rYpBnPi1ARI/BrsU= go.opentelemetry.io/contrib/propagators/ot v1.20.0 h1:duH7mgL6VGQH7e7QEAVOFkCQXWpCb4PjTtrhdrYrJRQ= go.opentelemetry.io/contrib/propagators/ot v1.20.0/go.mod h1:gijQzxOq0JLj9lyZhTvqjDddGV/zaNagpPIn+2r8CEI= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= +go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM= -go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= +go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= +go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -676,8 +679,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -689,8 +692,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8= -golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo= +golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -712,8 +715,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -749,8 +752,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -758,8 +761,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -772,8 +775,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -813,7 +816,6 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -825,13 +827,13 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -839,6 +841,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= @@ -892,14 +895,14 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca h1:PupagGYwj8+I4ubCxcmcBRk3VlUWtTg5huQpZR9flmE= @@ -921,16 +924,16 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= -google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.160.0 h1:SEspjXHVqE1m5a1fRy8JFB+5jSu+V0GEDKDghF3ttO4= +google.golang.org/api v0.160.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= 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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -961,12 +964,12 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 h1:FSL3lRCkhaPFxqi0s9o+V4UI2WTzAVOvkgbd4kVV4Wg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -980,8 +983,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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= @@ -996,8 +999,9 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1045,8 +1049,8 @@ k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5Ohx k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -resenje.org/singleflight v0.4.0 h1:NdOEhCxEikK2S2WxGjZV9EGSsItolQKslOOi6pE1tJc= -resenje.org/singleflight v0.4.0/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk= +resenje.org/singleflight v0.4.1 h1:ryGHRaOBwhnZLyf34LMDf4AsTSHrs4hdGPdG/I4Hmac= +resenje.org/singleflight v0.4.1/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index 0117a65a..7956763c 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -173,7 +173,11 @@ func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) return schema, nil } - compiledSchema, err := compiler.Compile(compiler.InputSchema{Source: "schema", SchemaString: schema}, compiler.SkipValidation()) + compiledSchema, err := compiler.Compile( + compiler.InputSchema{Source: "schema", SchemaString: schema}, + compiler.AllowUnprefixedObjectType(), + compiler.SkipValidation(), + ) if err != nil { return "", fmt.Errorf("error reading schema: %w", err) } @@ -200,7 +204,10 @@ func filterSchemaDefs(schema, prefix string) (filteredSchema string, err error) } // Validate that the type system for the generated schema is comprehensive. - compiledFilteredSchema, err := compiler.Compile(compiler.InputSchema{Source: "generated-schema", SchemaString: filteredSchema}) + compiledFilteredSchema, err := compiler.Compile( + compiler.InputSchema{Source: "generated-schema", SchemaString: filteredSchema}, + compiler.AllowUnprefixedObjectType(), + ) if err != nil { return "", fmt.Errorf("generated invalid schema: %w", err) } diff --git a/internal/cmd/schema.go b/internal/cmd/schema.go index 9892f07b..0529aa67 100644 --- a/internal/cmd/schema.go +++ b/internal/cmd/schema.go @@ -187,9 +187,11 @@ func rewriteSchema(existingSchemaText string, definitionPrefix string) (string, return existingSchemaText, nil } - compiled, err := compiler.Compile(compiler.InputSchema{ - Source: input.Source("schema"), SchemaString: existingSchemaText, - }, compiler.ObjectTypePrefix(&definitionPrefix), compiler.SkipValidation()) + compiled, err := compiler.Compile( + compiler.InputSchema{Source: input.Source("schema"), SchemaString: existingSchemaText}, + compiler.ObjectTypePrefix(definitionPrefix), + compiler.SkipValidation(), + ) if err != nil { return "", err } @@ -225,9 +227,11 @@ func determinePrefixForSchema(ctx context.Context, specifiedPrefix string, clien } // Otherwise, compile the schema and grab the prefixes of the namespaces defined. - found, err := compiler.Compile(compiler.InputSchema{ - Source: input.Source("schema"), SchemaString: schemaText, - }, compiler.SkipValidation()) + found, err := compiler.Compile( + compiler.InputSchema{Source: input.Source("schema"), SchemaString: schemaText}, + compiler.AllowUnprefixedObjectType(), + compiler.SkipValidation(), + ) if err != nil { return "", err } diff --git a/internal/commands/completion.go b/internal/commands/completion.go index 8e4504e3..85ced363 100644 --- a/internal/commands/completion.go +++ b/internal/commands/completion.go @@ -151,7 +151,11 @@ func readSchema(cmd *cobra.Command) (*compiler.CompiledSchema, error) { return nil, errors.New("no schema defined") } - compiledSchema, err := compiler.Compile(compiler.InputSchema{Source: "schema", SchemaString: schemaText}, compiler.SkipValidation()) + compiledSchema, err := compiler.Compile( + compiler.InputSchema{Source: "schema", SchemaString: schemaText}, + compiler.AllowUnprefixedObjectType(), + compiler.SkipValidation(), + ) if err != nil { return nil, err } diff --git a/internal/decode/decoder.go b/internal/decode/decoder.go index 241615b9..ac6abbbc 100644 --- a/internal/decode/decoder.go +++ b/internal/decode/decoder.go @@ -109,8 +109,9 @@ func unmarshalAsYAMLOrSchema(data []byte, out interface{}) (bool, error) { // Check for indications of a schema-only file. if !strings.Contains(string(data), "schema:") { compiled, serr := compiler.Compile(compiler.InputSchema{ - Source: input.Source("schema"), SchemaString: string(data), - }) + Source: input.Source("schema"), + SchemaString: string(data), + }, compiler.AllowUnprefixedObjectType()) if serr != nil { return false, serr } diff --git a/pkg/backupformat/redaction.go b/pkg/backupformat/redaction.go index 6f331505..c3b875db 100644 --- a/pkg/backupformat/redaction.go +++ b/pkg/backupformat/redaction.go @@ -132,8 +132,9 @@ func (r *Redactor) Close() error { func redactSchema(schema string, opts RedactionOptions) (string, RedactionMap, error) { // Parse the schema. compiled, err := compiler.Compile(compiler.InputSchema{ - Source: input.Source("schema"), SchemaString: schema, - }) + Source: input.Source("schema"), + SchemaString: schema, + }, compiler.AllowUnprefixedObjectType()) if err != nil { return "", RedactionMap{}, err } From c43b9f9dbc79434a8bf4bb8f33de453bf81618b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:01:47 +0000 Subject: [PATCH 47/49] build(deps): bump github.com/hamba/avro/v2 from 2.19.0 to 2.20.0 Bumps [github.com/hamba/avro/v2](https://github.com/hamba/avro) from 2.19.0 to 2.20.0. - [Release notes](https://github.com/hamba/avro/releases) - [Commits](https://github.com/hamba/avro/compare/v2.19.0...v2.20.0) --- updated-dependencies: - dependency-name: github.com/hamba/avro/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 211f5ac9..33e52bff 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/charmbracelet/lipgloss v0.9.1 github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 - github.com/hamba/avro/v2 v2.19.0 + github.com/hamba/avro/v2 v2.20.0 github.com/jzelinskie/cobrautil/v2 v2.0.0-20231016191810-9f8a4f6d038a github.com/jzelinskie/stringz v0.0.3 github.com/mattn/go-isatty v0.0.20 diff --git a/go.sum b/go.sum index ee7b6c98..d2fc990b 100644 --- a/go.sum +++ b/go.sum @@ -333,8 +333,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0Q github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/hamba/avro/v2 v2.19.0 h1:jITwvb03UMLfTFHFKdvaMyU/G96iVWS5EiMsqo3flfE= -github.com/hamba/avro/v2 v2.19.0/go.mod h1:72DkWmMmAyZA+qHoI89u4RMCQ3X54vpEb1ap80iCIBg= +github.com/hamba/avro/v2 v2.20.0 h1:zTOh3qAwt1ahUU6Rq99EP1Ek24abSzMW8aTbyhdIpHM= +github.com/hamba/avro/v2 v2.20.0/go.mod h1:mp3l5/S+XRRTIz/dscaZprFxWLMBWbcjxw0PqL+6wng= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= From 0f37192691dee1e629ebda3acc04b8f571faf151 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:01:54 +0000 Subject: [PATCH 48/49] build(deps): bump github.com/brianvoe/gofakeit/v6 from 6.26.3 to 6.28.0 Bumps [github.com/brianvoe/gofakeit/v6](https://github.com/brianvoe/gofakeit) from 6.26.3 to 6.28.0. - [Release notes](https://github.com/brianvoe/gofakeit/releases) - [Commits](https://github.com/brianvoe/gofakeit/compare/v6.26.3...v6.28.0) --- updated-dependencies: - dependency-name: github.com/brianvoe/gofakeit/v6 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 211f5ac9..cb8d9df7 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/authzed/authzed-go v0.10.1 github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b github.com/authzed/spicedb v1.29.1 - github.com/brianvoe/gofakeit/v6 v6.26.3 + github.com/brianvoe/gofakeit/v6 v6.28.0 github.com/cenkalti/backoff/v4 v4.2.1 github.com/charmbracelet/lipgloss v0.9.1 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index ee7b6c98..be521007 100644 --- a/go.sum +++ b/go.sum @@ -103,8 +103,8 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bloom/v3 v3.6.0 h1:dTU0OVLJSoOhz9m68FTXMFfA39nR8U/nTCs1zb26mOI= github.com/bits-and-blooms/bloom/v3 v3.6.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg= -github.com/brianvoe/gofakeit/v6 v6.26.3 h1:3ljYrjPwsUNAUFdUIr2jVg5EhKdcke/ZLop7uVg1Er8= -github.com/brianvoe/gofakeit/v6 v6.26.3/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= +github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= +github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= From fae4a369a4939149452f3277c5fd95c48b29bb72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:03:08 +0000 Subject: [PATCH 49/49] build(deps): bump google.golang.org/grpc from 1.61.0 to 1.61.1 Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.61.0 to 1.61.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.61.0...v1.61.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 211f5ac9..9918423e 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( golang.org/x/mod v0.15.0 golang.org/x/sync v0.6.0 golang.org/x/term v0.17.0 - google.golang.org/grpc v1.61.0 + google.golang.org/grpc v1.61.1 google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index ee7b6c98..2e500ca9 100644 --- a/go.sum +++ b/go.sum @@ -983,8 +983,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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=