pax_global_header00006660000000000000000000000064147535324200014517gustar00rootroot0000000000000052 comment=813e102555445d3677dcf99c21be4c6de6fce0ce prometheus-nextcloud-exporter-0.8.0/000077500000000000000000000000001475353242000175705ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/.bingo/000077500000000000000000000000001475353242000207445ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/.bingo/.gitignore000066400000000000000000000001731475353242000227350ustar00rootroot00000000000000 # Ignore everything * # But not these files: !.gitignore !*.mod !*.sum !README.md !Variables.mk !variables.env *tmp.mod prometheus-nextcloud-exporter-0.8.0/.bingo/README.md000066400000000000000000000014641475353242000222300ustar00rootroot00000000000000# Project Development Dependencies. This is directory which stores Go modules with pinned buildable package that is used within this repository, managed by https://github.com/bwplotka/bingo. * Run `bingo get` to install all tools having each own module file in this directory. * Run `bingo get ` to install that have own module file in this directory. * For Makefile: Make sure to put `include .bingo/Variables.mk` in your Makefile, then use $() variable where is the .bingo/.mod. * For shell: Run `source .bingo/variables.env` to source all environment variable for each tool. * For go: Import `.bingo/variables.go` to for variable names. * See https://github.com/bwplotka/bingo or -h on how to add, remove or change binaries dependencies. ## Requirements * Go 1.14+ prometheus-nextcloud-exporter-0.8.0/.bingo/Variables.mk000066400000000000000000000030011475353242000231770ustar00rootroot00000000000000# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.9. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. BINGO_DIR := $(dir $(lastword $(MAKEFILE_LIST))) GOPATH ?= $(shell go env GOPATH) GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin GO ?= $(shell which go) # Below generated variables ensure that every time a tool under each variable is invoked, the correct version # will be used; reinstalling only if needed. # For example for bingo variable: # # In your main Makefile (for non array binaries): # #include .bingo/Variables.mk # Assuming -dir was set to .bingo . # #command: $(BINGO) # @echo "Running bingo" # @$(BINGO) # BINGO := $(GOBIN)/bingo-v0.9.0 $(BINGO): $(BINGO_DIR)/bingo.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. @echo "(re)installing $(GOBIN)/bingo-v0.9.0" @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=bingo.mod -o=$(GOBIN)/bingo-v0.9.0 "github.com/bwplotka/bingo" GOLANGCI_LINT := $(GOBIN)/golangci-lint-v1.62.2 $(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. @echo "(re)installing $(GOBIN)/golangci-lint-v1.62.2" @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.62.2 "github.com/golangci/golangci-lint/cmd/golangci-lint" prometheus-nextcloud-exporter-0.8.0/.bingo/bingo.mod000066400000000000000000000002001475353242000225330ustar00rootroot00000000000000module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.20 require github.com/bwplotka/bingo v0.9.0 prometheus-nextcloud-exporter-0.8.0/.bingo/bingo.sum000066400000000000000000000132331475353242000225720ustar00rootroot00000000000000github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/bwplotka/bingo v0.8.0 h1:Cx9eQb+ed9aU7sbrmZagomKx+wYor9y5z5HM91bvp1U= github.com/bwplotka/bingo v0.8.0/go.mod h1:eXPFwhZ92mmOUBk6F7aKcAJoq8HX88Ju3wLZKwtNKEw= github.com/bwplotka/bingo v0.9.0 h1:slnsdJYExR4iRalHR6/ZiYnr9vSazOuFGmc2LdX293g= github.com/bwplotka/bingo v0.9.0/go.mod h1:GxC/y/xbmOK5P29cn+B3HuOSw0s2gruddT3r+rDizDw= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.15/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/efficientgo/core v1.0.0-rc.0 h1:jJoA0N+C4/knWYVZ6GrdHOtDyrg8Y/TR4vFpTaqTsqs= github.com/efficientgo/core v1.0.0-rc.0/go.mod h1:kQa0V74HNYMfuJH6jiPiwNdpWXl4xd/K4tzlrcvYDQI= github.com/frankban/quicktest v1.13.1/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1-0.20210923151022-86f73c517451/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210925032602-92d5a993a665/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210916214954-140adaaadfaf/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0= mvdan.cc/sh/v3 v3.4.3 h1:zbuKH7YH9cqU6PGajhFFXZY7dhPXcDr55iN/cUAqpuw= mvdan.cc/sh/v3 v3.4.3/go.mod h1:p/tqPPI4Epfk2rICAe2RoaNd8HBSJ8t9Y2DA9yQlbzY= mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg= mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8= prometheus-nextcloud-exporter-0.8.0/.bingo/go.mod000066400000000000000000000002241475353242000220500ustar00rootroot00000000000000module _ // Fake go.mod auto-created by 'bingo' for go -moddir compatibility with non-Go projects. Commit this file, together with other .mod files.prometheus-nextcloud-exporter-0.8.0/.bingo/golangci-lint.mod000066400000000000000000000002641475353242000241760ustar00rootroot00000000000000module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.22.1 toolchain go1.23.4 require github.com/golangci/golangci-lint v1.62.2 // cmd/golangci-lint prometheus-nextcloud-exporter-0.8.0/.bingo/golangci-lint.sum000066400000000000000000003543141475353242000242330ustar00rootroot000000000000004d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= 4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= 4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= 4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= 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/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/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/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/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= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/4meepo/tagalign v1.3.3 h1:ZsOxcwGD/jP4U/aw7qeWu58i7dwYemfy5Y+IF1ACoNw= github.com/4meepo/tagalign v1.3.3/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= github.com/4meepo/tagalign v1.3.4 h1:P51VcvBnf04YkHzjfclN6BbsopfJR5rxs1n+5zHt+w8= github.com/4meepo/tagalign v1.3.4/go.mod h1:M+pnkHH2vG8+qhE5bVc/zeP7HS/j910Fwa9TUSyZVI0= github.com/Abirdcfly/dupword v0.0.11 h1:z6v8rMETchZXUIuHxYNmlUAuKuB21PeaSymTed16wgU= github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= github.com/Abirdcfly/dupword v0.0.13 h1:SMS17YXypwP000fA7Lr+kfyBQyW14tTT+nRv9ASwUUo= github.com/Abirdcfly/dupword v0.0.13/go.mod h1:Ut6Ue2KgF/kCOawpW4LnExT+xZLQviJPE4klBPMK/5Y= github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= github.com/Antonboom/errname v0.1.9 h1:BZDX4r3l4TBZxZ2o2LNrlGxSHran4d1u4veZdoORTT4= github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= github.com/Antonboom/errname v0.1.12 h1:oh9ak2zUtsLp5oaEd/erjB4GPu9w19NyoIskZClDcQY= github.com/Antonboom/errname v0.1.12/go.mod h1:bK7todrzvlaZoQagP1orKzWXv59X/x0W0Io2XT1Ssro= github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= github.com/Antonboom/nilnil v0.1.3 h1:6RTbx3d2mcEu3Zwq9TowQpQMVpP75zugwOtqY1RTtcE= github.com/Antonboom/nilnil v0.1.3/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= github.com/Antonboom/nilnil v0.1.7 h1:ofgL+BA7vlA1K2wNQOsHzLJ2Pw5B5DpWRLdDAVvvTow= github.com/Antonboom/nilnil v0.1.7/go.mod h1:TP+ScQWVEq0eSIxqU8CbdT5DFWoHp0MbP+KMUO1BKYQ= github.com/Antonboom/nilnil v1.0.0 h1:n+v+B12dsE5tbAqRODXmEKfZv9j2KcTBrp+LkoM4HZk= github.com/Antonboom/nilnil v1.0.0/go.mod h1:fDJ1FSFoLN6yoG65ANb1WihItf6qt9PJVTn/s2IrcII= github.com/Antonboom/testifylint v1.1.2 h1:IdLRermiLRogxY5AumBL4sP0A+qKHQM/AP1Xd7XOTKc= github.com/Antonboom/testifylint v1.1.2/go.mod h1:9PFi+vWa8zzl4/B/kqmFJcw85ZUv8ReyBzuQCd30+WI= github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Crocmagnon/fatcontext v0.5.3 h1:zCh/wjc9oyeF+Gmp+V60wetm8ph2tlsxocgg/J0hOps= github.com/Crocmagnon/fatcontext v0.5.3/go.mod h1:XoCQYY1J+XTfyv74qLXvNw4xFunr3L1wkopIIKG7wGM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 h1:sATXp1x6/axKxz2Gjxv8MALP0bXaNRfQinEwyfMcx8c= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0/go.mod h1:Nl76DrGNJTA1KJ0LePKBw/vznBX1EHbAZX8mwjR82nI= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU= github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= github.com/alecthomas/go-check-sumtype v0.1.4 h1:WCvlB3l5Vq5dZQTFmodqL2g68uHiSwwlWcT5a2FGK0c= github.com/alecthomas/go-check-sumtype v0.1.4/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= github.com/alecthomas/go-check-sumtype v0.2.0 h1:Bo+e4DFf3rs7ME9w/0SU/g6nmzJaphduP8Cjiz0gbwY= github.com/alecthomas/go-check-sumtype v0.2.0/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= 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/alexkohler/nakedret/v2 v2.0.2 h1:qnXuZNvv3/AxkAb22q/sEsEpcA99YxLFACDtEw9TPxE= github.com/alexkohler/nakedret/v2 v2.0.2/go.mod h1:2b8Gkk0GsOrqQv/gPWjNLDSKwG8I5moSXG1K4VIBcTQ= github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/ashanbrown/forbidigo v1.5.1 h1:WXhzLjOlnuDYPYQo/eFlcFMi8X/kLfvWLYu6CSoebis= github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= 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/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/bkielbasa/cyclop v1.2.1 h1:AeF71HZDob1P2/pRm1so9cd1alZnrpyc4q2uP2l0gJY= github.com/bkielbasa/cyclop v1.2.1/go.mod h1:K/dT/M0FPAiYjBgQGau7tz+3TMh4FWAEqlMhzFWCrgM= github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= github.com/bombsimon/wsl/v4 v4.2.1 h1:Cxg6u+XDWff75SIFFmNsqnIOgob+Q9hG6y/ioKbRFiM= github.com/bombsimon/wsl/v4 v4.2.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= github.com/bombsimon/wsl/v4 v4.4.1 h1:jfUaCkN+aUpobrMO24zwyAMwMAV5eSziCkOKEauOLdw= github.com/bombsimon/wsl/v4 v4.4.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY= github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ= github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA= github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U= github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0= github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA= github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= github.com/butuzov/mirror v1.2.0 h1:9YVK1qIjNspaqWutSv8gsge2e/Xpq1eqEkslEUHy5cs= github.com/butuzov/mirror v1.2.0/go.mod h1:DqZZDtzm42wIAIyHXeN8W/qb1EPlb9Qn/if9icBOpdQ= github.com/catenacyber/perfsprint v0.6.0 h1:VSv95RRkk5+BxrU/YTPcnxuMEWar1iMK5Vyh3fWcBfs= github.com/catenacyber/perfsprint v0.6.0/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc= github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= 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/ckaznocha/intrange v0.2.1 h1:M07spnNEQoALOJhwrImSrJLaxwuiQK+hA2DeajBlwYk= github.com/ckaznocha/intrange v0.2.1/go.mod h1:7NEhVyf8fzZO5Ds7CRaqPEm52Ut83hsTiL5zbER/HYk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/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/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/daixiang0/gci v0.10.1 h1:eheNA3ljF6SxnPD/vE4lCBusVHmV3Rs3dkKvFrJ7MR0= github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= github.com/daixiang0/gci v0.12.1 h1:ugsG+KRYny1VK4oqrX4Vtj70bo4akYKa0tgT1DXMYiY= github.com/daixiang0/gci v0.12.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= 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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= 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/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghostiam/protogetter v0.3.4 h1:5SZ+lZSNmNkSbGVSF9hUHhv/b7ELF9Rwchoq7btYo6c= github.com/ghostiam/protogetter v0.3.4/go.mod h1:A0JgIhs0fgVnotGinjQiKaFVG3waItLJNwPmcMzDnvk= github.com/ghostiam/protogetter v0.3.8 h1:LYcXbYvybUyTIxN2Mj9h6rHrDZBDwZloPoKctWrFyJY= github.com/ghostiam/protogetter v0.3.8/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= github.com/go-critic/go-critic v0.7.0 h1:tqbKzB8pqi0NsRZ+1pyU4aweAF7A7QN0Pi4Q02+rYnQ= github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64= github.com/go-critic/go-critic v0.11.1 h1:/zBseUSUMytnRqxjlsYNbDDxpu3R2yH8oLXo/FOE8b8= github.com/go-critic/go-critic v0.11.1/go.mod h1:aZVQR7+gazH6aDEQx4356SD7d8ez8MipYjXbEl5JAKA= github.com/go-critic/go-critic v0.11.5 h1:TkDTOn5v7EEngMxu8KbuFqFR43USaaH8XRJLz1jhVYA= github.com/go-critic/go-critic v0.11.5/go.mod h1:wu6U7ny9PiaHaZHcvMDmdysMqvDem162Rh3zWTrqk8M= 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-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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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/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 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 h1:/1322Qns6BtQxUZDTAT4SdcoxknUki7IAoK4SAXr8ME= github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9/go.mod h1:Oesb/0uFAyWoaw1U1qS5zyjCg5NP9C9iwjnI4tIsXEE= github.com/golangci/golangci-lint v1.52.2 h1:FrPElUUI5rrHXg1mQ7KxI1MXPAw5lBVskiz7U7a8a1A= github.com/golangci/golangci-lint v1.52.2/go.mod h1:S5fhC5sHM5kE22/HcATKd1XLWQxX+y7mHj8B5H91Q/0= github.com/golangci/golangci-lint v1.56.2 h1:dgQzlWHgNbCqJjuxRJhFEnHDVrrjuTGQHJ3RIZMpp/o= github.com/golangci/golangci-lint v1.56.2/go.mod h1:7CfNO675+EY7j84jihO4iAqDQ80s3HCjcc5M6B7SlZQ= github.com/golangci/golangci-lint v1.62.2 h1:b8K5K9PN+rZN1+mKLtsZHz2XXS9aYKzQ9i25x3Qnxxw= github.com/golangci/golangci-lint v1.62.2/go.mod h1:ILWWyeFUrctpHVGMa1dg2xZPKoMUTc5OIMgW7HZr34g= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= github.com/golangci/misspell v0.4.1 h1:+y73iSicVy2PqyX7kmUefHusENlrP9YwuHZHPLGQj/g= github.com/golangci/misspell v0.4.1/go.mod h1:9mAN1quEo3DlpbaIKKyEvRxK1pwqR9s/Sea1bJCtlNI= github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= github.com/golangci/modinfo v0.3.4 h1:oU5huX3fbxqQXdfspamej74DFX0kyGLkw1ppvXoJ8GA= github.com/golangci/modinfo v0.3.4/go.mod h1:wytF1M5xl9u0ij8YSvhkEVPP3M5Mc7XLl1pxH3B2aUM= github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= github.com/golangci/revgrep v0.5.2 h1:EndcWoRhcnfj2NHQ+28hyuXpLMF+dQmCN+YaeeIl4FU= github.com/golangci/revgrep v0.5.2/go.mod h1:bjAMA+Sh/QUfTDcHzxfyHxr4xKvllVr/0sCv2e7jJHA= github.com/golangci/revgrep v0.5.3 h1:3tL7c1XBMtWHHqVpS5ChmiAAoe4PF/d5+ULzV9sLAzs= github.com/golangci/revgrep v0.5.3/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= 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/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.5.6/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 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 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/gofuzz v1.0.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/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= 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/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= 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.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jgautheron/goconst v1.7.0 h1:cEqH+YBKLsECnRSd4F4TK5ri8t/aXtt/qoL0Ft252B0= github.com/jgautheron/goconst v1.7.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jjti/go-spancheck v0.5.2 h1:WXTZG3efY/ji1Vi8mkH+23O3bLeKR6hp3tI3YB7XwKk= github.com/jjti/go-spancheck v0.5.2/go.mod h1:ARPNI1JRG1V2Rjnd6/2f2NEfghjSVDZGVmruNKlnXU0= github.com/jjti/go-spancheck v0.6.2 h1:iYtoxqPMzHUPp7St+5yA8+cONdyXD3ug6KK15n7Pklk= github.com/jjti/go-spancheck v0.6.2/go.mod h1:+X7lvIrR5ZdUTkxFYqzJ0abr8Sb5LOo80uOhWNqIrYA= 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.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/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/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/junk1tm/musttag v0.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= github.com/karamaru-alpha/copyloopvar v1.1.0 h1:x7gNyKcC2vRBO1H2Mks5u1VxQtYvFiym7fCjIP8RPos= github.com/karamaru-alpha/copyloopvar v1.1.0/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k= github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0= github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg= github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA= 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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= github.com/kunwardeep/paralleltest v1.0.9 h1:3Sr2IfFNcsMmlqPk1cjTUbJ4zofKPGyHxenwPebgTug= github.com/kunwardeep/paralleltest v1.0.9/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/gomoddirectives v0.2.4 h1:j3YjBIjEBbqZ0NKtBNzr8rtMHTOrLPeiwTkfUJZ3alg= github.com/ldez/gomoddirectives v0.2.4/go.mod h1:oWu9i62VcQDYp9EQ0ONTfqLNh+mDLWWDO+SO0qSQw5g= github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mgechev/revive v1.3.1 h1:OlQkcH40IB2cGuprTPcjB0iIUddgVZgGmDX3IAMR8D4= github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= github.com/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE= github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA= github.com/mgechev/revive v1.5.1 h1:hE+QPeq0/wIzJwOphdVyUJ82njdd8Khp4fUIHGZHW3M= github.com/mgechev/revive v1.5.1/go.mod h1:lC9AhkJIBs5zwx8wkudyHrU+IJkrEKmpCmGMnIJPk4o= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= 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/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.9.0 h1:Sm0zX5QfjJzkeCjEp+t6d3Ha0jwvoDjleP9XCsrEzOA= github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= github.com/nunnatsa/ginkgolinter v0.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1oBKBNHg= github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc= github.com/nunnatsa/ginkgolinter v0.18.3 h1:WgS7X3zzmni3vwHSBhvSgqrRgUecN6PQUcfB0j1noDw= github.com/nunnatsa/ginkgolinter v0.18.3/go.mod h1:BE1xyB/PNtXXG1azrvrqJW5eFH0hSRylNzFy8QHPwzs= 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/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= 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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polyfloyd/go-errorlint v1.4.0 h1:b+sQ5HibPIAjEZwtuwU8Wz/u0dMZ7YL+bk+9yWyHVJk= github.com/polyfloyd/go-errorlint v1.4.0/go.mod h1:qJCkPeBn+0EXkdKTrUCcuFStM2xrDKfxI3MGLXPexUs= github.com/polyfloyd/go-errorlint v1.4.8 h1:jiEjKDH33ouFktyez7sckv6pHWif9B7SuS8cutDXFHw= github.com/polyfloyd/go-errorlint v1.4.8/go.mod h1:NNCxFcFjZcw3xNjVdCchERkEM6Oz7wta2XJVxRftwO4= github.com/polyfloyd/go-errorlint v1.7.0 h1:Zp6lzCK4hpBDj8y8a237YK4EPrMXQWvOe3nGoH4pFrU= github.com/polyfloyd/go-errorlint v1.7.0/go.mod h1:dGWKu85mGHnegQ2SWpEybFityCg3j7ZbwsVUxAOk9gY= 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.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 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= 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.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= 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.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 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= github.com/quasilyte/go-ruleguard v0.4.0 h1:DyM6r+TKL+xbKB4Nm7Afd1IQh9kEUKQs2pboWGKtvQo= github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/raeperd/recvcheck v0.1.2 h1:SjdquRsRXJc26eSonWIo8b7IMtKD3OAT2Lb5G3ZX1+4= github.com/raeperd/recvcheck v0.1.2/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= github.com/sashamelentyev/usestdlibvars v1.25.0 h1:IK8SI2QyFzy/2OD2PYnhy84dpfNo9qADrRt6LH8vSzU= github.com/sashamelentyev/usestdlibvars v1.25.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= github.com/sashamelentyev/usestdlibvars v1.27.0 h1:t/3jZpSXtRPRf2xr0m63i32ZrusyurIGT9E5wAvXQnI= github.com/sashamelentyev/usestdlibvars v1.27.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= github.com/securego/gosec/v2 v2.19.0 h1:gl5xMkOI0/E6Hxx0XCY2XujA3V7SNSefA8sC+3f1gnk= github.com/securego/gosec/v2 v2.19.0/go.mod h1:hOkDcHz9J/XIgIlPDXalxjeVYsHxoWUc5zJSHxcB8YM= github.com/securego/gosec/v2 v2.21.4 h1:Le8MSj0PDmOnHJgUATjD96PaXRvCpKC+DGJvwyy0Mlk= github.com/securego/gosec/v2 v2.21.4/go.mod h1:Jtb/MwRQfRxCXyCm1rfM1BEiiiTfUOdyzzAhlr6lUTA= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= 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.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= 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.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= 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/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 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.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= 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/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/tetafro/godot v1.4.16 h1:4ChfhveiNLk4NveAZ9Pu2AN8QZ2nkUGFuadM9lrr5D0= github.com/tetafro/godot v1.4.16/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= github.com/tetafro/godot v1.4.18 h1:ouX3XGiziKDypbpXqShBfnNLTSjR8r3/HVzrtJ+bHlI= github.com/tetafro/godot v1.4.18/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= github.com/tomarrell/wrapcheck/v2 v2.9.0 h1:801U2YCAjLhdN8zhZ/7tdjB3EnAoRlJHt/s+9hijLQ4= github.com/tomarrell/wrapcheck/v2 v2.9.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/ultraware/whitespace v0.1.0 h1:O1HKYoh0kIeqE8sFqZf1o0qbORXUCOQFrlaQyZsczZw= github.com/ultraware/whitespace v0.1.0/go.mod h1:/se4r3beMFNmewJ4Xmz0nMQ941GJt+qmSHGP9emHYe0= github.com/ultraware/whitespace v0.1.1 h1:bTPOGejYFulW3PkcrqkeQwOd6NKOOXvmGD9bo/Gk8VQ= github.com/ultraware/whitespace v0.1.1/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM= github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U= github.com/uudashr/iface v1.2.1 h1:vHHyzAUmWZ64Olq6NZT3vg/z1Ws56kyPdBOd5kTXDF8= github.com/uudashr/iface v1.2.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4= github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= 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.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4= gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/musttag v0.8.0 h1:DR4UTgetNNhPRNo02rkK1hwDTRzAPotN+ZqYpdtEwWc= go-simpler.org/musttag v0.8.0/go.mod h1:fiNdCkXt2S6je9Eblma3okjnlva9NT1Eg/WUt19rWu8= go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= go-simpler.org/sloglint v0.4.0 h1:UVJuUJo63iNQNFEOtZ6o1xAgagVg/giVLLvG9nNLobI= go-simpler.org/sloglint v0.4.0/go.mod h1:v6zJ++j/thFPhefs2wEXoCKwT10yo5nkBDYRCXyqgNQ= go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY= go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo= 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.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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-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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= 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-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 h1:J74nGeMgeFnYQJN59eFwh06jX/V8g0lB7LWpjSLxtgU= golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848 h1:UhRVJ0i7bF9n/Hd8YjW3eKjlPVBHzbQdxrBgjbSKl64= golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f h1:WTyX8eCCyfdqiPYkRGm0MqElSfYFH3yR1+rl/mct9sA= golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= 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/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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 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.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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-20210220032951-036812b2e83c/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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.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-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-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-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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/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-20220412211240-33da011f77ad/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-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 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.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.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.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/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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/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-20190321232350-e250d351ecad/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-20190910044552-dd2b5c81c578/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-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 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-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 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-20200820010801-b793a1359eac/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-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/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/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/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-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/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/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 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 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.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= 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= honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8= honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 h1:zCr3iRRgdk5eIikZNDphGcM6KGVTx3Yu+/Uu9Es254w= mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14/go.mod h1:ZzZjEpJDOmx8TdVU6umamY3Xy0UAQUI2DHbf05USVbI= mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= 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= prometheus-nextcloud-exporter-0.8.0/.bingo/variables.env000066400000000000000000000007011475353242000234240ustar00rootroot00000000000000# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.9. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. # Those variables will work only until 'bingo get' was invoked, or if tools were installed via Makefile's Variables.mk. GOBIN=${GOBIN:=$(go env GOBIN)} if [ -z "$GOBIN" ]; then GOBIN="$(go env GOPATH)/bin" fi BINGO="${GOBIN}/bingo-v0.9.0" GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.62.2" prometheus-nextcloud-exporter-0.8.0/.dockerignore000077700000000000000000000000001475353242000242272.gitignoreustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/.editorconfig000066400000000000000000000003661475353242000222520ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.md] trim_trailing_whitespace = false [*.go] indent_style = tab [Makefile] indent_style = tab prometheus-nextcloud-exporter-0.8.0/.github/000077500000000000000000000000001475353242000211305ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/.github/workflows/000077500000000000000000000000001475353242000231655ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/.github/workflows/package.yml000066400000000000000000000034031475353242000253030ustar00rootroot00000000000000name: Package on: push: branches: - master release: types: - published pull_request: branches: - master jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Go uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Build and Test run: make docker: needs: test runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 if: ${{ github.event_name != 'pull_request' }} with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker hub uses: docker/login-action@v3 if: ${{ github.event_name != 'pull_request' }} with: username: xperimental password: ${{ secrets.DOCKER_TOKEN }} - name: Docker Metadata id: meta uses: docker/metadata-action@v5 with: images: | ghcr.io/xperimental/nextcloud-exporter xperimental/nextcloud-exporter tags: | type=semver,pattern={{version}} type=ref,event=branch type=ref,event=pr - name: Build and push Docker images uses: docker/build-push-action@v5 with: context: . push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 prometheus-nextcloud-exporter-0.8.0/.github/workflows/pull-request.yml000066400000000000000000000005161475353242000263540ustar00rootroot00000000000000name: Pull-request on: pull_request: branches: - master jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: golangci-lint uses: golangci/golangci-lint-action@v4 with: version: v1.62.2 prometheus-nextcloud-exporter-0.8.0/.gitignore000066400000000000000000000001021475353242000215510ustar00rootroot00000000000000run.sh nextcloud-exporter nextcloud-exporter.yml config.yml dist/ prometheus-nextcloud-exporter-0.8.0/.golangci.yaml000066400000000000000000000000411475353242000223100ustar00rootroot00000000000000linters: enable: - gofumpt prometheus-nextcloud-exporter-0.8.0/CHANGELOG.md000066400000000000000000000060221475353242000214010ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [0.8.0] - 2024-12-22 ### Added - New metric showing available Nextcloud update (`nextcloud_system_update_available`) ### Changed - Updated Go runtime and dependencies ## [0.7.0] - 2024-03-21 ### Added - Example Grafana Dashboard now included in the repository ### Changed - App-related metrics (installed, available updates) are opt-in now, mirroring the change in Nextcloud 28 - Updates Go and dependencies ### Fixed - Error parsing "free space" reported by Nextcloud when number is very large ## [0.6.2] - 2023-10-15 ### Changed - Maintenance release, updates Go and dependencies ## [0.6.1] - 2023-05-29 ### Changed - `latest` Docker tag now points to most recent release and `master` points to the build from the default branch ## [0.6.0] - 2022-10-19 ### Added - New database info metric (`nextcloud_database_info`) containing type and version - New metrics for hourly and daily active users - Additional label on `nextcloud_scrape_errors_total` for errors due to rate-limiting - Additional labels for email and room shares on `nextcloud_shares_total` ## [0.5.1] - 2022-04-02 ### Fixed - Updated Prometheus client library for CVE-2022-21698 ## [0.5.0] - 2022-01-15 ### Added - Flag for showing version information - Option to disable TLS validation - Token authentication for Nextcloud 22 and newer ### Changed - Switched to JSON from XML for getting information from server - Use different metric for authentication errors ## [0.4.0] - 2021-01-21 ### Added - Metrics for installed apps and available updates ## [0.3.0] - 2020-06-01 ### Added - Makefile target for building deb - Login flow for app password ### Changed - Simpler configuration of server URL ### Fixed - Error in version information ## [0.2.0] - 2020-05-20 ### Added - Version information in binary - Custom User-Agent header - systemd service unit ### Changed - No timestamp in log output ## [0.1.0] - 2019-10-12 - Initial release [0.8.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.8.0 [0.7.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.7.0 [0.6.2]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.6.2 [0.6.1]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.6.1 [0.6.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.6.0 [0.5.1]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.5.1 [0.5.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.5.0 [0.4.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.4.0 [0.3.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.3.0 [0.2.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.2.0 [0.1.0]: https://github.com/xperimental/nextcloud-exporter/releases/tag/v0.1.0 prometheus-nextcloud-exporter-0.8.0/Dockerfile000066400000000000000000000011561475353242000215650ustar00rootroot00000000000000FROM --platform=$BUILDPLATFORM golang:1.23.4-alpine AS builder ARG TARGETOS ARG TARGETARCH ENV GOOS=$TARGETOS ENV GOARCH=$TARGETARCH RUN apk add --no-cache make git bash WORKDIR /build COPY go.mod go.sum /build/ RUN go mod download RUN go mod verify COPY . /build/ RUN make build-binary FROM --platform=$TARGETPLATFORM busybox LABEL maintainer="Robert Jacob " COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt COPY --from=builder /build/nextcloud-exporter /bin/nextcloud-exporter USER nobody EXPOSE 9205 ENTRYPOINT ["/bin/nextcloud-exporter"] prometheus-nextcloud-exporter-0.8.0/LICENSE000066400000000000000000000020671475353242000206020ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2017 Robert Jacob Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. prometheus-nextcloud-exporter-0.8.0/Makefile000066400000000000000000000026711475353242000212360ustar00rootroot00000000000000SHELL := /bin/bash GO ?= go GO_CMD := CGO_ENABLED=0 $(GO) GIT_VERSION := $(shell git describe --tags --dirty) VERSION := $(GIT_VERSION:v%=%) GIT_COMMIT := $(shell git rev-parse HEAD) DOCKER_REPO ?= xperimental/nextcloud-exporter DOCKER_TAG ?= dev .PHONY: all all: test build-binary include .bingo/Variables.mk .PHONY: test test: $(GO_CMD) test -cover ./... .PHONY: lint lint: $(GOLANGCI_LINT) $(GOLANGCI_LINT) run .PHONY: lint-fix lint-fix: $(GOLANGCI_LINT) $(GOLANGCI_LINT) run --fix .PHONY: build-binary build-binary: $(GO_CMD) build -tags netgo -ldflags "-w -X main.Version=$(VERSION) -X main.GitCommit=$(GIT_COMMIT)" -o nextcloud-exporter . .PHONY: deb deb: build-binary mkdir -p dist/deb/DEBIAN dist/deb/usr/bin sed 's/%VERSION%/$(VERSION)/' contrib/debian/control > dist/deb/DEBIAN/control cp nextcloud-exporter dist/deb/usr/bin/ fakeroot dpkg-deb --build dist/deb dist .PHONY: install install: install -D -t $(DESTDIR)/usr/bin/ nextcloud-exporter install -D -m 0644 -t $(DESTDIR)/lib/systemd/system/ contrib/nextcloud-exporter.service .PHONY: image image: docker buildx build -t "ghcr.io/$(DOCKER_REPO):$(DOCKER_TAG)" --load . .PHONY: all-images all-images: docker buildx build -t "ghcr.io/$(DOCKER_REPO):$(DOCKER_TAG)" -t "docker.io/$(DOCKER_REPO):$(DOCKER_TAG)" --platform linux/amd64,linux/arm64 --push . .PHONY: tools tools: $(BINGO) $(GOLANGCI_LINT) @echo Tools built. .PHONY: clean clean: rm -f nextcloud-exporter rm -r dist prometheus-nextcloud-exporter-0.8.0/README.md000066400000000000000000000342661475353242000210620ustar00rootroot00000000000000# nextcloud-exporter A [prometheus](https://prometheus.io) exporter for getting some metrics of a [Nextcloud](https://nextcloud.com/) server instance. ## Installation ### Docker Image The preferred way to use `nextcloud-exporter` is by running the provided Docker image. It is currently provided on Docker Hub and GitHub Container Registry: - [`ghcr.io/xperimental/nextcloud-exporter`](https://github.com/xperimental/nextcloud-exporter/pkgs/container/nextcloud-exporter) - [`xperimental/nextcloud-exporter`](https://hub.docker.com/r/xperimental/nextcloud-exporter/) The following tags are available: - `x.y.z` pointing to the release with that version - `latest` pointing to the most recent released version - `master` pointing to the latest build from the default branch ### Pre-built binaries The [releases](https://github.com/xperimental/nextcloud-exporter/releases) page contains pre-built binaries for AMD64 and ARM64 linux. ### Build from Source If you have a recent Go installation (see `go.mod` for the minimum version), Git and GNU Make, the following commands will check out the repository and compile the binary from source: ```bash git clone https://github.com/xperimental/nextcloud-exporter.git cd nextcloud-exporter make ``` After this there should be a `nextcloud-exporter` binary in your current directory. ## Client credentials The exporter supports two different approaches for authenticating with the Nextcloud server: - Token authentication (needs Nextcloud 22 or newer) - Username and password If you have Nextcloud 22 then using the token authentication is recommended, because it does not need a normal user account with admin privileges. If both a token and username/password are specified in the configuration, the token will take precedence. ### Token authentication Nextcloud 22 and newer versions support "token authentication" for the serverinfo. That way, accessing this information does not need a normal user account with admin privileges. You can set the token to anything you like, but the recommendation is to set it to a long random number: ```bash # Generate random value (for example using openssl) TOKEN=$(openssl rand -hex 32) # Set token (using the occ console application) occ config:app:set serverinfo token --value "$TOKEN" ``` You can then use this generated token in the exported configuration instead of username and password. ### Username and password authentication To access the serverinfo API you will need the credentials of an admin user. It is recommended to create a separate user for that purpose. It's also possible for the exporter to generate an "app password", so that the real user password is never saved to the configuration. This also makes the exporter show up in the security panel of the user as a connected application. To let the nextcloud-exporter create an app password, start it with the `--login` parameter: ```bash nextcloud-exporter --login --server https://nextcloud.example.com ``` The exporter will generate a login URL that you need to open in your browser. Be sure to login with the correct user if you created a special user for the exporter as the app password will be bound to the logged-in user. Once the access has been granted using the browser the exporter will output the username and password that need to be entered into the configuration. When the login process is done, it is possible to disable filesystem access for the generated token in the user's settings: ![Allow filesystem access checkbox](contrib/allow-filesystem.png) --- The interactive login can also be done using a Docker container: ```bash docker run --rm -it ghcr.io/xperimental/nextcloud-exporter --login --server https://nextcloud.example.com ``` The login flow needs at least Nextcloud 16 to work. ## Usage ```plain $ nextcloud-exporter --help Usage of nextcloud-exporter: -a, --addr string Address to listen on for connections. (default ":9205") --auth-token string Authentication token. Can replace username and password when using Nextcloud 22 or newer. -c, --config-file string Path to YAML configuration file. --enable-info-apps Enable gathering of apps-related metrics. --enable-info-update Enable gathering of system update-related metrics. --login Use interactive login to create app password. -p, --password string Password for connecting to Nextcloud. -s, --server string URL to Nextcloud server. -t, --timeout duration Timeout for getting server info document. (default 5s) --tls-skip-verify Skip certificate verification of Nextcloud server. -u, --username string Username for connecting to Nextcloud. -V, --version Show version information and exit. ``` After starting the server will offer the metrics on the `/metrics` endpoint, which can be used as a target for prometheus. ### Example Dashboard The repository contains an [example Grafana dashboard](contrib/grafana-dashboard.json) that can be imported into Grafana. The dashboard is also available as ID `20716` from the [Grafana Dashboard Exchange](https://grafana.com/grafana/dashboards/20716-nextcloud/). ### Configuration methods There are three methods of configuring the nextcloud-exporter (higher methods take precedence over lower ones): - Environment variables - Configuration file - Command-line parameters #### Environment variables All settings can also be specified through environment variables: | Environment variable | Flag equivalent | |----------------------------:|:---------------------| | `NEXTCLOUD_SERVER` | --server | | `NEXTCLOUD_USERNAME` | --username | | `NEXTCLOUD_PASSWORD` | --password | | `NEXTCLOUD_AUTH_TOKEN` | --auth-token | | `NEXTCLOUD_LISTEN_ADDRESS` | --addr | | `NEXTCLOUD_TIMEOUT` | --timeout | | `NEXTCLOUD_TLS_SKIP_VERIFY` | --tls-skip-verify | | `NEXTCLOUD_INFO_APPS` | --enable-info-apps | | `NEXTCLOUD_INFO_UPDATE` | --enable-info-update | #### Configuration file The `--config-file` option can be used to read the configuration options from a YAML file: ```yaml # required server: "https://example.com" # required for token authentication authToken: "example-token" # required for username/password authentication username: "example" password: "example" # optional listenAddress: ":9205" timeout: "5s" tlsSkipVerify: false info: apps: false update: false ``` ### Loading Credentials from Files Both the authentication token and the password can optionally be read from a separate file instead of directly from the input methods above. This can be achieved by setting the value to the path of the file prefixed with an "@", for example: ```bash # Authentication token nextcloud-exporter -c config-without-token.yml --auth-token @/path/to/tokenfile # Password nextcloud-exporter -c config-without-password.yml -p @/path/to/passwordfile ``` This also works when the password or token is set using one of the other configuration modes (configuration file or environment variables). ## Other information ### Info URL The exporter reads the metrics from the Nextcloud server using its "serverinfo" API. You can find the URL of this API in the administrator settings in the "Monitoring" section. It should look something like this: ```plain https://example.com/ocs/v2.php/apps/serverinfo/api/v1/info ``` The path will be automatically added to the server URL you provide, so in the above example setting `--server https://example.com` would be sufficient. If you open this URL in a browser you should see an XML structure with the information that will be used by the exporter. ### Scrape configuration The exporter will query the nextcloud server every time it is scraped by prometheus. If you want to reduce load on the nextcloud server you need to change the scrape interval accordingly: ```yml scrape_configs: - job_name: 'nextcloud' scrape_interval: 90s static_configs: - targets: ['localhost:9205'] ``` ### Exported metrics These metrics are exported by `nextcloud-exporter`: | name | description | |----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | nextcloud_active_users_daily_total | Number of active users in the last 24 hours | | nextcloud_active_users_hourly_total | Number of active users in the last hour | | nextcloud_active_users_total | Number of active users for the last five minutes | | nextcloud_apps_installed_total | Number of currently installed apps | | nextcloud_apps_updates_available_total | Number of apps that have available updates | | nextcloud_database_info | Contains meta information about the database as labels. Value is always 1. | | nextcloud_database_size_bytes | Size of database in bytes as reported from engine | | nextcloud_exporter_info | Contains meta information of the exporter. Value is always 1. | | nextcloud_files_total | Number of files served by the instance | | nextcloud_free_space_bytes | Free disk space in data directory in bytes | | nextcloud_php_info | Contains meta information about PHP as labels. Value is always 1. | | nextcloud_php_memory_limit_bytes | Configured PHP memory limit in bytes | | nextcloud_php_upload_max_size_bytes | Configured maximum upload size in bytes | | nextcloud_scrape_errors_total | Counts the number of scrape errors by this collector | | nextcloud_shares_federated_total | Number of federated shares by direction `sent` / `received` | | nextcloud_shares_total | Number of shares by type:
`authlink`: shared password protected links
`group`: shared groups
`link`: all shared links
`user`: shared users
`mail`: shared by mail
`room`: shared with room | | nextcloud_system_info | Contains meta information about Nextcloud as labels. Value is always 1. | | nextcloud_system_update_available | Contains information whether a system update is available:
`0`: no update available
`1`: nextcloud update available
In case of 1=yes, `available_version` label contains the new version. This metric is only available if activated. | | nextcloud_up | Indicates if the metrics could be scraped by the exporter:
`1`: successful
`0`: unsuccessful (server down, server/endpoint not reachable, invalid credentials, ...) | | nextcloud_users_total | Number of users of the instance | prometheus-nextcloud-exporter-0.8.0/contrib/000077500000000000000000000000001475353242000212305ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/contrib/allow-filesystem.png000066400000000000000000000314111475353242000252360ustar00rootroot00000000000000‰PNG  IHDR,,ö" pHYs.#.#x¥?vtIMEä "è)ÚbKGDÿÿÿ ½§“2–IDATxÚíytÕåÿ3çxfþ˜_{¬vÚé¬Úδµ­Óéx:=vde‹;ZAË®l²ÉŽ(ˆì‚‚ì¢@d“}‘ÈNBBH–•„¤†$ÆH4ú{y?úôëM¸$77 Ëû}rrî}¾ßï³~^Ïçó<ß{¿7ì/’$5ªÂÔ’$%IJ’$%IJ’$%éæ„ðÏ’¬ÄOh ,”®7{ôé§Ÿº×E>5XM.]º$„ŽÞ\úòË/+**JKKÏ;wöìÙ3gÎdgggffò"'''??ÏŸ?ÿÅ_A(…R~Ù>eÕLœ ™Ÿ}ö™zOJÁëòåË8½¼¼¼ŒŒ Ü]VíeW0þSý)¥ÚáWRR’Rá?ÿüsõ­ ”®.¼Þ/8×wUª‡¡HçϟϪgá+++ÕÕ‚PªF,ÞêÉV´«Ã¡ô­Eà'Ÿ|Ò`¢ŒŒŒ²²2õ¼ ”¾V~~~Vc¨¤¤D/åÚúÝÃP\*ovg5ªˆKuQÞ¼ºpá d5¶Îœ9£¹ ›Q_~ùeÍ?†Vß:wîœFDÞt*((Ⱥf¤Å¡ T ÚøÊÉɹ|ù²†FÞÂÖóòò²®1É ›H•••Yת4:‚ð¦PcÝš¯‰ô1AxãëË/¿¼ÖVƒ^hŒá ®Ï>û,ëVvv¶ÆHÞàúä“O®e333ËËË5L×1„e>©[èÌ™3×8„ŠHÂI“&­Y³&$y•””üæ7¿ ØEEE‡Ò‚Péa“&MÀ¦_¿~uÏë‹/¾5jÔÀCS3Ÿn°î>þ|c}a¢Vb² áçŸÞ­[7Ì=**ªîÙ…ðÁÌwß}÷ÿ÷ß`Ý]XXx]@¨GB5ôšðèÑ£@8~üøjÏHOO焸¸¸Ã‡ÇÇÇ%’˜’’b)'Nœð~Ö)Þ'{}éÒ% Î{íŸþô'oÎ`Ÿ˜˜èu¤±±±DkÂ_üâGŽáZâRïB…*YžÉÉÉ~ÿw‡¸0''§Ú€:SÎáLVh~'TTT$%%ö)!!áôéÓ~nÁqüøñÚvwД!Dqn¬pܸq¯ù4a„_ÿú×ä!@H @1îÚµ+@‹ˆÙæÎ;uêÔ3f 4ÈŒ•tŠÆÛ¤¥¥U !.”×íÍŠ•!‰Ë—/¯ïp”U5äkiBMzpÚx[·nÞ›Õ ‘ù¯ÿú¯>ú(mQ8z@øúë¯_S/„“&MòÎý¼>}zM Ü¿?^× açÎk!þìg?{â‰'¨ÏXF垒„òÌ3ÏXIØYµ9Û¶mãЃ>«¸—ððpá¬Y³pÔÞox!¤z¼ž9s¦77N&qΜ95ìn8 ú ¬ú† 6|øðäädó¨ééécÆŒa!Nv3«W¯&…¹2ha#¬ káĉC!Áí• „@V8~[‹¿üå/1¯ÀÆ9cÿõ_ÿUímFÿçþÇ=‚zëÖ­ÂÈÈH\MRRÒ•ÂQ^1›ۖ-[H$Ì®aw1½i™ý'V{Zm¥G?5ôîhcAغukod{þüy/„棼5!à¼ï¾ûHô»ÕQ­(—3á¶jsž~úi?Ì B¼ï~÷»={ö´Û!4Í»1séÒ%¿¦M›ÚMÃÒêSó[Û¬µB~Ÿ0Ó§Ðæ©çä7(„ÉU{Ÿ½þ dsÇw°Æ[µjÕŽ;.\øÏÿüÏÂ÷Þ{œ;tè°}ûöÅ‹Ûg븖D¼+:øY¿~ý€¾øâ C´k×®›6mŠçÿÿýßÿqfÕ‡ˆµiÓ†˜“ ÜnôMž<ÙAˆÞyçËØ~÷»ßÙÝ·;Jýy{Ï=÷¬X±Ø®];N¨¹´½¥ºl-óeT‘;TÇ"ôœ‹†Þ˜qªv—ô!C†¸·#GŽ$ÅyƒÐmÓûíøóú7Þp×îÞ½›V2înÁÚµk½hÞ¼94ºó“ã<%%¥G.ýÇ?þ±må¢mÒ˜Z¶lWµ9………ôúóŸÿÜûiIÈ\·nÝìÙ³!™Nž<éŽÆÆÆ>ûì³váoû["ØÚ>,°.¢~éß–¥8ƒ.¥jø 5r8z3ËbÚÐ~|„X:hüœÇ6Ö½§¿-R B¯WÔ“fáõ$<óÊ•+£¢¢RSS1è7þþ÷¿ê©§BõiXÓ§Ÿ~Z~TÒþ{åh´3ƒãP±¨ l4á£î½÷^¦~ÿû߇@,;´¥6× G Åœ†1ù©S§ˆ“YÍ?óßÞ’n(:¯X[k²é% Âú«»’’’sçÎ}â«GÛò ¹j~ËÞK 9@03öŽù”œœœ““C /ŒFCÑX ‚CVò²Ax㫼¼¼&Tx tÐ\_RRRbbâÑ£GóóóÿâÛˆBÞ’™æÍ%ÖŠCÎÑR›B,º®ê ý„(¸‚.`ƒ´#GŽÄÅÅyCG8LHHˆç(çx]b 9ä¨~®PÞD"ê €„w'Æ@H¿ØØØ³gÏúå Bö=IÅUâ0ý84õÛL7„—¥:ÈV†™ÕÉ{Ðh!¨}Å9&&¦Úoi‡öhhôã°ÚÞB‹‹‹5.uІƒÐмä/ìy—<ú³TÑQUo¸;y·a¼FGGWõ^}úé§±>YhjKDÇ¡©jq999»œŸµ»×A„ëse[µ¾”‚UAAcÃïλ9@„¢£GZœUí3;ªúÃC>¸r­Ûªq»¦ÞûûÆ$3‚†#92Ap„4ð*}ú£ϥÚ+;;Û{·Ýn~8@· ƒg;xðà•¢Ðjý!Q«ãGj(’­ÑèJämaa¡¢VúâÛ?&k…bXm 4ürå>]¼xñÂ7:/ÕF¥¥¥ q¼Š¼» àtàÀÚ>Ô8$|µ§l‘›¡èW®U£Vs9;¿è“Ù?q„C1k ¡emÞÏØ£Ô©¬¬ 3ú̧>•j¬¢¢"ØHò)ѧ„„ÃHºoß¾šû@?¹ŠK4ÉÙn'ZYD¤êÿªäÛ2›ÇøAÀAÃPt¡ih t>Ð øÙÄiÔa@3çÎ+ðé“oô'©6:{ö,xØS=œüìß¿ïÞ½uùÙÀââb¼(“^Ñh4šÚ󻤚ÈÙ¶™:6åcÿô0 @£ùIóеâ0¬&¨[RÅ|õð³ÏðuÅ…ç >ùS~~~^ÞÙ³ÙÙg®ñ_Y¸ÆŸ<Ÿ‘‘$|‚™={öìÚµ+22²î?܉•Xn»wï&çý>áÕíA¦žã³'À$@ŠÆ¡ Mk”†ÕÜ ’5>÷+ÿûYÉó“ÂFÆ|ý7(êÝÄ"Ýr•næ@!â‰Z½ÖÐÖB˜&Ø%_îW뽢—$…‹ýúI… é&âáU"¯AÆ9Ã@h›1ðÍ:ÜÏ}ò§% BIò Rˆü-.u‹CÛ)­+„ÐL^Î ~µ”Ï;ûÀ¢£‚P’ªnGòÉ' HPŠ3t;4u‚ÐnÍÛ¦(N–Ü¿ÚÊËÉn±0AJ’ŸäìÙ³8CbÆ‹/Ö0"­‘'$5‰EóóósÏdÝ¿@J’¿$''‡h‘˜‘ÈÑn^«ÞG¶ošçåå9s&--í«/Ô$m2÷° ”$?áí!°„î^ÅU ¼Pö¹*°&w²†ÃÓ§OŸ<~¬É¼8A(I~ÂfffB q)‘£AX×pÔÝŸ¸pá‚íÊäææf¤Ÿn6ÿˆ ”$?3!a#NËnT„Bû¬ŒBBÞŒ´Ôfóã¡$U…0==Yǹ ÒAèîO‘¦Ÿ„’TDÐ6Hë B@„’´´4áÅ‹kr¿¾ÚȯöHSS¡$ BIº!<}ú4ž;wÎî× BI„’$¡$ ¿Êný'ý^—$CááÇß{ï½EµWDD„û}_I„ÁC¸}ûöŒŒŒ Ú[ío_K’ ¬5„T1ˆ¶ÅÄÄÄÇÇkŒ%AxÃB˜––Ö­[·ÈÈH{{üøñŽ;îÙ³§^Œáùøã{õêÕ¼yóÇ{ŒÒÛ¹¹¹……_w&õiß¾=.ã„7„—/_ƬxðàA¿C'Nœxþùç÷îÝko9“¨×Ûºuk÷îݧNjئoO:Õ¥KRÊÊÊ8aÓ¦MÔ*¸ÇþÖEEEELC•••‚J†Bzäµ×^ëܹó´iÓ.\¸àa=BúsÒ¤IcÇŽõþ.gqqñÊ•+©†m7 „ôÌ”)S^zé%ºKP ÂCxèÐ!b¿#Fà ®q!¤'1ôùóçžF»yóÍ7™­¡ 1„4ÛzõÕWûöí»hÑ¢ÚB˜ŸŸ¿{÷îmÛ¶í߿߹/Öo4*66–^rtmÞ¼Ù~JÞ:øwìØQ^^î—ÛÈ‘#_yå•Í>šæää0l}ô¹€0%%…Ü(”q…šˆf¹œ¬¨gVV–Í™ œ;'//oË–-'Ož´'C;vŒÜ¸„pvv6)á€Ö­[·Å'Jt—3|Ažqqq˜—wN!…hŸ¬8J4km¤Ké12w ]?a™™™œ°Ý'U5 ¶vYÏcåîŽ1¯¹YZS1Úkéó¬8,ݯ÷Ü!ZM?[Øÿß3ܖޱ¹tAJ±$ÜàúõëiÎܹs äžÀ2ê»vízæ™gúôé3dÈÀàdìØØ&¤œ8q¢‹oà¹çžcøímEEŸqã^ýug"^Ép”OcÆŒ†pèС‹/®B²š7o^‡L5ºvíJ\mþŠF-_¾œC´ ˺÷ý÷ß'“â4zÏ•‹5Ó´äädµlÙ²N:‘—¼ð kÖ¬ÁV Bš@õ¨Ó„õEç³Ï>KT’µë„ ° ËvΜ9¤Pî°aÃúõëG¡ýû÷'…ÿäOnt~ZZZÕq9ªÁ´8|øð_|‘KÞxã Zê¦ÎwÞyçü#yÒdòE›>èaÒ{öìI:Gg̘aWa`”E:Ò(2tͧ'©]J4ÄQZa7Ÿ±jŘZ:Ww#M]€…õîÝÛ~ã–¹•!&^Cy‹UÍž=›éœn¥^~ùe ¯ÂÑ÷Þ{*((°“ñ±„»ÎÓGñ*~Ã@:C¾`Áû¡+ûH€‡‰I¹ý8Q+<2öð¼téRæFÝ~»Ë¦ÒáÓJçLlšrG‚Cpe†ÂÜo<„Ì,Ø=hÏ®eìè4|…ý.ˆÊÐ.«³øQ áUè+ꆶG<$%%íò›‰\l&ãÌU«VVTT”aÿÁP( ·ê€idf”RTTDz™O¶¥Ä¬A¼C§‘!ãÅÂÀl¤¨-£Œ_µö£žJP(¶‘à—.C !ɼ>kÖ,‹ hC…ƒ¢»¯ !£Žçd’öþD.ƬŒEÚRêøo9“-3Fl6 ðœyôèQ¿*!“®_TBòÁKµŸ7`PHÁÐ(ÎÁÊÐ/–ãíÔ©SG]\\l™ð`¸[ä ô»¤Ú5!E‹¦L™b“²%R¬É¶]>|˜V[ŸØÍ˜É“'ã9¯jÜ4„Þ#`±§YÓíT¦êiÇi†–W,Àm3¯õ?)öI`ÝÔÔT¿«V¬X„¬S´&¬G™Y™¶½÷ý¨³¥K`éJˆ%žôfȔ̪ ¯bvƒ­XøG˜í̸¸Ûû ‚:ú­ŽÒoxT"¥—¿ÙbRıö4!®Â‡ð–j{?g»sçNx°–BÓL|©Ù(~….³ÚbR}|ò+ª !†NÍAÂAøöÛoÓ3ÕÞö sÞ}÷]&/&ˆñãÇ3£­]»–êáÆ©-®Þï|œuv7r¼¶ N 4ª«'n6Ú`½ÀÆÔ3þ|·hG0C˜JßÒŠª`7„=öXXXØ !½@çbXüÆ7lØÀlÓ4rCo˜Ç›'ÖÆR‡…­[xYÐ?N˜/S8«,¬‡èÃrPÕB»“É⨶{ÄÌbîððÏðÓ®];LŠ€ÍÄ[bf^S%LÍÙƒ‹Ëb öÄO]¨ÕBH& '¶'äfÕzB–Ô–ª:‡la°[ì9q&9ãÖà‡È‚y ¤9ÌhdBÔíw ÝË´8sæL¿ûL”ÌŒ#á··ž,#ÝÞ×2FùÈ#0¹-+FŠÞf2}ôÑG.\è½oÔÞqÇ·ÝvÛ ¡E8@ÕõÛb°K›È@hqÆk”äÉœÊ`»(K¢’Ó¦MÃÇÚÊã&…lÝng] ÌÊÊ‚¦ðj—UNØnff&~{²6Ä4—,YB ùP=l×»«iâÌ¡>1ÄøUÖZÌ)^ÇFÉxþJåÖB ÉïB°ÁÁRggÄ„æ ±4¼ÖÊ•+«Îª·ŒˆÅØÞ¶ƒTüû “&âíÔ©Ó²e˼xзô99¸‘m ›5kö½ï}/„Ö<ú‘$ H?ÒbÁ‘ëBqk6¯iâ7#Í t[š@È%¾Òö?üÐvDܵ`Œçq7* ÇhÌVÈ’ Ëf0‚ƒ9›Lì§êK¼1~Ìve —Bõœ386zËõ!Ê@z»O¶  ›ððxKÜ!s;„”¡1`&LÀ¬±Èd}رcG,Õ4½Ì¡Î;ã@p¶Î!7NcN­v7¢&²TÃÔ(Îx`¡…—°­WìÎ$ v›ìÔI„ét1k,ÞKgâÛͺ{6x6füÓ? N–yvË6Òi–RkÖ¬!œ³E)ÝH&à´oß>¢D°tß/ B&A¦?ÊÚ¿?S¡}˜Ö äh\\o9…µbî£\Ñɬ÷ì#~L+4™~¶!ƵÒEô-±7yå›,Cè["p¦HBn<áêÕ« iÒIä¢Tà‚ëaïþûïŸ>}:3ýÝwß}çw~ï–°[ú½w]@ȸ>þøãLU·`ƒ±oß¾=<ÐG¤÷Û”ÇÊ¡Ûr'¾‚”–-[b⌮Ÿ=1~-Z´`ÈÝä…Ù=ôÐCÎù‰qÂVü¶þ Ã"´·¶eÏê…~sèbd8ðæÍ›³öÃÓi¤¡±¼oÒ¤ <²õîåº%åÒ¥K] nYÝwß}O=õ]ä ÅnXSQJá?¯Íy‚:¶ŸØ½J”îJÁ6pAÎçCxëÖ­aÃeˆýÐÞªkBFÁevoÚ´)Ã?Œ…³ZÜ `PCº×n,Ÿ”EHI£H§+è4ƒá]mÛ¶-‡8¸ÀæAÇÛ“Hý àÙ¶š]:íe^¶ôkB&xšQVV†•ð¶é=wuX~\_eºŽÄKñ~öEªÕ#„DÏÌaÌ4,…q?ùa/ rMÜä amÅØáF06¢M".}1âF€Xœ•ÒO¾>/6aI·h0ÙGPYüÄýyH隃hûÇÁBÈÒâÏÁJz BzL– ”$A(%IJ’ ¼ „£FêÕ«Wí>›ƒpƌ۷k+%)TÎÔvD*++ÝgGsss3¿ú¹l=_’ Bý…$ BI„‚P’¡$ BA(I‚P’¡ ”$A(I‚PJ’ ”$A(%©Q!L?6+6lhÔ×ý,N8§¤†ƒðäÉ“åúñ:IjTý™*I’ ”$A(I‚PJ’ ”$A(%IJ’ ¬„…WAù’ivvvZZø%&&FGGWû›{’$Cï ¹˜,È×WRRRPP““sêÔ)yBIR8*I‚P’$A(I‚P’$A(I‚P’$A(I‚P’$A(I‚0Ä¢ ”¨q•aã@¸qãÆŸýìg?ùÉOFUTT¤Ñ•aCCXXX8`À€Ö­[‡‡‡Ï™3G£+ ‚°¢¢báÂ…|ðÁåË—iÆÈ‘#[µj5lØ0J×K‚°Þ!¬¬¬œ={vË–-q€pHJAAAß¾}§M›VG§:~üønݺuíÚµgÏžcƌپ}{yy¹,F„þ>pÞ¼yà÷O¼ˆˆˆÀRhIII]r¦Gˆl§L™²oß¾ÈÈÈE‹uìØqðàÁiii2IþÕÎ;÷Á|È#8ܰaCÝ3§G^|ñÅÕ«W»”ìììΚ5‹>²hg¸èíugÒw´·i‡8‡3ÝQÎt‡8Í¥s]j|ÜÉü§W½5䨕Î!oé’ l É|Μ9ΚڴiCIYõ!¢DœÅÅż¦›Ö®]Û»wïxàø>377×NKLLÄ‹vèÐ "<<¼OŸ>ëׯwœlÚ´é©§žjÑ¢4hPLLŒ!šŸŸ?a„.]ºpkZbà Lœ8‘ÌyKú’%K´ŒÓ²e˺wï~ÿý÷SSƒnÌÂ…*Ο?Ÿu —À¶mÛbîø«QB/HŒ7®´´”Þ¥Î;ãuËÊÊ’’’8yæÌ™¸&Î÷Üsk™¬X±JwîÜI—’øÂ /,\¸Ðëo%AX’-¿Ÿ„@L6$>Ð !¦OC âĉʲpóæÍ¥]LJçßvìØW„.ƒ°W¯^Ç·CÀ†Ç[³fMÕRà“0û÷ï¿}ûv;Db¿~ýÜÛ¼¼¼aÆ٤ÀDCÝàÐQºÔ‡:Ë a½CHži„g~Q(>0„„ø¥§Ÿ~úW¿úÕÿþïÿ>ñă޻w¯Ù}ZZ·øÒà“¦­[·Î¹;? _ÇŽ»xñb{ËùxÔG}´Y³f8·¾}ûr¹ƒpÛ¶mv<1¡K&8aËäðáâL)))äÆBSJä… ZÖ/„ÔìÍ7ßô#EW×®]C…úyÂU«Vñšj³äã­s5§NÂM0t󉄠x¶ª”Ž?žp‘×$â0É ÷HÿìÚµ‹¨ªBH§±þ´›.ˆndÅÈÄkâOÜ>¥wóˆ Ì’ ¬Gãââ0ý'Ÿ|Ò»й‡ÖV»&ÌÍÍåíœ9sèë5<áÖ­[«½6„0Æ…®Â‰‰‰øÏš@H&ÂcÇŽA2nYæ+ÂE‹±<Ã{<þøã!œ••UýRuc†r;uêÄÚÏ6ifΜ9dÈzí²OÞ. add$3))É=z”·µ…n$ =ztAA…ú•. Âú‚055õÀ¶$ã‹4â±úðW‚Íž={РA4Ƕ[8:̘1ãwÞ Öo¶OBzyèС¬`çÍ›÷Þ{ïMž<íÌšChÛ6ıøCâs²"w¡$«0--¹?:::è{YÔ†̾Až˜ûË/¿\O>Є“™;wîÇìMÌÌÌÄîÙ³ÇÞVTTlß¾Ó€¢RRRlŽ ª°‘žžn§á½9ºiÓ&·º[·nÝÛo¿ÍUK–,!¦µùùùo½õVTT”FcAÏéÍdãÆ®2eeeäÉ%äQ¯½!]ßRÀ£>æSlllЛ¢ƒÆdwîܹjÕ*! ÔàI‚°F2£oذácŸ(#¸ZBïk¯½FÄe÷µ%IÖzMXÇߢø³O-I!™&''ã /^ò»y’$¯!®o»í¶_þò—?ýéO9¢—¤…°²²2,,ì?øÁ¡C‡Nœ8¡/ÅJRCCXQQ„ááá, õû„’Ô8ž°yóæ·ß~ûìÙ³·mÛVÇo»K’ fM˜™™Ù¡C‡ï|ç;¸D‚Rõ¸$5(„çÏŸÇûåææ¦¤¤ÄÇÇë7ë%© Ôcð%IJ’ „’$%I BI„’$¡$ BI„’$ BI„’$ BI„’$ BI„’$ BI„’$¡$ BI„ ¡y(I¡„°, JJJ`¯°°Üsrr222pƒñññ¥¥¥êqI „¥W¹@`qq19æååáÓÒÒNœ8'%©ÂQ¼bÝ•I’aÖ„Ú˜‘$A(I‚PJ’ ”$A(I’ ”$A(IÒuáåË—©z¶OYYYÅÅÅKI6(„]ºtiÕªU›6mZ¶l9iÒ$¥$ëÂÜÜ\¨»í¶Ûn÷é®»î èÁáøC;ôï|güøñååå××HPá¼¼<@F)¯Qcbbš6múPÍÔ¾}ûë.@ýøãûõë—––&£„×(„Ô/>>>¡f:zô(¥×¥_¨jTTÔNŸ"##8‘‘!¥›}Mxùòeb¶‹WSEEEÝû…0`@Ÿ>}FŒ1|øðþýûwìØqæÌ™õ·Á+áuaYYY§N~÷»ßÝP!Ù¤¡G^|ñÅ>ø€×´…†ìÛ·ï¹çž{÷Ýw+++¡t“BÈåC† iÛ¶màáüùóCáêÕ«½‰o¼ñÆË/¿L‹Ì-§§§7®uëÖ]ºtÙ¾};G:‘p›6mvíÚÅ vÕ‘#G8çСCÖ„7vîÜ9<<üµ×^9wšBúœûöíK×ñ–Qá*& rfŠ¡3e¸‚°q $Ã)S¦`Ð!\¿~}=A8cÆŒW^y¥¤¤„×±±±Ý»w‰ÔÔÔuëÖÁáŠ+p’4™ðuñâÅÖƒ0¶víZ²*--¥ùÔwºiÓ&È?~|×®]Yy‡B`îܹƒ6ØðÿÓ§Oþùç?úè£ãÇ=8³²²d»‚° ¤fø¢V­Z†pëÖ­¡‚pÕªUŽ‚á($X8ʲ„ Э?W®\ɲ¨¨ˆ£K–,9r¤5–k9sÞ¼y¼Ø½{7ÆÅŹæL›6 ªíL dåI/EDDðÂÅ¥111ݺu㿽ÍÏχÕ?üйPI6„d <ð@~øa|TH 8p`=p;/¼ðBïÞ½ñ{Lv/;;»OŸ>Û¶ms烈ÒFÆ ‰KyMÈÊåû÷ïç5þmìØ±îÞ eÏž=O:åÝ}÷ݬŠYO!IÖ×ÇÖX¾e„999!_&$$àÜXÝÙ[–dxÂÈÈÈ+]¾|ùò—_~™’E ѩà OHÈz%OH@‹ÿ$FÅfffÚi\þÒK/ÙBT„5…Ð,Ì !`˜Õý£dDz ïÒ¥‹í(†Bz„Uibb"oY âìJ ?¢ÓÅ‹ÃØ‰',qÏž=$âý¼kÂÑ£G»5!Þ•^¢ÇÆ7tèPü'é¤\Û\•a ŒŠŠ ;pà€ƒ°   ::ºC‡ñññu¬.9<öØcW‚8 £§%õ±;JCÆŒÚnbŠ¡E]»v5j-=vìØŽ; Åõ\سÏ>;qâIJ²2—øúë¯C1*+¤U»;ÊkJgáÇ`p9Wqæû￟””D“‡d¢‘nLßzë­[n¹å‡?ü!.ËAˆ~ýë_³ž©û'¿p;w¾„­[·&r ÉÓMqÝüã—-[æç‡)bË–-æê³³³!í‰'ž ±wïÞ8::μk×®|pûöíÞè_.‡(j Ï4Çí¯lÛ¶íøCjjª½…I.·²ˆ €¼W¯^­Zµbå9}úôL4ÒáñãÇô£á™Âðƒx!Äb[ÌñuÿŠ@^^¾îJb£X¶¾ˆ ݤ# ›Ýzë­^Cø[TŽÅ’÷KL^ÝÿýóæÍÓÞ½t³¯ q‰ÕBxòäÉ|Ç/77wçÎU'BÚ A•aõRÌÁƒÕã’Ôh¦¤¤Ô÷Wò$I^%ÕÓÖ$IJÒÍ aNNŽ ”¤Fƒ¬Y†ä>¡$ ÂZCXRRÖ®];=»A’ÂcÇŽ\tt´ó„yyy³fÍjÚ´©}gG’¤ú…Ðä÷- 8 É·($IÖBý Œ$ BI„‚P’¡$ BA(I‚P’¡ ”$A(I‚PJ’ ”$A(%IJ’ „’$%IJ’$%IJ’$%IJ’Tr1YÔ•””äää„äW™$I~ aa@áúÈ—L³³³ÓÒÒð‰‰‰ÑÑÑúÉ$I „—ŠX´²²²¢¢¢¬¬Œp”2ŽJ’Ö„’$¡$ BI„‚P’¡$ BI’¡$ Â:‹œ{÷îvë­·òÞ¼yKIÖ/„d5eÊ”G¿Ñ#<òзå=A4º’ %„111÷ÝwßC5ÓÓO?M¹ Ü•»¬Ž*--ݼyó¡C‡ê’ ã"‹„ÁCß½{÷>5Ó‹/¾XRRtYö §t/SWQQa.÷í·ß4hPý}86//oèС6l:‡”””®]»’CàFI‚ðš•5jÔøñãW811±}ûöäõ‚ † r-C˜žžþÜsÏmݺU ÂàEýš5kvë­·~/ \÷~Y¸p!žÍÅ´tǺuëú÷“ãÎÙ¾}{=222`œòóóë¡$C!—FÛ¶m/çÎ[÷~ÁcÞÃÞ–••7®S§N‘‘‘îœE‹á0 x½iÓ&œ¡5>åí¼yó¦OŸN˜Š«ôëÍòòrx3fÌàœãÇ_©œ¶qãÆ™3gÒ"^ 6Ì !»zõj2¡™™™–È¢qÚ´iDžî´¤¤¤×_†àKÉ***Ê"b_³f 9PÉ}ûö1ð–Nn‹/&}ÕªUu‰ê¥BŒòÕW_mÓ¦M`W¬XQ÷~Áv»uë¶wï^˱Ô0`ÀìÙ³©Æ_|»µ'N|óÍ7YòöÝwß=ztii)ÁÀtèÐaÊ”)óçÏBVÎtÖŒO#píÝ»7†>a„gŸ}Ö•âl9’e0EÌ™3‡ó©9ÛÑ´´´^½záó—.]:f̘.]º“ÎX¾ð L.Ÿ•+W’¹egg÷ë×ï£>²ôS§N’á4ŠªÚ¶Ížyæfœ%K–Ð^Vטˆ8„_‹ ±éV­Z†ÐYj]”››‹ ._¾ÜÞ®_¿È§9¤Ð"ÜòÚµkí/„[¶láZ`³86!!sÿý÷íL¼–MþöÅKx饗ü tèêÛ·¯¹bÎ$ 9ó„`áǘqˆa›4iÒäÉ“qו••€=kÖ,Ò8Õ~çw¨†BæÐå#b_µñÆrŠ“‰¼¥âDþÕ4±|0?ü°í”ÔQfÙ0Ow`²¼&r£³ ‹ÈŽ9òüóÏÇÆÆ^ BcÕ"b4wDGƒ.Yyw}Aôĉ~7Á'ñ­ïÆ ,Žñã?vçƒ%ZPÊ9ÀfTãî˜5pn¼öBˆŸ§Ðèèh¿=á;wâ`³²²\ Óvóö’ ü*ÛeË–=ðÀ!<|øpHº7ˆóÁe%''ã»0hü~ì7Þ u,êp¶ ¡­9H€ ßÒµkWB>QþwîܹcÇŽ è‹̺u명…_Ÿ\&¼fF †ÍÈÈàõþýûyM%hÛK^wïÞݳgO;ßÛ½,2­>–3¢ªcÇŽ-..*‚ð¯S~“&M‡£`’®ÁQ`Í111«V­?~<’ˆqرcÇ#ñ“–xUq}¤€AJJ ®‰P“8óô7JMMõûh H ¥Üj!d–Á {3AŸ‚R1V’š²´³ÅžBœ9t1¹x µ`–¾@îÍ–¹ÃíÙH‚ð«mƒÖ­[_ ¿ððp¦p[ŒÕ]T7b÷*vìØa·×è#E#Ñë©@H,7sæÌqãÆq-.eÔ¨QóçÏlÖt«>Èwq B¨  0U 2dÛ¶mPÇŠÔ½¦¥¥вÄõ»gÞqqqC^Q¬Á8@ÈïBÄ:ŠVÌš5 gŠn™„"""°ÔîݻۆdµR•+WⓇCœÏrËÎä(×ëÒ'x<¢G jéð@d½8ON;zô(Õp·(ˉ'?üðCfz˜`Ì][TT4|øp0c9ÇT…1~ûí·{ôèA†XÄè<õ'ød~ÁácäCu—B~KÔ•Ë• ÄIâg°¤t 8a²=öë@ï§.iH‡(È»RZ´hÒ !Žë‘GiÕª´¸À•þ]¿~=®Œ)£yóæíÚµs{°UÝþÈ‘#©@³fÍøÏ%n3†žä*0#ÿûï¿ÿ¿uëVïµ+V¬hß¾½#1tëÖ ÷èvžˆŠá°eË–ôÛˆ#,‚À fϞݩS'ÖÞu¿M#éf‡éK !îÈ–F!­(//wü¸µNƒÖyé5m»ßÂQÜ çXõ3¨¼µó-Ÿ_ø°'Gš¸Ä;*~™ø}8›ùdµ\¹p BIÞ¤·Bz399Ù>Ý&I‚P’¡ ”$A(I‚PJ’ ”$A(%IJÒM aII‰A¨ß¬—¤+A˜––„………¥¥¥õaAA ”¤F†0'''%%EJRµ¦§§W…0ðb¯!„P'%)°X¯Ù3) ÂòòòCÈB“åfnnnjjª ”¤j!ÌÈÈ¢¢¢²²²PBHF8VƒW{úôiA(IÕB˜™™™ŸŸoÚ×>C !î' å8\{¦$I^ᥲ²²X~úé§çÏŸ„daB6|C9ÅBIª*¼Ô™3gð‡¡„Ðž-m_Bw¿¾á3P’®qA ‹µÜÜ\»SÏ’Ížxq†Ðì6HmY˜““£'XJ’W€g±(£ÛBª+„îV¡E¤ÅÅÅ8C Ćêih’t] FpNÙÙÙyyy¼p±hMîÔ×Ô’‘=,Œ¬ÁÀ—•!¦§§Ÿ8q")))!!!..îðáñ±±‡Š‘¤WXøaŸŽ9rôèÑäää”””ÌÌLQü^ÊnÓã·j² ¬„κí JáˆÿµG¸ŸòéÄ·u\’ny ûäÉ“X{jj*–Ÿ‘‘4 DñRø*w‡0z!™º )¯  )¯H=’ù çtIºeæå6:{ö,ë@‹B½âm5ÝÊÐCÊ£TBSЇF¦|Ÿò$醖ٹýè–8$ÜQ¨èÑ«nÉÔÂK>”ÚN)%]¸p¡Ì'h¤YìS‘G…’t£ÈkØfêØ<–ýC8àœœt†BÇ¡mÒ¸‡º_ô‰ À1Y*I7ºÌÔ±y,ߨ³Ÿ0€ »1h°Ô„ÀšBèåÐâÒ/}úÂ'÷k¦rIºÑå¬ýsŸÌû~µòµƒÐqèu‰Fc¥G_HÒM ÊoËy¿ ¬„i¼äÑŸ%鯕Ÿ»·Ž‹ÚÜG.[—$é¦Ôå* ‚¦0}æH’Wa’¬‚›ø%‹%)X ÂÐ@¨.$A(I‚P’¤ÆÓÿ•¥­íœÜðbIEND®B`‚prometheus-nextcloud-exporter-0.8.0/contrib/debian/000077500000000000000000000000001475353242000224525ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/contrib/debian/control000066400000000000000000000010111475353242000240460ustar00rootroot00000000000000Package: nextcloud-exporter Architecture: amd64 Version: %VERSION% Maintainer: Robert Jacob Homepage: https://github.com/xperimental/nextcloud-exporter Section: net Priority: optional Recommends: prometheus Description: Prometheus exporter for Nextcloud metrics The nextcloud-exporter can be used to gather metrics from a Nextcloud server instance. . A Prometheus server is needed to pull and store the metrics generated by the exporter, but it does not need to be on the same machine. prometheus-nextcloud-exporter-0.8.0/contrib/grafana-dashboard.json000066400000000000000000000641751475353242000254640ustar00rootroot00000000000000{ "__inputs": [ { "name": "DS_LOCAL", "label": "Prometheus", "description": "", "type": "datasource", "pluginId": "prometheus", "pluginName": "Prometheus" } ], "__elements": {}, "__requires": [ { "type": "grafana", "id": "grafana", "name": "Grafana", "version": "10.2.3" }, { "type": "panel", "id": "piechart", "name": "Pie chart", "version": "" }, { "type": "datasource", "id": "prometheus", "name": "Prometheus", "version": "1.0.0" }, { "type": "panel", "id": "stat", "name": "Stat", "version": "" }, { "type": "panel", "id": "timeseries", "name": "Time series", "version": "" } ], "annotations": { "list": [ { "$$hashKey": "object:405", "builtIn": 1, "datasource": { "type": "datasource", "uid": "grafana" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "target": { "limit": 100, "matchAny": false, "tags": [], "type": "dashboard" }, "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 2, "id": null, "links": [], "liveNow": false, "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 5, "panels": [], "title": "Users and Files", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 7, "w": 4, "x": 0, "y": 1 }, "id": 12, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto", "wideLayout": true }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(instance) (nextcloud_active_users_daily_total{instance=\"$instance\"})", "instant": false, "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Daily Active Users", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 7, "w": 8, "x": 4, "y": 1 }, "id": 1, "links": [], "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(instance) (nextcloud_users_total{instance=\"$instance\"})", "intervalFactor": 1, "legendFormat": "total ({{instance}})", "metric": "", "range": true, "refId": "A", "step": 900 }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(instance) (nextcloud_active_users_total{instance=\"$instance\"})", "hide": false, "intervalFactor": 1, "legendFormat": "active ({{instance}})", "metric": "", "range": true, "refId": "B", "step": 900 } ], "title": "Users", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 1 }, "id": 11, "links": [], "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(instance) (nextcloud_files_total{instance=\"$instance\"})", "intervalFactor": 1, "legendFormat": "__auto", "metric": "", "range": true, "refId": "B", "step": 900 } ], "title": "Files", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 8 }, "id": 6, "panels": [], "title": "Shares", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 9 }, "id": 2, "links": [], "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(type) (nextcloud_shares_total{instance=\"$instance\"})", "intervalFactor": 1, "legendFormat": "{{type}}", "metric": "", "range": true, "refId": "A", "step": 1800 } ], "title": "Shares by Type", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 9 }, "id": 3, "links": [], "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(direction) (nextcloud_shares_federated_total{instance=\"$instance\"})", "intervalFactor": 1, "legendFormat": "{{direction}}", "metric": "", "range": true, "refId": "A", "step": 1800 } ], "title": "Federated Shares", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 }, "id": 7, "panels": [], "title": "Apps", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 7, "w": 4, "x": 0, "y": 17 }, "id": 9, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto", "wideLayout": true }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(instance) (nextcloud_apps_installed_total{instance=\"$instance\"})", "instant": false, "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Installed Apps", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "#EAB839", "value": 1 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 7, "w": 4, "x": 4, "y": 17 }, "id": 10, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto", "wideLayout": true }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(instance) (nextcloud_apps_updates_available_total{instance=\"$instance\"})", "instant": false, "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Available Updates", "type": "stat" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 }, "id": 8, "panels": [], "title": "System Information", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green" } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 25 }, "id": 4, "links": [], "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": false }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "10.2.3", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "expr": "sum by(instance) (nextcloud_free_space_bytes{instance=\"$instance\"})", "interval": "", "intervalFactor": 1, "legendFormat": "", "metric": "", "range": true, "refId": "A", "step": 900 } ], "title": "Disk Space Left", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "hideFrom": { "legend": false, "tooltip": false, "viz": false } }, "mappings": [] }, "overrides": [] }, "gridPos": { "h": 7, "w": 4, "x": 12, "y": 25 }, "id": 13, "options": { "legend": { "displayMode": "table", "placement": "right", "showLegend": true, "values": [ "percent" ] }, "pieType": "pie", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "tooltip": { "mode": "single", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "exemplar": false, "expr": "sum by(version) (nextcloud_system_info)", "instant": true, "legendFormat": "__auto", "range": false, "refId": "A" } ], "title": "Nextcloud Versions (all instances)", "type": "piechart" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "hideFrom": { "legend": false, "tooltip": false, "viz": false } }, "mappings": [] }, "overrides": [] }, "gridPos": { "h": 7, "w": 4, "x": 16, "y": 25 }, "id": 17, "options": { "legend": { "displayMode": "table", "placement": "right", "showLegend": true, "values": [ "percent" ] }, "pieType": "pie", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "tooltip": { "mode": "single", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "exemplar": false, "expr": "sum by(version) (nextcloud_exporter_info)", "instant": true, "legendFormat": "__auto", "range": false, "refId": "A" } ], "title": "Exporter Versions (all instances)", "type": "piechart" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 32 }, "id": 16, "panels": [], "title": "Environment Information", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "hideFrom": { "legend": false, "tooltip": false, "viz": false } }, "mappings": [] }, "overrides": [] }, "gridPos": { "h": 7, "w": 4, "x": 0, "y": 33 }, "id": 14, "options": { "legend": { "displayMode": "table", "placement": "right", "showLegend": true, "values": [ "percent" ] }, "pieType": "pie", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "tooltip": { "mode": "single", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "exemplar": false, "expr": "sum by(version) (nextcloud_php_info)", "instant": true, "legendFormat": "__auto", "range": false, "refId": "A" } ], "title": "PHP Versions (all instances)", "type": "piechart" }, { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "hideFrom": { "legend": false, "tooltip": false, "viz": false } }, "mappings": [] }, "overrides": [] }, "gridPos": { "h": 7, "w": 4, "x": 4, "y": 33 }, "id": 15, "options": { "legend": { "displayMode": "table", "placement": "right", "showLegend": true, "values": [ "percent" ] }, "pieType": "pie", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "tooltip": { "mode": "single", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "editorMode": "code", "exemplar": false, "expr": "sum by(type, version) (nextcloud_database_info)", "instant": true, "legendFormat": "{{type}} {{version}}", "range": false, "refId": "A" } ], "title": "Databases (all instances)", "type": "piechart" } ], "refresh": "5m", "schemaVersion": 39, "tags": [ "prometheus", "nextcloud" ], "templating": { "list": [ { "current": {}, "datasource": { "type": "prometheus", "uid": "${DS_LOCAL}" }, "definition": "", "hide": 0, "includeAll": false, "label": "Instance", "multi": false, "name": "instance", "options": [], "query": "label_values(nextcloud_up, instance)", "refresh": 2, "regex": "", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tagsQuery": "", "type": "query", "useTags": false } ] }, "time": { "from": "now-30d", "to": "now" }, "timepicker": { "refresh_intervals": [ "30s", "1m", "5m", "15m", "1h", "2h", "1d" ], "time_options": [ "5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d" ] }, "timezone": "browser", "title": "Nextcloud", "uid": "cdae9143-9a17-4d37-87da-d34fb9cfd92f", "version": 4, "weekStart": "" } prometheus-nextcloud-exporter-0.8.0/contrib/nextcloud-exporter.service000066400000000000000000000006541475353242000264720ustar00rootroot00000000000000[Unit] Description=Prometheus exporter for Nextcloud metrics Documentation=https://github.com/xperimental/nextcloud-exporter After=network.target nss-lookup.target [Service] Type=simple ExecStart=/usr/bin/nextcloud-exporter -c /etc/nextcloud-exporter.yml User=nextcloud-exporter Group=nextcloud-exporter PrivateTmp=true ProtectHome=true ProtectSystem=full Restart=on-failure RestartSec=20 [Install] WantedBy=multi-user.target prometheus-nextcloud-exporter-0.8.0/go.mod000066400000000000000000000014071475353242000207000ustar00rootroot00000000000000module github.com/xperimental/nextcloud-exporter go 1.23 toolchain go1.23.4 require ( github.com/google/go-cmp v0.6.0 github.com/prometheus/client_golang v1.20.5 github.com/sirupsen/logrus v1.9.3 github.com/spf13/pflag v1.0.5 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/klauspost/compress v1.17.11 // indirect github.com/kr/text v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.61.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect golang.org/x/sys v0.28.0 // indirect google.golang.org/protobuf v1.36.0 // indirect ) prometheus-nextcloud-exporter-0.8.0/go.sum000066400000000000000000000126001475353242000207220ustar00rootroot00000000000000github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.49.0 h1:ToNTdK4zSnPVJmh698mGFkDor9wBI/iGaJy5dbH1EgI= github.com/prometheus/common v0.49.0/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE= github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= prometheus-nextcloud-exporter-0.8.0/internal/000077500000000000000000000000001475353242000214045ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/internal/client/000077500000000000000000000000001475353242000226625ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/internal/client/client.go000066400000000000000000000030221475353242000244640ustar00rootroot00000000000000package client import ( "crypto/tls" "errors" "fmt" "net/http" "time" "github.com/xperimental/nextcloud-exporter/serverinfo" ) const ( nextcloudTokenHeader = "NC-Token" ) var ( ErrNotAuthorized = errors.New("wrong credentials") ErrRatelimit = errors.New("too many requests") ) type InfoClient func() (*serverinfo.ServerInfo, error) func New(infoURL, username, password, authToken string, timeout time.Duration, userAgent string, tlsSkipVerify bool) InfoClient { client := &http.Client{ Timeout: timeout, Transport: &http.Transport{ TLSClientConfig: &tls.Config{ // disable TLS certification verification, if desired InsecureSkipVerify: tlsSkipVerify, }, }, } return func() (*serverinfo.ServerInfo, error) { req, err := http.NewRequest(http.MethodGet, infoURL, nil) if err != nil { return nil, err } if authToken == "" { req.SetBasicAuth(username, password) } else { req.Header.Set(nextcloudTokenHeader, authToken) } req.Header.Set("User-Agent", userAgent) res, err := client.Do(req) if err != nil { return nil, err } defer res.Body.Close() switch res.StatusCode { case http.StatusOK: break case http.StatusUnauthorized: return nil, ErrNotAuthorized case http.StatusTooManyRequests: return nil, ErrRatelimit default: return nil, fmt.Errorf("unexpected status code: %d", res.StatusCode) } status, err := serverinfo.ParseJSON(res.Body) if err != nil { return nil, fmt.Errorf("can not parse server info: %w", err) } return status, nil } } prometheus-nextcloud-exporter-0.8.0/internal/client/client_test.go000066400000000000000000000074311475353242000255330ustar00rootroot00000000000000package client import ( "errors" "fmt" "net/http" "net/http/httptest" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/xperimental/nextcloud-exporter/internal/testutil" "github.com/xperimental/nextcloud-exporter/serverinfo" ) func TestClient(t *testing.T) { wantUserAgent := "test-ua" wantUsername := "test-user" wantPassword := "test-password" wantToken := "test-token" tt := []struct { desc string password string token string handler func(t *testing.T) http.Handler wantInfo *serverinfo.ServerInfo wantErr error }{ { desc: "password", password: wantPassword, token: "", handler: func(t *testing.T) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { user, password, ok := req.BasicAuth() if !ok { t.Error("failed to get authentication header") } if user != wantUsername { t.Errorf("got username %q, want %q", user, wantUsername) } if password != wantPassword { t.Errorf("got password %q, want %q", password, wantPassword) } fmt.Fprintln(w, "{}") }) }, wantInfo: &serverinfo.ServerInfo{}, wantErr: nil, }, { desc: "token", password: "", token: wantToken, handler: func(t *testing.T) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { token := req.Header.Get(nextcloudTokenHeader) if token != wantToken { t.Errorf("got token %q, want %q", token, wantToken) } fmt.Fprintln(w, "{}") }) }, wantInfo: &serverinfo.ServerInfo{}, wantErr: nil, }, { desc: "user-agent", token: wantToken, handler: func(t *testing.T) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { ua := req.UserAgent() if ua != wantUserAgent { t.Errorf("got user-agent %q, want %q", ua, wantUserAgent) } fmt.Fprintln(w, "{}") }) }, wantInfo: &serverinfo.ServerInfo{}, wantErr: nil, }, { desc: "auth error", password: "", token: "", handler: func(t *testing.T) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusUnauthorized) }) }, wantInfo: nil, wantErr: ErrNotAuthorized, }, { desc: "simple info", token: wantToken, handler: func(t *testing.T) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { fmt.Fprintln(w, `{"ocs": {"meta": {"status": "OK", "statuscode": 200}}}`) }) }, wantInfo: &serverinfo.ServerInfo{ Meta: serverinfo.Meta{ Status: "OK", StatusCode: http.StatusOK, }, }, wantErr: nil, }, { desc: "parse error", password: "", token: "", handler: func(t *testing.T) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) }) }, wantInfo: nil, wantErr: errors.New("can not parse server info: EOF"), }, { desc: "ratelimit", handler: func(t *testing.T) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusTooManyRequests) }) }, wantErr: ErrRatelimit, }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() s := httptest.NewServer(tc.handler(t)) defer s.Close() client := New(s.URL, wantUsername, tc.password, tc.token, time.Second, wantUserAgent, false) info, err := client() if !testutil.EqualErrorMessage(err, tc.wantErr) { t.Errorf("got error %q, want %q", err, tc.wantErr) } if err != nil { return } if diff := cmp.Diff(info, tc.wantInfo); diff != "" { t.Errorf("info differs: -got+want\n%s", diff) } }) } } prometheus-nextcloud-exporter-0.8.0/internal/config/000077500000000000000000000000001475353242000226515ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/internal/config/config.go000066400000000000000000000205361475353242000244530ustar00rootroot00000000000000package config import ( "errors" "fmt" "os" "strconv" "strings" "time" "github.com/spf13/pflag" "gopkg.in/yaml.v3" ) const ( envPrefix = "NEXTCLOUD_" envListenAddress = envPrefix + "LISTEN_ADDRESS" envTimeout = envPrefix + "TIMEOUT" envServerURL = envPrefix + "SERVER" envUsername = envPrefix + "USERNAME" envPassword = envPrefix + "PASSWORD" envAuthToken = envPrefix + "AUTH_TOKEN" envTLSSkipVerify = envPrefix + "TLS_SKIP_VERIFY" envInfoApps = envPrefix + "INFO_APPS" envInfoUpdate = envPrefix + "INFO_UPDATE" ) // RunMode signals what the main application should do after parsing the options. type RunMode int const ( // RunModeExporter is the normal operation as an exporter serving metrics via HTTP. RunModeExporter RunMode = iota // RunModeHelp shows information about available options. RunModeHelp // RunModeLogin is used to interactively login to a Nextcloud instance. RunModeLogin // RunModeVersion shows version information. RunModeVersion ) func (m RunMode) String() string { switch m { case RunModeExporter: return "exporter" case RunModeHelp: return "help" case RunModeLogin: return "login" case RunModeVersion: return "version" default: return "error" } } // Config contains the configuration options for nextcloud-exporter. type Config struct { ListenAddr string `yaml:"listenAddress"` Timeout time.Duration `yaml:"timeout"` ServerURL string `yaml:"server"` Username string `yaml:"username"` Password string `yaml:"password"` AuthToken string `yaml:"authToken"` TLSSkipVerify bool `yaml:"tlsSkipVerify"` Info InfoConfig `yaml:"info"` RunMode RunMode } // InfoConfig contains configuration related to what information is read from serverinfo. type InfoConfig struct { Apps bool `yaml:"apps"` Update bool `yaml:"update"` } var ( errValidateNoServerURL = errors.New("need to set a server URL") errValidateNoAuth = errors.New("need to either set username/password or a token") errValidateNoUsername = errors.New("need to provide a username") errValidateNoPassword = errors.New("need to provide a password") ) // Validate checks if the configuration contains all necessary parameters. func (c Config) Validate() error { if len(c.ServerURL) == 0 { return errValidateNoServerURL } if len(c.AuthToken) == 0 { if len(c.Username) == 0 && len(c.Password) == 0 { return errValidateNoAuth } if len(c.Username) == 0 { return errValidateNoUsername } if len(c.Password) == 0 { return errValidateNoPassword } } return nil } // Get loads the configuration. Flags, environment variables and configuration file are considered. func Get() (Config, error) { return parseConfig(os.Args, os.Getenv) } func parseConfig(args []string, envFunc func(string) string) (Config, error) { result, configFile, err := loadConfigFromFlags(args) if err != nil { return Config{}, fmt.Errorf("error parsing flags: %w", err) } if configFile != "" { rawFile, err := loadConfigFromFile(configFile) if err != nil { return Config{}, fmt.Errorf("error reading configuration file: %w", err) } result = mergeConfig(result, rawFile) } env, err := loadConfigFromEnv(envFunc) if err != nil { return Config{}, fmt.Errorf("error reading environment variables: %w", err) } result = mergeConfig(result, env) if strings.HasPrefix(result.Password, "@") { fileName := strings.TrimPrefix(result.Password, "@") password, err := readPasswordFile(fileName) if err != nil { return Config{}, fmt.Errorf("can not read password file: %w", err) } result.Password = password } if strings.HasPrefix(result.AuthToken, "@") { fileName := strings.TrimPrefix(result.AuthToken, "@") authToken, err := readPasswordFile(fileName) if err != nil { return Config{}, fmt.Errorf("can not read token file: %w", err) } result.AuthToken = authToken } return result, nil } func defaultConfig() Config { return Config{ ListenAddr: ":9205", Timeout: 5 * time.Second, } } func loadConfigFromFlags(args []string) (result Config, configFile string, err error) { defaults := defaultConfig() flags := pflag.NewFlagSet(args[0], pflag.ContinueOnError) flags.StringVarP(&configFile, "config-file", "c", "", "Path to YAML configuration file.") flags.StringVarP(&result.ListenAddr, "addr", "a", defaults.ListenAddr, "Address to listen on for connections.") flags.DurationVarP(&result.Timeout, "timeout", "t", defaults.Timeout, "Timeout for getting server info document.") flags.StringVarP(&result.ServerURL, "server", "s", "", "URL to Nextcloud server.") flags.StringVarP(&result.Username, "username", "u", defaults.Username, "Username for connecting to Nextcloud.") flags.StringVarP(&result.Password, "password", "p", defaults.Password, "Password for connecting to Nextcloud.") flags.StringVar(&result.AuthToken, "auth-token", defaults.AuthToken, "Authentication token. Can replace username and password when using Nextcloud 22 or newer.") flags.BoolVar(&result.TLSSkipVerify, "tls-skip-verify", defaults.TLSSkipVerify, "Skip certificate verification of Nextcloud server.") flags.BoolVar(&result.Info.Apps, "enable-info-apps", defaults.Info.Apps, "Enable gathering of apps-related metrics.") flags.BoolVar(&result.Info.Update, "enable-info-update", defaults.Info.Update, "Enable metric showing system update availability.") modeLogin := flags.Bool("login", false, "Use interactive login to create app password.") modeVersion := flags.BoolP("version", "V", false, "Show version information and exit.") if err := flags.Parse(args[1:]); err != nil { if err == pflag.ErrHelp { return Config{ RunMode: RunModeHelp, }, "", nil } return Config{}, "", err } if *modeVersion { return Config{ RunMode: RunModeVersion, }, "", nil } if *modeLogin { result.RunMode = RunModeLogin } return result, configFile, nil } func loadConfigFromFile(fileName string) (Config, error) { file, err := os.Open(fileName) if err != nil { return Config{}, err } var result Config if err := yaml.NewDecoder(file).Decode(&result); err != nil { return Config{}, err } return result, nil } func loadConfigFromEnv(getEnv func(string) string) (Config, error) { tlsSkipVerify := false if rawValue := getEnv(envTLSSkipVerify); rawValue != "" { value, err := strconv.ParseBool(rawValue) if err != nil { return Config{}, fmt.Errorf("can not parse value for %q: %s", envTLSSkipVerify, rawValue) } tlsSkipVerify = value } infoApps := false if rawValue := getEnv(envInfoApps); rawValue != "" { value, err := strconv.ParseBool(rawValue) if err != nil { return Config{}, fmt.Errorf("can not parse value for %q: %s", envInfoApps, rawValue) } infoApps = value } infoUpdate := false if rawValue := getEnv(envInfoUpdate); rawValue != "" { value, err := strconv.ParseBool(rawValue) if err != nil { return Config{}, fmt.Errorf("can not parse value for %q: %s", envInfoUpdate, rawValue) } infoUpdate = value } result := Config{ ListenAddr: getEnv(envListenAddress), ServerURL: getEnv(envServerURL), Username: getEnv(envUsername), Password: getEnv(envPassword), AuthToken: getEnv(envAuthToken), TLSSkipVerify: tlsSkipVerify, Info: InfoConfig{ Apps: infoApps, Update: infoUpdate, }, } if raw := getEnv(envTimeout); raw != "" { value, err := time.ParseDuration(raw) if err != nil { return Config{}, err } result.Timeout = value } return result, nil } func mergeConfig(base, override Config) Config { result := base if override.ListenAddr != "" { result.ListenAddr = override.ListenAddr } if override.ServerURL != "" { result.ServerURL = override.ServerURL } if override.Username != "" { result.Username = override.Username } if override.Password != "" { result.Password = override.Password } if override.AuthToken != "" { result.AuthToken = override.AuthToken } if override.Timeout != 0 { result.Timeout = override.Timeout } if override.TLSSkipVerify { result.TLSSkipVerify = override.TLSSkipVerify } if override.Info.Apps { result.Info.Apps = override.Info.Apps } if override.Info.Update { result.Info.Update = override.Info.Update } return result } func readPasswordFile(fileName string) (string, error) { bytes, err := os.ReadFile(fileName) if err != nil { return "", err } return strings.TrimSuffix(string(bytes), "\n"), nil } prometheus-nextcloud-exporter-0.8.0/internal/config/config_test.go000066400000000000000000000204441475353242000255100ustar00rootroot00000000000000package config import ( "errors" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/xperimental/nextcloud-exporter/internal/testutil" ) func testEnv(env map[string]string) func(string) string { return func(key string) string { return env[key] } } func TestConfig(t *testing.T) { defaults := defaultConfig() tt := []struct { desc string args []string env map[string]string wantErr error wantConfig Config }{ { desc: "flags", args: []string{ "test", "--addr", "127.0.0.1:9205", "--timeout", "30s", "--server", "http://localhost", "--username", "testuser", "--password", "testpass", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ ListenAddr: "127.0.0.1:9205", Timeout: 30 * time.Second, ServerURL: "http://localhost", Username: "testuser", Password: "testpass", TLSSkipVerify: false, }, }, { desc: "password from file", args: []string{ "test", "--server", "http://localhost", "--username", "testuser", "--password", "@testdata/password", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ ListenAddr: defaults.ListenAddr, Timeout: defaults.Timeout, ServerURL: "http://localhost", Username: "testuser", Password: "testpass", TLSSkipVerify: false, }, }, { desc: "config from file", args: []string{ "test", "--config-file", "testdata/all.yml", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ ListenAddr: "127.0.0.10:9205", Timeout: 10 * time.Second, ServerURL: "http://localhost", Username: "testuser", Password: "testpass", TLSSkipVerify: false, }, }, { desc: "config and password from file", args: []string{ "test", "--config-file", "testdata/passwordfile.yml", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ ListenAddr: "127.0.0.10:9205", Timeout: 10 * time.Second, ServerURL: "http://localhost", Username: "testuser", Password: "testpass", TLSSkipVerify: false, }, }, { desc: "don't check tls certificates", args: []string{ "test", "--tls-skip-verify", "true", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ ListenAddr: ":9205", Timeout: 5 * time.Second, ServerURL: "", Username: "", Password: "", TLSSkipVerify: true, }, }, { desc: "env config", args: []string{ "test", }, env: map[string]string{ envListenAddress: "127.0.0.11:9205", envTimeout: "15s", envServerURL: "http://localhost", envUsername: "testuser", envPassword: "testpass", envTLSSkipVerify: "true", }, wantErr: nil, wantConfig: Config{ ListenAddr: "127.0.0.11:9205", Timeout: 15 * time.Second, ServerURL: "http://localhost", Username: "testuser", Password: "testpass", TLSSkipVerify: true, }, }, { desc: "minimal env", args: []string{ "test", }, env: map[string]string{ envServerURL: "http://localhost", envUsername: "testuser", envPassword: "testpass", }, wantErr: nil, wantConfig: Config{ ListenAddr: defaults.ListenAddr, Timeout: defaults.Timeout, ServerURL: "http://localhost", Username: "testuser", Password: "testpass", TLSSkipVerify: false, }, }, { desc: "auth token env, skip apps", args: []string{ "test", }, env: map[string]string{ envServerURL: "http://localhost", envAuthToken: "auth-token", envInfoApps: "true", }, wantErr: nil, wantConfig: Config{ ListenAddr: defaults.ListenAddr, Timeout: defaults.Timeout, ServerURL: "http://localhost", AuthToken: "auth-token", Info: InfoConfig{ Apps: true, }, }, }, { desc: "token file", args: []string{ "test", "--config-file", "testdata/authtoken.yml", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ ListenAddr: defaults.ListenAddr, Timeout: defaults.Timeout, ServerURL: "http://localhost", Username: "", Password: "", AuthToken: "auth-token", TLSSkipVerify: false, }, }, { desc: "show help", args: []string{ "test", "--help", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ RunMode: RunModeHelp, }, }, { desc: "show version", args: []string{ "test", "--version", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ RunMode: RunModeVersion, }, }, { desc: "login mode", args: []string{ "test", "--login", "--server", "http://localhost", }, env: map[string]string{}, wantErr: nil, wantConfig: Config{ ListenAddr: defaults.ListenAddr, Timeout: defaults.Timeout, ServerURL: "http://localhost", RunMode: RunModeLogin, }, }, { desc: "wrongflag", args: []string{ "test", "--unknown", }, env: map[string]string{}, wantErr: errors.New("error parsing flags: unknown flag: --unknown"), }, { desc: "env wrong duration", args: []string{ "test", }, env: map[string]string{ "NEXTCLOUD_TIMEOUT": "unknown", }, wantErr: errors.New("error reading environment variables: time: invalid duration \"unknown\""), }, { desc: "password from file error", args: []string{ "test", "--server", "http://localhost", "--password", "@testdata/notfound", }, env: map[string]string{}, wantErr: errors.New("can not read password file: open testdata/notfound: no such file or directory"), }, { desc: "config from file error", args: []string{ "test", "--config-file", "testdata/notfound.yml", }, env: map[string]string{}, wantErr: errors.New("error reading configuration file: open testdata/notfound.yml: no such file or directory"), }, { desc: "fail parsing tlsSkipVerify env", args: []string{ "test", }, env: map[string]string{ envTLSSkipVerify: "invalid", }, wantErr: errors.New(`error reading environment variables: can not parse value for "NEXTCLOUD_TLS_SKIP_VERIFY": invalid`), }, { desc: "fail parsing infoSkipApps env", args: []string{ "test", }, env: map[string]string{ envInfoApps: "invalid", }, wantErr: errors.New(`error reading environment variables: can not parse value for "NEXTCLOUD_INFO_APPS": invalid`), }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() config, err := parseConfig(tc.args, testEnv(tc.env)) if !testutil.EqualErrorMessage(err, tc.wantErr) { t.Errorf("got error %q, want %q", err, tc.wantErr) } if err != nil { return } if diff := cmp.Diff(config, tc.wantConfig); diff != "" { t.Errorf("config differs: -got +want\n%s", diff) } }) } } func TestConfigValidate(t *testing.T) { tt := []struct { desc string config Config wantErr error }{ { desc: "minimal", config: Config{ ServerURL: "https://example.com", Username: "exporter", Password: "testpass", }, wantErr: nil, }, { desc: "auth token", config: Config{ ServerURL: "https://example.com", AuthToken: "auth-token", }, wantErr: nil, }, { desc: "no url", config: Config{ Username: "exporter", Password: "testpass", }, wantErr: errValidateNoServerURL, }, { desc: "auth help", config: Config{ ServerURL: "https://example.com", }, wantErr: errValidateNoAuth, }, { desc: "no username", config: Config{ ServerURL: "https://example.com", Password: "testpass", }, wantErr: errValidateNoUsername, }, { desc: "no password", config: Config{ ServerURL: "https://example.com", Username: "exporter", }, wantErr: errValidateNoPassword, }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() err := tc.config.Validate() if !testutil.EqualErrorMessage(err, tc.wantErr) { t.Errorf("got error %q, want %q", err, tc.wantErr) } }) } } prometheus-nextcloud-exporter-0.8.0/internal/config/testdata/000077500000000000000000000000001475353242000244625ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/internal/config/testdata/all.yml000066400000000000000000000001531475353242000257540ustar00rootroot00000000000000listenAddress: 127.0.0.10:9205 timeout: 10s server: http://localhost username: testuser password: testpass prometheus-nextcloud-exporter-0.8.0/internal/config/testdata/authtoken.yml000066400000000000000000000000571475353242000272110ustar00rootroot00000000000000server: http://localhost authToken: auth-token prometheus-nextcloud-exporter-0.8.0/internal/config/testdata/password000066400000000000000000000000111475353242000262370ustar00rootroot00000000000000testpass prometheus-nextcloud-exporter-0.8.0/internal/config/testdata/passwordfile.yml000066400000000000000000000001671475353242000277130ustar00rootroot00000000000000listenAddress: 127.0.0.10:9205 timeout: 10s server: http://localhost username: testuser password: "@testdata/password" prometheus-nextcloud-exporter-0.8.0/internal/login/000077500000000000000000000000001475353242000225145ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/internal/login/login.go000066400000000000000000000115231475353242000241550ustar00rootroot00000000000000package login import ( "crypto/tls" "encoding/json" "fmt" "io" "net/http" "strconv" "strings" "time" "github.com/sirupsen/logrus" ) const ( statusPath = "/status.php" minimumMajorVersion = 16 loginPath = "/index.php/login/v2" pollInterval = time.Second contentType = "application/x-www-form-urlencoded" ) type loginInfo struct { LoginURL string `json:"login"` PollInfo pollInfo `json:"poll"` } type pollInfo struct { Token string `json:"token"` Endpoint string `json:"endpoint"` } type passwordInfo struct { Server string `json:"server"` LoginName string `json:"loginName"` AppPassword string `json:"appPassword"` } // Login contains the login information gathered during the login session. type Login struct { Username string Password string } // Client can be used to start an interactive login session with a Nextcloud server. type Client struct { log logrus.FieldLogger userAgent string serverURL string client *http.Client sleepFunc func() } // Init creates a new LoginClient. The session can then be started using StartInteractive. func Init(log logrus.FieldLogger, userAgent, serverURL string, tlsSkipVerify bool) *Client { return &Client{ log: log, userAgent: userAgent, serverURL: serverURL, client: &http.Client{ Timeout: 30 * time.Second, Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: tlsSkipVerify, }, }, }, sleepFunc: func() { time.Sleep(pollInterval) }, } } // StartInteractive starts an interactive login session for the Nextcloud server and user. // The end-result of this is an app-password for the exporter which should be used instead of a user password. func (c *Client) StartInteractive() error { version, err := c.getMajorVersion() if err != nil { return fmt.Errorf("error getting version: %w", err) } if version < minimumMajorVersion { return fmt.Errorf("Nextcloud version too old for login: %d Minimum: %d", version, minimumMajorVersion) } info, err := c.getLoginInfo() if err != nil { return fmt.Errorf("error getting login info: %w", err) } c.log.Infof("Please open this URL in a browser: %s", info.LoginURL) c.log.Infoln("Waiting for login ... (Ctrl-C to abort)") login, err := c.pollLogin(info.PollInfo) if err != nil { return fmt.Errorf("error during poll: %w", err) } c.log.Infof("Username: %s", login.Username) c.log.Infof("Password: %s", login.Password) return nil } func (c *Client) doRequest(method, url string, body io.Reader) (*http.Response, error) { req, err := http.NewRequest(method, url, body) if err != nil { return nil, fmt.Errorf("can not create request: %w", err) } req.Header.Set("User-Agent", c.userAgent) if body != nil { req.Header.Set("Content-Type", contentType) } res, err := c.client.Do(req) if err != nil { return nil, fmt.Errorf("error connecting: %w", err) } return res, nil } func (c *Client) getMajorVersion() (int, error) { statusURL := c.serverURL + statusPath res, err := c.doRequest(http.MethodGet, statusURL, nil) if err != nil { return 0, fmt.Errorf("error connecting: %w", err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { return 0, fmt.Errorf("non-ok status: %d", res.StatusCode) } var status struct { Version string `json:"version"` } if err := json.NewDecoder(res.Body).Decode(&status); err != nil { return 0, fmt.Errorf("error decoding status: %w", err) } tokens := strings.SplitN(status.Version, ".", 2) version, err := strconv.Atoi(tokens[0]) if err != nil { return 0, fmt.Errorf("can not parse %q as version: %w", status.Version, err) } return version, nil } func (c *Client) getLoginInfo() (loginInfo, error) { loginURL := c.serverURL + loginPath res, err := c.doRequest(http.MethodPost, loginURL, nil) if err != nil { return loginInfo{}, fmt.Errorf("error connecting: %w", err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { return loginInfo{}, fmt.Errorf("non-ok status: %d", res.StatusCode) } var result loginInfo if err := json.NewDecoder(res.Body).Decode(&result); err != nil { return loginInfo{}, fmt.Errorf("error decoding login info: %w", err) } return result, nil } func (c *Client) pollLogin(info pollInfo) (Login, error) { body := fmt.Sprintf("token=%s", info.Token) c.log.Debugf("poll endpoint: %s", info.Endpoint) for { c.sleepFunc() reader := strings.NewReader(body) res, err := c.doRequest(http.MethodPost, info.Endpoint, reader) if err != nil { continue } defer res.Body.Close() if res.StatusCode != http.StatusOK { c.log.Debugf("poll status: %d", res.StatusCode) continue } var password passwordInfo if err := json.NewDecoder(res.Body).Decode(&password); err != nil { return Login{}, fmt.Errorf("error decoding password info: %w", err) } return Login{ Username: password.LoginName, Password: password.AppPassword, }, nil } } prometheus-nextcloud-exporter-0.8.0/internal/login/login_test.go000066400000000000000000000102251475353242000252120ustar00rootroot00000000000000package login import ( "errors" "fmt" "net/http" "net/http/httptest" "testing" "github.com/google/go-cmp/cmp" "github.com/sirupsen/logrus" "github.com/xperimental/nextcloud-exporter/internal/testutil" ) func testClient(url string) *Client { return &Client{ log: logrus.New(), client: &http.Client{}, serverURL: url, sleepFunc: func() {}, } } func testHandler(status int, body string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(status) fmt.Fprintln(w, body) }) } func TestGetMajorVersion(t *testing.T) { tt := []struct { desc string testHandler http.Handler wantErr error wantVersion int }{ { desc: "success", testHandler: testHandler(http.StatusOK, `{"version": "18.0.2"}`), wantVersion: 18, }, { desc: "parse error", testHandler: testHandler(http.StatusOK, ``), wantErr: errors.New("error decoding status: EOF"), }, { desc: "error version", testHandler: testHandler(http.StatusOK, `{"version": "unparseable"}`), wantErr: errors.New(`can not parse "unparseable" as version: strconv.Atoi: parsing "unparseable": invalid syntax`), }, { desc: "error http", testHandler: testHandler(http.StatusInternalServerError, "test error"), wantErr: errors.New("non-ok status: 500"), }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() s := httptest.NewServer(tc.testHandler) defer s.Close() c := testClient(s.URL) version, err := c.getMajorVersion() if !testutil.EqualErrorMessage(err, tc.wantErr) { t.Errorf("got error %q, want %q", err, tc.wantErr) } if err != nil { return } if version != tc.wantVersion { t.Errorf("got version %d, want %d", version, tc.wantVersion) } }) } } func TestGetLoginInfo(t *testing.T) { tt := []struct { desc string testHandler http.Handler wantErr error wantInfo loginInfo }{ { desc: "success", testHandler: testHandler(http.StatusOK, `{"login": "http://localhost/login", "poll": {"token": "token", "endpoint": "http://localhost/poll"}}`), wantInfo: loginInfo{ LoginURL: "http://localhost/login", PollInfo: pollInfo{ Token: "token", Endpoint: "http://localhost/poll", }, }, }, { desc: "parse error", testHandler: testHandler(http.StatusOK, ``), wantErr: errors.New("error decoding login info: EOF"), }, { desc: "error http", testHandler: testHandler(http.StatusInternalServerError, "test error"), wantErr: errors.New("non-ok status: 500"), }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() s := httptest.NewServer(tc.testHandler) defer s.Close() c := testClient(s.URL) info, err := c.getLoginInfo() if !testutil.EqualErrorMessage(err, tc.wantErr) { t.Errorf("got error %q, want %q", err, tc.wantErr) } if err != nil { return } if diff := cmp.Diff(info, tc.wantInfo); diff != "" { t.Errorf("info differs: -got +want\n%s", diff) } }) } } func TestPollPassword(t *testing.T) { tt := []struct { desc string testHandler http.Handler pollInfo pollInfo wantErr error wantLogin Login }{ { desc: "success", testHandler: testHandler(http.StatusOK, `{"loginName": "username", "appPassword": "password"}`), wantLogin: Login{ Username: "username", Password: "password", }, }, { desc: "parse error", testHandler: testHandler(http.StatusOK, ``), wantErr: errors.New("error decoding password info: EOF"), }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() s := httptest.NewServer(tc.testHandler) defer s.Close() tc.pollInfo.Endpoint = s.URL c := testClient("") login, err := c.pollLogin(tc.pollInfo) if !testutil.EqualErrorMessage(err, tc.wantErr) { t.Errorf("got error %q, want %q", err, tc.wantErr) } if err != nil { return } if diff := cmp.Diff(login, tc.wantLogin); diff != "" { t.Errorf("login differs: -got +want\n%s", diff) } }) } } prometheus-nextcloud-exporter-0.8.0/internal/metrics/000077500000000000000000000000001475353242000230525ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/internal/metrics/collector.go000066400000000000000000000226321475353242000253740ustar00rootroot00000000000000package metrics import ( "fmt" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" "github.com/xperimental/nextcloud-exporter/internal/client" "github.com/xperimental/nextcloud-exporter/serverinfo" ) const ( metricPrefix = "nextcloud_" labelErrorCauseOther = "other" labelErrorCauseAuth = "auth" labelErrorCauseRatelimit = "ratelimit" ) var ( systemInfoDesc = prometheus.NewDesc( metricPrefix+"system_info", "Contains meta information about Nextcloud as labels. Value is always 1.", []string{"version"}, nil) systemUpdateAvailableDesc = prometheus.NewDesc( metricPrefix+"system_update_available", "Contains information whether a system update is available (0 = no, 1 = yes). The available_version label contains the latest available nextcloud version, whereas the version label contains the current installed nextcloud version.", []string{"version", "available_version"}, nil) appsInstalledDesc = prometheus.NewDesc( metricPrefix+"apps_installed_total", "Number of currently installed apps", nil, nil) appsUpdatesDesc = prometheus.NewDesc( metricPrefix+"apps_updates_available_total", "Number of apps that have available updates", nil, nil) usersDesc = prometheus.NewDesc( metricPrefix+"users_total", "Number of users of the instance.", nil, nil) filesDesc = prometheus.NewDesc( metricPrefix+"files_total", "Number of files served by the instance.", nil, nil) freeSpaceDesc = prometheus.NewDesc( metricPrefix+"free_space_bytes", "Free disk space in data directory in bytes.", nil, nil) sharesDesc = prometheus.NewDesc( metricPrefix+"shares_total", "Number of shares by type.", []string{"type"}, nil) federationsDesc = prometheus.NewDesc( metricPrefix+"shares_federated_total", "Number of federated shares by direction.", []string{"direction"}, nil) activeUsersDesc = prometheus.NewDesc( metricPrefix+"active_users_total", "Number of active users for the last five minutes.", nil, nil) hourlyActiveUsersDesc = prometheus.NewDesc( metricPrefix+"active_users_hourly_total", "Number of active users in the last hour.", nil, nil) dailyActiveUsersDesc = prometheus.NewDesc( metricPrefix+"active_users_daily_total", "Number of active users in the last 24 hours.", nil, nil) phpInfoDesc = prometheus.NewDesc( metricPrefix+"php_info", "Contains meta information about PHP as labels. Value is always 1.", []string{"version"}, nil) phpMemoryLimitDesc = prometheus.NewDesc( metricPrefix+"php_memory_limit_bytes", "Configured PHP memory limit in bytes.", nil, nil) phpMaxUploadSizeDesc = prometheus.NewDesc( metricPrefix+"php_upload_max_size_bytes", "Configured maximum upload size in bytes.", nil, nil) databaseInfoDesc = prometheus.NewDesc( metricPrefix+"database_info", "Contains meta information about the database as labels. Value is always 1.", []string{"version", "type"}, nil) databaseSizeDesc = prometheus.NewDesc( metricPrefix+"database_size_bytes", "Size of database in bytes as reported from engine.", nil, nil) ) type nextcloudCollector struct { log logrus.FieldLogger infoClient client.InfoClient appsMetrics bool updateMetrics bool upMetric prometheus.Gauge scrapeErrorsMetric *prometheus.CounterVec } func RegisterCollector(log logrus.FieldLogger, infoClient client.InfoClient, appsMetrics bool, updateMetrics bool) error { c := &nextcloudCollector{ log: log, infoClient: infoClient, appsMetrics: appsMetrics, updateMetrics: updateMetrics, upMetric: prometheus.NewGauge(prometheus.GaugeOpts{ Name: metricPrefix + "up", Help: "Indicates if the metrics could be scraped by the exporter.", }), scrapeErrorsMetric: prometheus.NewCounterVec(prometheus.CounterOpts{ Name: metricPrefix + "scrape_errors_total", Help: "Counts the number of scrape errors by this collector.", }, []string{"cause"}), } return prometheus.Register(c) } func (c *nextcloudCollector) Describe(ch chan<- *prometheus.Desc) { c.upMetric.Describe(ch) c.scrapeErrorsMetric.Describe(ch) ch <- usersDesc ch <- filesDesc ch <- freeSpaceDesc ch <- sharesDesc ch <- federationsDesc ch <- activeUsersDesc ch <- hourlyActiveUsersDesc ch <- dailyActiveUsersDesc } func (c *nextcloudCollector) Collect(ch chan<- prometheus.Metric) { if err := c.collectNextcloud(ch); err != nil { c.log.Errorf("Error during scrape: %s", err) cause := labelErrorCauseOther if err == client.ErrNotAuthorized { cause = labelErrorCauseAuth } else if err == client.ErrRatelimit { cause = labelErrorCauseRatelimit } c.scrapeErrorsMetric.WithLabelValues(cause).Inc() c.upMetric.Set(0) } else { c.upMetric.Set(1) } c.upMetric.Collect(ch) c.scrapeErrorsMetric.Collect(ch) } func (c *nextcloudCollector) collectNextcloud(ch chan<- prometheus.Metric) error { status, err := c.infoClient() if err != nil { return err } return readMetrics(ch, status, c.appsMetrics, c.updateMetrics) } func readMetrics(ch chan<- prometheus.Metric, status *serverinfo.ServerInfo, appsMetrics bool, updateMetrics bool) error { if err := collectSimpleMetrics(ch, status, appsMetrics); err != nil { return err } if updateMetrics { if err := collectUpdate(ch, status); err != nil { return err } } if err := collectShares(ch, status.Data.Nextcloud.Shares); err != nil { return err } if err := collectFederatedShares(ch, status.Data.Nextcloud.Shares); err != nil { return err } systemInfo := []string{ status.Data.Nextcloud.System.Version, } if err := collectInfoMetric(ch, systemInfoDesc, systemInfo); err != nil { return err } phpInfo := []string{ status.Data.Server.PHP.Version, } if err := collectInfoMetric(ch, phpInfoDesc, phpInfo); err != nil { return err } databaseInfo := []string{ status.Data.Server.Database.Version, status.Data.Server.Database.Type, } if err := collectInfoMetric(ch, databaseInfoDesc, databaseInfo); err != nil { return err } return nil } type simpleMetric struct { desc *prometheus.Desc value float64 } func collectSimpleMetrics(ch chan<- prometheus.Metric, status *serverinfo.ServerInfo, appsMetrics bool) error { metrics := []simpleMetric{ { desc: usersDesc, value: float64(status.Data.Nextcloud.Storage.Users), }, { desc: filesDesc, value: float64(status.Data.Nextcloud.Storage.Files), }, { desc: freeSpaceDesc, value: status.Data.Nextcloud.System.FreeSpace, }, { desc: activeUsersDesc, value: float64(status.Data.ActiveUsers.Last5Minutes), }, { desc: hourlyActiveUsersDesc, value: float64(status.Data.ActiveUsers.LastHour), }, { desc: dailyActiveUsersDesc, value: float64(status.Data.ActiveUsers.LastDay), }, { desc: phpMemoryLimitDesc, value: float64(status.Data.Server.PHP.MemoryLimit), }, { desc: phpMaxUploadSizeDesc, value: float64(status.Data.Server.PHP.UploadMaxFilesize), }, { desc: databaseSizeDesc, value: float64(status.Data.Server.Database.Size), }, } if appsMetrics { metrics = append(metrics, []simpleMetric{ { desc: appsInstalledDesc, value: float64(status.Data.Nextcloud.System.Apps.Installed), }, { desc: appsUpdatesDesc, value: float64(status.Data.Nextcloud.System.Apps.AvailableUpdates), }, }...) } for _, m := range metrics { metric, err := prometheus.NewConstMetric(m.desc, prometheus.GaugeValue, m.value) if err != nil { return fmt.Errorf("error creating metric for %s: %w", m.desc, err) } ch <- metric } return nil } func collectUpdate(ch chan<- prometheus.Metric, status *serverinfo.ServerInfo) error { systemInfo := status.Data.Nextcloud.System updateAvailableValue := 0.0 // Fix small bug: its indicated as "true" even if there is no real update available. if systemInfo.Update.Available && systemInfo.Version != systemInfo.Update.AvailableVersion { updateAvailableValue = 1.0 } metric, err := prometheus.NewConstMetric(systemUpdateAvailableDesc, prometheus.GaugeValue, updateAvailableValue, systemInfo.Version, systemInfo.Update.AvailableVersion) if err != nil { return fmt.Errorf("error creating metric for %s: %w", systemUpdateAvailableDesc, err) } ch <- metric return nil } func collectShares(ch chan<- prometheus.Metric, shares serverinfo.Shares) error { values := make(map[string]float64) values["user"] = float64(shares.SharesUser) values["group"] = float64(shares.SharesGroups) values["authlink"] = float64(shares.SharesLink - shares.SharesLinkNoPassword) values["link"] = float64(shares.SharesLink) values["mail"] = float64(shares.SharesMail) values["room"] = float64(shares.SharesRoom) return collectMap(ch, sharesDesc, values) } func collectFederatedShares(ch chan<- prometheus.Metric, shares serverinfo.Shares) error { values := make(map[string]float64) values["sent"] = float64(shares.FedSent) values["received"] = float64(shares.FedReceived) return collectMap(ch, federationsDesc, values) } func collectMap(ch chan<- prometheus.Metric, desc *prometheus.Desc, labelValueMap map[string]float64) error { for k, v := range labelValueMap { metric, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, v, k) if err != nil { return fmt.Errorf("error creating shares metric for %s: %w", k, err) } ch <- metric } return nil } func collectInfoMetric(ch chan<- prometheus.Metric, desc *prometheus.Desc, labelValues []string) error { metric, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, 1, labelValues...) if err != nil { return err } ch <- metric return nil } prometheus-nextcloud-exporter-0.8.0/internal/metrics/info.go000066400000000000000000000006711475353242000243400ustar00rootroot00000000000000package metrics import ( "github.com/prometheus/client_golang/prometheus" ) func RegisterInfoMetric(version, gitCommit string) error { infoMetric := prometheus.NewGauge(prometheus.GaugeOpts{ Name: metricPrefix + "exporter_info", Help: "Information about the nextcloud-exporter.", ConstLabels: prometheus.Labels{ "version": version, "commit": gitCommit, }, }) infoMetric.Set(1) return prometheus.Register(infoMetric) } prometheus-nextcloud-exporter-0.8.0/internal/testutil/000077500000000000000000000000001475353242000232615ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/internal/testutil/testutil.go000066400000000000000000000004671475353242000254740ustar00rootroot00000000000000package testutil import ( "strings" ) // EqualErrorMessage compares two errors by just comparing their messages. func EqualErrorMessage(a, b error) bool { aMsg := "" if a != nil { aMsg = a.Error() } bMsg := "" if b != nil { bMsg = b.Error() } return strings.Compare(aMsg, bMsg) == 0 } prometheus-nextcloud-exporter-0.8.0/internal/testutil/testutil_test.go000066400000000000000000000023641475353242000265310ustar00rootroot00000000000000package testutil import ( "errors" "testing" ) type testError struct{} func (e testError) Error() string { return "test message" } func TestEqualErrorMessage(t *testing.T) { tt := []struct { desc string a error b error wantEqual bool }{ { desc: "two nil", a: nil, b: nil, wantEqual: true, }, { desc: "a not nil", a: errors.New("error A"), b: nil, wantEqual: false, }, { desc: "b not nil", a: nil, b: errors.New("error B"), wantEqual: false, }, { desc: "both not nil", a: errors.New("error A"), b: errors.New("error B"), wantEqual: false, }, { desc: "equal message, same type", a: errors.New("test message"), b: errors.New("test message"), wantEqual: true, }, { desc: "equal message, different type", a: errors.New("test message"), b: testError{}, wantEqual: true, }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() equal := EqualErrorMessage(tc.a, tc.b) if equal != tc.wantEqual { t.Errorf("got equal %v, want %v", equal, tc.wantEqual) } }) } } prometheus-nextcloud-exporter-0.8.0/main.go000066400000000000000000000051421475353242000210450ustar00rootroot00000000000000package main import ( "fmt" "net/http" "os" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sirupsen/logrus" "github.com/xperimental/nextcloud-exporter/internal/client" "github.com/xperimental/nextcloud-exporter/internal/config" "github.com/xperimental/nextcloud-exporter/internal/login" "github.com/xperimental/nextcloud-exporter/internal/metrics" "github.com/xperimental/nextcloud-exporter/serverinfo" ) var ( // Version contains the version as set during the build. Version = "" // GitCommit contains the git commit hash set during the build. GitCommit = "" log = &logrus.Logger{ Out: os.Stderr, Formatter: &logrus.TextFormatter{ DisableTimestamp: true, }, Hooks: make(logrus.LevelHooks), Level: logrus.InfoLevel, ExitFunc: os.Exit, ReportCaller: false, } ) func main() { cfg, err := config.Get() if err != nil { log.Fatalf("Error loading configuration: %s", err) } if cfg.RunMode == config.RunModeHelp { return } if cfg.RunMode == config.RunModeVersion { fmt.Println(Version) return } log.Infof("nextcloud-exporter %s", Version) userAgent := fmt.Sprintf("nextcloud-exporter/%s", Version) if cfg.RunMode == config.RunModeLogin { if cfg.ServerURL == "" { log.Fatalf("Need to specify --server for login.") } loginClient := login.Init(log, userAgent, cfg.ServerURL, cfg.TLSSkipVerify) log.Infof("Starting interactive login on: %s", cfg.ServerURL) if err := loginClient.StartInteractive(); err != nil { log.Fatalf("Error during login: %s", err) } return } if err := cfg.Validate(); err != nil { log.Fatalf("Invalid configuration: %s", err) } if cfg.AuthToken == "" { log.Infof("Nextcloud server: %s User: %s", cfg.ServerURL, cfg.Username) } else { log.Infof("Nextcloud server: %s Authentication using token.", cfg.ServerURL) } infoURL := serverinfo.InfoURL(cfg.ServerURL, !cfg.Info.Apps, !cfg.Info.Update) if cfg.TLSSkipVerify { log.Warn("HTTPS certificate verification is disabled.") } infoClient := client.New(infoURL, cfg.Username, cfg.Password, cfg.AuthToken, cfg.Timeout, userAgent, cfg.TLSSkipVerify) if err := metrics.RegisterCollector(log, infoClient, cfg.Info.Apps, cfg.Info.Update); err != nil { log.Fatalf("Failed to register collector: %s", err) } if err := metrics.RegisterInfoMetric(Version, GitCommit); err != nil { log.Fatalf("Failed to register info metric: %s", err) } http.Handle("/metrics", promhttp.Handler()) http.Handle("/", http.RedirectHandler("/metrics", http.StatusFound)) log.Infof("Listen on %s...", cfg.ListenAddr) log.Fatal(http.ListenAndServe(cfg.ListenAddr, nil)) } prometheus-nextcloud-exporter-0.8.0/serverinfo/000077500000000000000000000000001475353242000217525ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/serverinfo/parse.go000066400000000000000000000005301475353242000234110ustar00rootroot00000000000000package serverinfo import ( "encoding/json" "io" ) // ParseJSON reads ServerInfo from a Reader in JSON format. func ParseJSON(r io.Reader) (*ServerInfo, error) { result := struct { ServerInfo ServerInfo `json:"ocs"` }{} if err := json.NewDecoder(r).Decode(&result); err != nil { return nil, err } return &result.ServerInfo, nil } prometheus-nextcloud-exporter-0.8.0/serverinfo/parse_test.go000066400000000000000000000010561475353242000244540ustar00rootroot00000000000000package serverinfo import ( "os" "testing" ) func TestParseJSON(t *testing.T) { inputFiles := []string{ "info.json", "negative-space.json", "na-values.json", "nc22.json", "large-freespace.json", } for _, inputFile := range inputFiles { inputFile := inputFile t.Run(inputFile, func(t *testing.T) { t.Parallel() reader, err := os.Open("testdata/" + inputFile) if err != nil { t.Fatalf("error opening test data: %s", err) } if _, err := ParseJSON(reader); err != nil { t.Errorf("got error %q", err) } }) } } prometheus-nextcloud-exporter-0.8.0/serverinfo/serverinfo.go000066400000000000000000000157411475353242000244730ustar00rootroot00000000000000package serverinfo import ( "encoding/json" "encoding/xml" "fmt" "strconv" ) // ServerInfo contains the complete data received from the server. type ServerInfo struct { Meta Meta `json:"meta"` Data Data `json:"data"` } // Meta contains meta information about the result. type Meta struct { Status string `json:"status"` StatusCode int `json:"statuscode"` Message string `json:"message"` } // Data contains the status information about the instance. type Data struct { Nextcloud Nextcloud `json:"nextcloud"` Server Server `json:"server"` ActiveUsers ActiveUsers `json:"activeUsers"` } // Nextcloud contains information about the nextcloud installation. type Nextcloud struct { System System `json:"system"` Storage Storage `json:"storage"` Shares Shares `json:"shares"` } // System contains nextcloud configuration and system information. type System struct { Version string `json:"version"` Theme string `json:"theme"` EnableAvatars bool `json:"enable_avatars"` EnablePreviews bool `json:"enable_previews"` MemcacheLocal string `json:"memcache.local"` MemcacheDistributed string `json:"memcache.distributed"` MemcacheLocking string `json:"memcache.locking"` FilelockingEnabled bool `json:"filelocking.enabled"` Debug bool `json:"debug"` FreeSpace float64 `json:"freespace"` Apps Apps `json:"apps"` Update Update `json:"update"` } const boolYes = "yes" func (s *System) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { var raw struct { Version string `xml:"version"` Theme string `xml:"theme"` EnableAvatars string `xml:"enable_avatars"` EnablePreviews string `xml:"enable_previews"` MemcacheLocal string `xml:"memcache.local"` MemcacheDistributed string `xml:"memcache.distributed"` MemcacheLocking string `xml:"memcache.locking"` FilelockingEnabled string `xml:"filelocking.enabled"` Debug string `xml:"debug"` FreeSpace float64 `xml:"freespace"` Apps Apps `xml:"apps"` Update Update `xml:"update"` } if err := d.DecodeElement(&raw, &start); err != nil { return err } s.Version = raw.Version s.Theme = raw.Theme s.EnableAvatars = raw.EnableAvatars == boolYes s.EnablePreviews = raw.EnablePreviews == boolYes s.MemcacheLocal = raw.MemcacheLocal s.MemcacheDistributed = raw.MemcacheDistributed s.MemcacheLocking = raw.MemcacheLocking s.FilelockingEnabled = raw.FilelockingEnabled == boolYes s.Debug = raw.Debug == boolYes s.FreeSpace = raw.FreeSpace s.Apps = raw.Apps s.Update = raw.Update return nil } func (s *System) UnmarshalJSON(data []byte) error { var raw struct { Version string `json:"version"` Theme string `json:"theme"` EnableAvatars string `json:"enable_avatars"` EnablePreviews string `json:"enable_previews"` MemcacheLocal string `json:"memcache.local"` MemcacheDistributed string `json:"memcache.distributed"` MemcacheLocking string `json:"memcache.locking"` FilelockingEnabled string `json:"filelocking.enabled"` Debug string `json:"debug"` FreeSpace float64 `json:"freespace"` Apps Apps `json:"apps"` Update Update `json:"update"` } if err := json.Unmarshal(data, &raw); err != nil { return err } s.Version = raw.Version s.Theme = raw.Theme s.EnableAvatars = raw.EnableAvatars == boolYes s.EnablePreviews = raw.EnablePreviews == boolYes s.MemcacheLocal = raw.MemcacheLocal s.MemcacheDistributed = raw.MemcacheDistributed s.MemcacheLocking = raw.MemcacheLocking s.FilelockingEnabled = raw.FilelockingEnabled == boolYes s.Debug = raw.Debug == boolYes s.FreeSpace = raw.FreeSpace s.Apps = raw.Apps s.Update = raw.Update return nil } // Apps contains information about installed apps and updates. type Apps struct { Installed uint `json:"num_installed"` AvailableUpdates uint `json:"num_updates_available"` } // Update contains information about Nextcloud system updates. type Update struct { Available bool `json:"available"` AvailableVersion string `json:"available_version"` } // Storage contains information about the nextcloud storage system. type Storage struct { Users uint `json:"num_users"` Files uint `json:"num_files"` Storages uint `json:"num_storages"` StoragesLocal uint `json:"num_storages_local"` StoragesHome uint `json:"num_storages_home"` StoragesOther uint `json:"num_storages_other"` } // Shares contains information about nextcloud shares. type Shares struct { SharesTotal uint `json:"num_shares"` SharesUser uint `json:"num_shares_user"` SharesGroups uint `json:"num_shares_groups"` SharesLink uint `json:"num_shares_link"` SharesLinkNoPassword uint `json:"num_shares_link_no_password"` SharesMail uint `json:"num_shares_mail"` SharesRoom uint `json:"num_shares_room"` FedSent uint `json:"num_fed_shares_sent"` FedReceived uint `json:"num_fed_shares_received"` // 2 // 4 // 2 // 2 // 3 // 1 } // Server contains information about the servers running nextcloud. type Server struct { Webserver string `json:"webserver"` PHP PHP `json:"php"` Database Database `json:"database"` } // PHP contains information about the PHP installation. type PHP struct { Version string `json:"version"` MemoryLimit int64 `json:"memory_limit"` MaxExecutionTime uint `json:"max_execution_time"` UploadMaxFilesize int64 `json:"upload_max_filesize"` } // Database contains information about the database used by nextcloud. type Database struct { Type string `json:"type"` Version string `json:"version"` Size uint64 `json:"size"` } func (d *Database) UnmarshalJSON(data []byte) error { var raw struct { Type string `json:"type"` Version string `json:"version"` Size interface{} `json:"size"` } if err := json.Unmarshal(data, &raw); err != nil { return err } d.Type = raw.Type d.Version = raw.Version switch rawSize := raw.Size.(type) { case float64: if rawSize < 0 { return fmt.Errorf("negative value for database.size: %f", rawSize) } d.Size = uint64(rawSize) case string: parsedSize, err := strconv.ParseUint(rawSize, 10, 64) if err != nil { return fmt.Errorf("can not parse database.size %q: %w", rawSize, err) } d.Size = parsedSize default: return fmt.Errorf("unexpected type for database.size: %t", rawSize) } return nil } // ActiveUsers contains statistics about the active users. type ActiveUsers struct { Last5Minutes uint `json:"last5minutes"` LastHour uint `json:"last1hour"` LastDay uint `json:"last24hours"` } prometheus-nextcloud-exporter-0.8.0/serverinfo/testdata/000077500000000000000000000000001475353242000235635ustar00rootroot00000000000000prometheus-nextcloud-exporter-0.8.0/serverinfo/testdata/info.json000066400000000000000000000074161475353242000254210ustar00rootroot00000000000000{ "ocs": { "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, "data": { "nextcloud": { "system": { "version": "21.0.3.1", "theme": "", "enable_avatars": "yes", "enable_previews": "yes", "memcache.local": "\\OC\\Memcache\\APCu", "memcache.distributed": "none", "filelocking.enabled": "yes", "memcache.locking": "\\OC\\Memcache\\Redis", "debug": "no", "freespace": 7635480576, "cpuload": [ 0.08, 0.05, 0.06 ], "mem_total": 1986232, "mem_free": 1285532, "swap_total": 0, "swap_free": 0, "apps": { "num_installed": 42, "num_updates_available": 0, "app_updates": [] } }, "storage": { "num_users": 4, "num_files": 148948, "num_storages": 32, "num_storages_local": 3, "num_storages_home": 4, "num_storages_other": 25 }, "shares": { "num_shares": 10, "num_shares_user": 0, "num_shares_groups": 2, "num_shares_link": 4, "num_shares_mail": 1, "num_shares_room": 0, "num_shares_link_no_password": 4, "num_fed_shares_sent": 0, "num_fed_shares_received": 0, "permissions_3_1": "2", "permissions_3_17": "1", "permissions_4_17": "1", "permissions_1_31": "2", "permissions_2_31": "3", "permissions_3_31": "1" } }, "server": { "webserver": "Apache\/2.4.41 (Ubuntu)", "php": { "version": "7.4.3", "memory_limit": 536870912, "max_execution_time": 3600, "upload_max_filesize": 2097152, "opcache": { "opcache_enabled": true, "cache_full": false, "restart_pending": false, "restart_in_progress": false, "memory_usage": { "used_memory": 35866872, "free_memory": 98334320, "wasted_memory": 16536, "current_wasted_percentage": 0.012320280075073242 }, "interned_strings_usage": { "buffer_size": 6291008, "used_memory": 4225688, "free_memory": 2065320, "number_of_strings": 68439 }, "opcache_statistics": { "num_cached_scripts": 1818, "num_cached_keys": 3489, "max_cached_keys": 16229, "hits": 2725757, "start_time": 1627817478, "last_restart_time": 0, "oom_restarts": 0, "hash_restarts": 0, "manual_restarts": 0, "misses": 1830, "blacklist_misses": 0, "blacklist_miss_ratio": 0, "opcache_hit_rate": 99.93290773126576 } }, "apcu": { "cache": { "num_slots": 4099, "ttl": 0, "num_hits": 175992, "num_misses": 1948, "num_inserts": 2009, "num_entries": 599, "expunges": 0, "start_time": 1627817478, "mem_size": 295024, "memory_type": "mmap" }, "sma": { "num_seg": 1, "seg_size": 33554312, "avail_mem": 33206176 } } }, "database": { "type": "mysql", "version": "10.5.11", "size": 59457536 } }, "activeUsers": { "last5minutes": 1, "last1hour": 1, "last24hours": 2 } } } } prometheus-nextcloud-exporter-0.8.0/serverinfo/testdata/large-freespace.json000066400000000000000000000074271475353242000275150ustar00rootroot00000000000000{ "ocs": { "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, "data": { "nextcloud": { "system": { "version": "21.0.3.1", "theme": "", "enable_avatars": "yes", "enable_previews": "yes", "memcache.local": "\\OC\\Memcache\\APCu", "memcache.distributed": "none", "filelocking.enabled": "yes", "memcache.locking": "\\OC\\Memcache\\Redis", "debug": "no", "freespace": 9.2233720360673E+18, "cpuload": [ 0.08, 0.05, 0.06 ], "mem_total": 1986232, "mem_free": 1285532, "swap_total": 0, "swap_free": 0, "apps": { "num_installed": 42, "num_updates_available": 0, "app_updates": [] } }, "storage": { "num_users": 4, "num_files": 148948, "num_storages": 32, "num_storages_local": 3, "num_storages_home": 4, "num_storages_other": 25 }, "shares": { "num_shares": 10, "num_shares_user": 0, "num_shares_groups": 2, "num_shares_link": 4, "num_shares_mail": 1, "num_shares_room": 0, "num_shares_link_no_password": 4, "num_fed_shares_sent": 0, "num_fed_shares_received": 0, "permissions_3_1": "2", "permissions_3_17": "1", "permissions_4_17": "1", "permissions_1_31": "2", "permissions_2_31": "3", "permissions_3_31": "1" } }, "server": { "webserver": "Apache\/2.4.41 (Ubuntu)", "php": { "version": "7.4.3", "memory_limit": 536870912, "max_execution_time": 3600, "upload_max_filesize": 2097152, "opcache": { "opcache_enabled": true, "cache_full": false, "restart_pending": false, "restart_in_progress": false, "memory_usage": { "used_memory": 35866872, "free_memory": 98334320, "wasted_memory": 16536, "current_wasted_percentage": 0.012320280075073242 }, "interned_strings_usage": { "buffer_size": 6291008, "used_memory": 4225688, "free_memory": 2065320, "number_of_strings": 68439 }, "opcache_statistics": { "num_cached_scripts": 1818, "num_cached_keys": 3489, "max_cached_keys": 16229, "hits": 2725757, "start_time": 1627817478, "last_restart_time": 0, "oom_restarts": 0, "hash_restarts": 0, "manual_restarts": 0, "misses": 1830, "blacklist_misses": 0, "blacklist_miss_ratio": 0, "opcache_hit_rate": 99.93290773126576 } }, "apcu": { "cache": { "num_slots": 4099, "ttl": 0, "num_hits": 175992, "num_misses": 1948, "num_inserts": 2009, "num_entries": 599, "expunges": 0, "start_time": 1627817478, "mem_size": 295024, "memory_type": "mmap" }, "sma": { "num_seg": 1, "seg_size": 33554312, "avail_mem": 33206176 } } }, "database": { "type": "mysql", "version": "10.5.11", "size": 59457536 } }, "activeUsers": { "last5minutes": 1, "last1hour": 1, "last24hours": 2 } } } } prometheus-nextcloud-exporter-0.8.0/serverinfo/testdata/na-values.json000066400000000000000000000074221475353242000263560ustar00rootroot00000000000000{ "ocs": { "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, "data": { "nextcloud": { "system": { "version": "21.0.3.1", "theme": "", "enable_avatars": "yes", "enable_previews": "yes", "memcache.local": "\\OC\\Memcache\\APCu", "memcache.distributed": "none", "filelocking.enabled": "yes", "memcache.locking": "\\OC\\Memcache\\Redis", "debug": "no", "freespace": 7635480576, "cpuload": [ 0.08, 0.05, 0.06 ], "mem_total": "N/A", "mem_free": "N/A", "swap_total": "N/A", "swap_free": "N/A", "apps": { "num_installed": 42, "num_updates_available": 0, "app_updates": [] } }, "storage": { "num_users": 4, "num_files": 148948, "num_storages": 32, "num_storages_local": 3, "num_storages_home": 4, "num_storages_other": 25 }, "shares": { "num_shares": 10, "num_shares_user": 0, "num_shares_groups": 2, "num_shares_link": 4, "num_shares_mail": 1, "num_shares_room": 0, "num_shares_link_no_password": 4, "num_fed_shares_sent": 0, "num_fed_shares_received": 0, "permissions_3_1": "2", "permissions_3_17": "1", "permissions_4_17": "1", "permissions_1_31": "2", "permissions_2_31": "3", "permissions_3_31": "1" } }, "server": { "webserver": "Apache\/2.4.41 (Ubuntu)", "php": { "version": "7.4.3", "memory_limit": 536870912, "max_execution_time": 3600, "upload_max_filesize": 2097152, "opcache": { "opcache_enabled": true, "cache_full": false, "restart_pending": false, "restart_in_progress": false, "memory_usage": { "used_memory": 35866872, "free_memory": 98334320, "wasted_memory": 16536, "current_wasted_percentage": 0.012320280075073242 }, "interned_strings_usage": { "buffer_size": 6291008, "used_memory": 4225688, "free_memory": 2065320, "number_of_strings": 68439 }, "opcache_statistics": { "num_cached_scripts": 1818, "num_cached_keys": 3489, "max_cached_keys": 16229, "hits": 2725757, "start_time": 1627817478, "last_restart_time": 0, "oom_restarts": 0, "hash_restarts": 0, "manual_restarts": 0, "misses": 1830, "blacklist_misses": 0, "blacklist_miss_ratio": 0, "opcache_hit_rate": 99.93290773126576 } }, "apcu": { "cache": { "num_slots": 4099, "ttl": 0, "num_hits": 175992, "num_misses": 1948, "num_inserts": 2009, "num_entries": 599, "expunges": 0, "start_time": 1627817478, "mem_size": 295024, "memory_type": "mmap" }, "sma": { "num_seg": 1, "seg_size": 33554312, "avail_mem": 33206176 } } }, "database": { "type": "mysql", "version": "10.5.11", "size": 59457536 } }, "activeUsers": { "last5minutes": 1, "last1hour": 1, "last24hours": 2 } } } } prometheus-nextcloud-exporter-0.8.0/serverinfo/testdata/nc22.json000066400000000000000000000076021475353242000252270ustar00rootroot00000000000000{ "ocs": { "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, "data": { "nextcloud": { "system": { "version": "22.2.0.2", "theme": "", "enable_avatars": "yes", "enable_previews": "yes", "memcache.local": "\\OC\\Memcache\\Redis", "memcache.distributed": "\\OC\\Memcache\\Redis", "filelocking.enabled": "yes", "memcache.locking": "\\OC\\Memcache\\Redis", "debug": "no", "freespace": 12975042, "cpuload": [ 0.8, 0.4, 0.3 ], "mem_total": 394078, "mem_free": 184536, "swap_total": 52428, "swap_free": 3960, "apps": { "num_installed": 4, "num_updates_available": 0, "app_updates": [] } }, "storage": { "num_users": 3, "num_files": 412, "num_storages": 6, "num_storages_local": 4, "num_storages_home": 3, "num_storages_other": 2 }, "shares": { "num_shares": 8, "num_shares_user": 4, "num_shares_groups": 2, "num_shares_link": 7, "num_shares_mail": 0, "num_shares_room": 0, "num_shares_link_no_password": 7, "num_fed_shares_sent": 1, "num_fed_shares_received": 2, "permissions_0_1": "3", "permissions_3_1": "43", "permissions_1_15": "1", "permissions_2_15": "1", "permissions_3_15": "3", "permissions_3_17": "27", "permissions_0_31": "1", "permissions_1_31": "1", "permissions_2_31": "5", "permissions_3_31": "2", "permissions_6_31": "1" } }, "server": { "webserver": "nginx\/1.14.0", "php": { "version": "7.4.0", "memory_limit": 26843545, "max_execution_time": 360, "upload_max_filesize": 1677721, "opcache": { "opcache_enabled": true, "cache_full": false, "restart_pending": false, "restart_in_progress": false, "memory_usage": { "used_memory": 3928244, "free_memory": 9490738, "wasted_memory": 2789, "current_wasted_percentage": 0.020 }, "interned_strings_usage": { "buffer_size": 629100, "used_memory": 489804, "free_memory": 139296, "number_of_strings": 7795 }, "opcache_statistics": { "num_cached_scripts": 209, "num_cached_keys": 399, "max_cached_keys": 1622, "hits": 391187, "start_time": 1634933931, "last_restart_time": 0, "oom_restarts": 0, "hash_restarts": 0, "manual_restarts": 0, "misses": 210, "blacklist_misses": 0, "blacklist_miss_ratio": 0, "opcache_hit_rate": 99.994 } }, "apcu": { "cache": { "num_slots": 409, "ttl": 0, "num_hits": 0, "num_misses": 0, "num_inserts": 0, "num_entries": 0, "expunges": 0, "start_time": 1634933931, "mem_size": 0, "memory_type": "mmap" }, "sma": { "num_seg": 1, "seg_size": 335543, "avail_mem": 335213 } } }, "database": { "type": "mysql", "version": "10.5.12", "size": "30638080" } }, "activeUsers": { "last5minutes": 3, "last1hour": 3, "last24hours": 3 } } } } prometheus-nextcloud-exporter-0.8.0/serverinfo/testdata/negative-space.json000066400000000000000000000074061475353242000273600ustar00rootroot00000000000000{ "ocs": { "meta": { "status": "ok", "statuscode": 200, "message": "OK" }, "data": { "nextcloud": { "system": { "version": "21.0.3.1", "theme": "", "enable_avatars": "yes", "enable_previews": "yes", "memcache.local": "\\OC\\Memcache\\APCu", "memcache.distributed": "none", "filelocking.enabled": "yes", "memcache.locking": "\\OC\\Memcache\\Redis", "debug": "no", "freespace": -2, "cpuload": [ 0.08, 0.05, 0.06 ], "mem_total": 1986232, "mem_free": 1285532, "swap_total": 0, "swap_free": 0, "apps": { "num_installed": 42, "num_updates_available": 0, "app_updates": [] } }, "storage": { "num_users": 4, "num_files": 148948, "num_storages": 32, "num_storages_local": 3, "num_storages_home": 4, "num_storages_other": 25 }, "shares": { "num_shares": 10, "num_shares_user": 0, "num_shares_groups": 2, "num_shares_link": 4, "num_shares_mail": 1, "num_shares_room": 0, "num_shares_link_no_password": 4, "num_fed_shares_sent": 0, "num_fed_shares_received": 0, "permissions_3_1": "2", "permissions_3_17": "1", "permissions_4_17": "1", "permissions_1_31": "2", "permissions_2_31": "3", "permissions_3_31": "1" } }, "server": { "webserver": "Apache\/2.4.41 (Ubuntu)", "php": { "version": "7.4.3", "memory_limit": 536870912, "max_execution_time": 3600, "upload_max_filesize": 2097152, "opcache": { "opcache_enabled": true, "cache_full": false, "restart_pending": false, "restart_in_progress": false, "memory_usage": { "used_memory": 35866872, "free_memory": 98334320, "wasted_memory": 16536, "current_wasted_percentage": 0.012320280075073242 }, "interned_strings_usage": { "buffer_size": 6291008, "used_memory": 4225688, "free_memory": 2065320, "number_of_strings": 68439 }, "opcache_statistics": { "num_cached_scripts": 1818, "num_cached_keys": 3489, "max_cached_keys": 16229, "hits": 2725757, "start_time": 1627817478, "last_restart_time": 0, "oom_restarts": 0, "hash_restarts": 0, "manual_restarts": 0, "misses": 1830, "blacklist_misses": 0, "blacklist_miss_ratio": 0, "opcache_hit_rate": 99.93290773126576 } }, "apcu": { "cache": { "num_slots": 4099, "ttl": 0, "num_hits": 175992, "num_misses": 1948, "num_inserts": 2009, "num_entries": 599, "expunges": 0, "start_time": 1627817478, "mem_size": 295024, "memory_type": "mmap" }, "sma": { "num_seg": 1, "seg_size": 33554312, "avail_mem": 33206176 } } }, "database": { "type": "mysql", "version": "10.5.11", "size": 59457536 } }, "activeUsers": { "last5minutes": 1, "last1hour": 1, "last24hours": 2 } } } } prometheus-nextcloud-exporter-0.8.0/serverinfo/url.go000066400000000000000000000006121475353242000231020ustar00rootroot00000000000000package serverinfo import ( "fmt" ) const ( infoPathFormat = "%s/ocs/v2.php/apps/serverinfo/api/v1/info?format=json&skipApps=%v&skipUpdate=%v" ) // InfoURL constructs the URL of the info endpoint from the server base URL and optional parameters. func InfoURL(serverURL string, skipApps bool, skipUpdate bool) string { return fmt.Sprintf(infoPathFormat, serverURL, skipApps, skipUpdate) } prometheus-nextcloud-exporter-0.8.0/serverinfo/url_test.go000066400000000000000000000037031475353242000241450ustar00rootroot00000000000000package serverinfo import ( "testing" ) func TestInfoURL(t *testing.T) { tt := []struct { desc string serverURL string skipApps bool skipUpdate bool wantURL string }{ { desc: "do not skip apps and do not skip update (implicit)", serverURL: "https://nextcloud.example.com", wantURL: "https://nextcloud.example.com/ocs/v2.php/apps/serverinfo/api/v1/info?format=json&skipApps=false&skipUpdate=false", }, { desc: "skip apps", serverURL: "https://nextcloud.example.com", skipApps: true, wantURL: "https://nextcloud.example.com/ocs/v2.php/apps/serverinfo/api/v1/info?format=json&skipApps=true&skipUpdate=false", }, { desc: "do not skip update", serverURL: "https://nextcloud.example.com", skipUpdate: false, wantURL: "https://nextcloud.example.com/ocs/v2.php/apps/serverinfo/api/v1/info?format=json&skipApps=false&skipUpdate=false", }, { desc: "skip update", serverURL: "https://nextcloud.example.com", skipUpdate: true, wantURL: "https://nextcloud.example.com/ocs/v2.php/apps/serverinfo/api/v1/info?format=json&skipApps=false&skipUpdate=true", }, { desc: "do not skip update and do not skip apps (explicit)", serverURL: "https://nextcloud.example.com", skipApps: false, skipUpdate: false, wantURL: "https://nextcloud.example.com/ocs/v2.php/apps/serverinfo/api/v1/info?format=json&skipApps=false&skipUpdate=false", }, { desc: "skip update and skip apps", serverURL: "https://nextcloud.example.com", skipApps: true, skipUpdate: true, wantURL: "https://nextcloud.example.com/ocs/v2.php/apps/serverinfo/api/v1/info?format=json&skipApps=true&skipUpdate=true", }, } for _, tc := range tt { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() url := InfoURL(tc.serverURL, tc.skipApps, tc.skipUpdate) if url != tc.wantURL { t.Errorf("got url %q, want %q", url, tc.wantURL) } }) } }