From 94415e80296cdb445ea228bdae3864f3d5ddc64a Mon Sep 17 00:00:00 2001 From: Jordan Whited Date: Tue, 25 Jun 2024 10:21:40 -0700 Subject: [PATCH] cmd/stunstamp: remove sqlite DB and API (#12604) stunstamp now sends data to Prometheus via remote write, and Prometheus can serve the same data. Retaining and cleaning up old data in sqlite leads to long probing pauses, and it's not worth investing more effort to optimize the schema and/or concurrency model. Updates tailscale/corp#20344 Signed-off-by: Jordan Whited --- cmd/stunstamp/api.go | 142 ---------------------- cmd/stunstamp/stunstamp.go | 97 --------------- cmd/stunstamp/stunstamp_db_default.go | 26 ---- cmd/stunstamp/stunstamp_db_windows_386.go | 17 --- go.mod | 15 +-- go.sum | 40 ------ 6 files changed, 1 insertion(+), 336 deletions(-) delete mode 100644 cmd/stunstamp/api.go delete mode 100644 cmd/stunstamp/stunstamp_db_default.go delete mode 100644 cmd/stunstamp/stunstamp_db_windows_386.go diff --git a/cmd/stunstamp/api.go b/cmd/stunstamp/api.go deleted file mode 100644 index 8effda6e4..000000000 --- a/cmd/stunstamp/api.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -package main - -import ( - "compress/gzip" - "encoding/json" - "errors" - "net/http" - "net/url" - "strconv" - "strings" - "time" - - sq "github.com/Masterminds/squirrel" -) - -type api struct { - db *db - mux *http.ServeMux -} - -func newAPI(db *db) *api { - a := &api{ - db: db, - } - mux := http.NewServeMux() - mux.HandleFunc("/query", a.query) - a.mux = mux - return a -} - -type apiResult struct { - At int `json:"at"` // time.Time.Unix() - RegionID int `json:"regionID"` - Hostname string `json:"hostname"` - Af int `json:"af"` // 4 or 6 - Addr string `json:"addr"` - Source int `json:"source"` // timestampSourceUserspace (0) or timestampSourceKernel (1) - StableConn bool `json:"stableConn"` - DstPort int `json:"dstPort"` - RttNS *int `json:"rttNS"` -} - -func getTimeBounds(vals url.Values) (from time.Time, to time.Time, err error) { - lastForm, ok := vals["last"] - if ok && len(lastForm) > 0 { - dur, err := time.ParseDuration(lastForm[0]) - if err != nil { - return time.Time{}, time.Time{}, err - } - now := time.Now() - return now.Add(-dur), now, nil - } - - fromForm, ok := vals["from"] - if ok && len(fromForm) > 0 { - fromUnixSec, err := strconv.Atoi(fromForm[0]) - if err != nil { - return time.Time{}, time.Time{}, err - } - from = time.Unix(int64(fromUnixSec), 0) - toForm, ok := vals["to"] - if ok && len(toForm) > 0 { - toUnixSec, err := strconv.Atoi(toForm[0]) - if err != nil { - return time.Time{}, time.Time{}, err - } - to = time.Unix(int64(toUnixSec), 0) - } else { - return time.Time{}, time.Time{}, errors.New("from specified without to") - } - return from, to, nil - } - - // no time bounds specified, default to last 1h - now := time.Now() - return now.Add(-time.Hour), now, nil -} - -func (a *api) ServeHTTP(w http.ResponseWriter, r *http.Request) { - a.mux.ServeHTTP(w, r) -} - -func (a *api) query(w http.ResponseWriter, r *http.Request) { - err := r.ParseForm() - if err != nil { - http.Error(w, err.Error(), 500) - return - } - from, to, err := getTimeBounds(r.Form) - if err != nil { - http.Error(w, err.Error(), 500) - return - } - - sb := sq.Select("at_unix", "region_id", "hostname", "af", "address", "timestamp_source", "stable_conn", "dst_port", "rtt_ns").From("rtt") - sb = sb.Where(sq.And{ - sq.GtOrEq{"at_unix": from.Unix()}, - sq.LtOrEq{"at_unix": to.Unix()}, - }) - query, args, err := sb.ToSql() - if err != nil { - return - } - - rows, err := a.db.Query(query, args...) - if err != nil { - http.Error(w, err.Error(), 500) - return - } - results := make([]apiResult, 0) - for rows.Next() { - rtt := 0 - result := apiResult{ - RttNS: &rtt, - } - err = rows.Scan(&result.At, &result.RegionID, &result.Hostname, &result.Af, &result.Addr, &result.Source, &result.StableConn, &result.DstPort, &result.RttNS) - if err != nil { - http.Error(w, err.Error(), 500) - return - } - results = append(results, result) - } - if rows.Err() != nil { - http.Error(w, rows.Err().Error(), 500) - return - } - if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { - gz := gzip.NewWriter(w) - defer gz.Close() - w.Header().Set("Content-Encoding", "gzip") - err = json.NewEncoder(gz).Encode(&results) - } else { - err = json.NewEncoder(w).Encode(&results) - } - if err != nil { - http.Error(w, err.Error(), 500) - return - } -} diff --git a/cmd/stunstamp/stunstamp.go b/cmd/stunstamp/stunstamp.go index 0ec0efeb2..6c009de46 100644 --- a/cmd/stunstamp/stunstamp.go +++ b/cmd/stunstamp/stunstamp.go @@ -38,11 +38,8 @@ var ( flagDERPMap = flag.String("derp-map", "https://login.tailscale.com/derpmap/default", "URL to DERP map") - flagOut = flag.String("out", "", "output sqlite filename") flagInterval = flag.Duration("interval", time.Minute, "interval to probe at in time.ParseDuration() format") - flagAPI = flag.String("api", "", "listen addr for HTTP API") flagIPv6 = flag.Bool("ipv6", false, "probe IPv6 addresses") - flagRetention = flag.Duration("retention", time.Hour*24*7, "sqlite retention period in time.ParseDuration() format") flagRemoteWriteURL = flag.String("rw-url", "", "prometheus remote write URL") flagInstance = flag.String("instance", "", "instance label value; defaults to hostname if unspecified") flagDstPorts = flag.String("dst-ports", "", "comma-separated list of destination ports to monitor") @@ -639,15 +636,9 @@ func main() { if len(*flagDERPMap) < 1 { log.Fatal("derp-map flag is unset") } - if len(*flagOut) < 1 { - log.Fatal("out flag is unset") - } if *flagInterval < minInterval || *flagInterval > maxBufferDuration { log.Fatalf("interval must be >= %s and <= %s", minInterval, maxBufferDuration) } - if *flagRetention < *flagInterval { - log.Fatal("retention must be >= interval") - } if len(*flagRemoteWriteURL) < 1 { log.Fatal("rw-url flag is unset") } @@ -693,49 +684,6 @@ func main() { } } - db, err := newDB(*flagOut) - if err != nil { - log.Fatalf("error opening output file for writing: %v", err) - } - defer db.Close() - - _, err = db.Exec("PRAGMA journal_mode=WAL") - if err != nil { - log.Fatalf("error enabling WAL mode: %v", err) - } - - // No indices or primary key. Keep it simple for now. Reads will be full - // scans. We can AUTOINCREMENT rowid in the future and hold an in-memory - // index to at_unix if needed as reads are almost always going to be - // time-bound (e.g. WHERE at_unix >= ?). At the time of authorship we have - // ~300 data points per-interval w/o ipv6 w/kernel timestamping resulting - // in ~2.6m rows in 24h w/a 10s probe interval. - _, err = db.Exec(` -CREATE TABLE IF NOT EXISTS rtt(at_unix INT, region_id INT, hostname TEXT, af INT, address TEXT, timestamp_source INT, stable_conn INT, dst_port INT, rtt_ns INT) -`) - if err != nil { - log.Fatalf("error initializing db: %v", err) - } - - wg := sync.WaitGroup{} - httpErrCh := make(chan error, 1) - var httpServer *http.Server - if len(*flagAPI) > 0 { - api := newAPI(db) - httpServer = &http.Server{ - Addr: *flagAPI, - Handler: api, - ReadTimeout: time.Second * 60, - WriteTimeout: time.Second * 60, - } - wg.Add(1) - go func() { - err := httpServer.ListenAndServe() - httpErrCh <- err - wg.Done() - }() - } - tsCh := make(chan []prompb.TimeSeries, maxBufferDuration / *flagInterval) remoteWriteDoneCh := make(chan struct{}) rwc := newRemoteWriteClient(*flagRemoteWriteURL) @@ -745,9 +693,6 @@ func main() { }() shutdown := func() { - if httpServer != nil { - httpServer.Close() - } close(tsCh) select { case <-time.After(time.Second * 10): // give goroutine some time to flush @@ -766,7 +711,6 @@ func main() { cancel() } - wg.Wait() return } @@ -787,20 +731,9 @@ func main() { defer derpMapTicker.Stop() probeTicker := time.NewTicker(*flagInterval) defer probeTicker.Stop() - cleanupTicker := time.NewTicker(time.Hour) - defer cleanupTicker.Stop() for { select { - case <-cleanupTicker.C: - older := time.Now().Add(-*flagRetention) - log.Printf("cleaning up measurements older than %v", older) - _, err := db.Exec("DELETE FROM rtt WHERE at_unix < ?", older.Unix()) - if err != nil { - log.Printf("error cleaning up old data: %v", err) - shutdown() - return - } case <-probeTicker.C: results, err := probeNodes(nodeMetaByAddr, stableConns, dstPorts) if err != nil { @@ -819,32 +752,6 @@ func main() { tsCh <- ts } } - tx, err := db.Begin() - if err != nil { - log.Printf("error beginning sqlite tx: %v", err) - shutdown() - return - } - for _, result := range results { - af := 4 - if result.key.meta.addr.Is6() { - af = 6 - } - _, err = tx.Exec("INSERT INTO rtt(at_unix, region_id, hostname, af, address, timestamp_source, stable_conn, dst_port, rtt_ns) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)", - result.at.Unix(), result.key.meta.regionID, result.key.meta.hostname, af, result.key.meta.addr.String(), result.key.timestampSource, result.key.connStability, result.key.dstPort, result.rtt) - if err != nil { - tx.Rollback() - log.Printf("error adding result to tx: %v", err) - shutdown() - return - } - } - err = tx.Commit() - if err != nil { - log.Printf("error committing tx: %v", err) - shutdown() - return - } case dm := <-dmCh: staleMeta, err := nodeMetaFromDERPMap(dm, nodeMetaByAddr, *flagIPv6) if err != nil { @@ -874,10 +781,6 @@ func main() { dmCh <- updatedDM } }() - case err := <-httpErrCh: - log.Printf("http server error: %v", err) - shutdown() - return case <-sigCh: shutdown() return diff --git a/cmd/stunstamp/stunstamp_db_default.go b/cmd/stunstamp/stunstamp_db_default.go deleted file mode 100644 index 3de3a0197..000000000 --- a/cmd/stunstamp/stunstamp_db_default.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -//go:build !(windows && 386) - -package main - -import ( - "database/sql" - - _ "modernc.org/sqlite" -) - -type db struct { - *sql.DB -} - -func newDB(path string) (*db, error) { - d, err := sql.Open("sqlite", *flagOut) - if err != nil { - return nil, err - } - return &db{ - DB: d, - }, nil -} diff --git a/cmd/stunstamp/stunstamp_db_windows_386.go b/cmd/stunstamp/stunstamp_db_windows_386.go deleted file mode 100644 index 67dba08ca..000000000 --- a/cmd/stunstamp/stunstamp_db_windows_386.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -package main - -import ( - "database/sql" - "errors" -) - -type db struct { - *sql.DB -} - -func newDB(path string) (*db, error) { - return nil, errors.New("unsupported platform") -} diff --git a/go.mod b/go.mod index 1746c0d69..cb23701b3 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.22.0 require ( filippo.io/mkcert v1.4.4 fybrik.io/crdoc v0.6.3 - github.com/Masterminds/squirrel v1.5.4 github.com/akutz/memconn v0.1.0 github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa github.com/andybalholm/brotli v1.1.0 @@ -113,7 +112,6 @@ require ( k8s.io/apimachinery v0.30.1 k8s.io/apiserver v0.30.1 k8s.io/client-go v0.30.1 - modernc.org/sqlite v1.29.10 nhooyr.io/websocket v1.8.10 sigs.k8s.io/controller-runtime v0.18.4 sigs.k8s.io/controller-tools v0.15.1-0.20240618033008-7824932b0cab @@ -127,21 +125,10 @@ require ( github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/dave/astrid v0.0.0-20170323122508-8c2895878b14 // indirect github.com/dave/brenda v1.1.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/gobuffalo/flect v1.0.2 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect + github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect github.com/gorilla/securecookie v1.1.2 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect - github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect - modernc.org/libc v1.49.3 // indirect - modernc.org/mathutil v1.6.0 // indirect - modernc.org/memory v1.8.0 // indirect - modernc.org/strutil v1.2.0 // indirect - modernc.org/token v1.1.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 07acdc7a6..0f416a49a 100644 --- a/go.sum +++ b/go.sum @@ -75,8 +75,6 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= -github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= -github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= @@ -265,8 +263,6 @@ github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqY github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/dsnet/try v0.0.3 h1:ptR59SsrcFUYbT/FhAbKTV6iLkeD6O18qfIWRml2fqI= github.com/dsnet/try v0.0.3/go.mod h1:WBM8tRpUmnXXhY1U6/S8dt6UWdHTQ7y8A5YSkRCkq40= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU= @@ -522,8 +518,6 @@ github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mO github.com/hashicorp/go-version v1.6.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/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= 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/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= @@ -623,10 +617,6 @@ github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoa github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= -github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= -github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= -github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= -github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= @@ -699,8 +689,6 @@ github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81 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/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nishanths/exhaustive v0.10.0 h1:BMznKAcVa9WOoLq/kTGp4NJOJSMwEpcpjFNAVRfPlSo= @@ -791,8 +779,6 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl 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/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -1475,32 +1461,6 @@ k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7F k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= -modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= -modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= -modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= -modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= -modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= -modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= -modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= -modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= -modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= -modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= -modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= -modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= -modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.29.10 h1:3u93dz83myFnMilBGCOLbr+HjklS6+5rJLx4q86RDAg= -modernc.org/sqlite v1.29.10/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= -modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= -modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= -modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=