mirror of
https://github.com/tailscale/tailscale.git
synced 2025-11-30 15:02:00 +01:00
cmd/cigocacher,go.mod: add cigocacher cmd
Adds cmd/cigocacher as the client to cigocached for Go caching over HTTP. The HTTP cache is best-effort only, and builds will fall back to disk-only cache if it's not available, much like regular builds. Not yet used in CI; that will follow in another PR once we have runners available in this repo with the right network setup for reaching cigocached. Updates tailscale/corp#10808 Change-Id: I13ae1a12450eb2a05bd9843f358474243989e967 Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
parent
698eecda04
commit
6637003cc8
308
cmd/cigocacher/cigocacher.go
Normal file
308
cmd/cigocacher/cigocacher.go
Normal file
@ -0,0 +1,308 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// cigocacher is an opinionated-to-Tailscale client for gocached. It connects
|
||||
// at a URL like "https://ci-gocached-azure-1.corp.ts.net:31364", but that is
|
||||
// stored in a GitHub actions variable so that its hostname can be updated for
|
||||
// all branches at the same time in sync with the actual infrastructure.
|
||||
//
|
||||
// It authenticates using GitHub OIDC tokens, and all HTTP errors are ignored
|
||||
// so that its failure mode is just that builds get slower and fall back to
|
||||
// disk-only cache.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
jsonv1 "encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/bradfitz/go-tool-cache/cacheproc"
|
||||
"github.com/bradfitz/go-tool-cache/cachers"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
auth = flag.Bool("auth", false, "auth with cigocached and exit, printing the access token as output")
|
||||
token = flag.String("token", "", "the cigocached access token to use, as created using --auth")
|
||||
cigocachedURL = flag.String("cigocached-url", "", "optional cigocached URL (scheme, host, and port). empty means to not use one.")
|
||||
verbose = flag.Bool("verbose", false, "enable verbose logging")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
if *auth {
|
||||
if *cigocachedURL == "" {
|
||||
log.Print("--cigocached-url is empty, skipping auth")
|
||||
return
|
||||
}
|
||||
tk, err := fetchAccessToken(httpClient(), os.Getenv("ACTIONS_ID_TOKEN_REQUEST_URL"), os.Getenv("ACTIONS_ID_TOKEN_REQUEST_TOKEN"), *cigocachedURL)
|
||||
if err != nil {
|
||||
log.Printf("error fetching access token, skipping auth: %v", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(tk)
|
||||
return
|
||||
}
|
||||
|
||||
d, err := os.UserCacheDir()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
d = filepath.Join(d, "go-cacher")
|
||||
log.Printf("Defaulting to cache dir %v ...", d)
|
||||
if err := os.MkdirAll(d, 0750); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
c := &cigocacher{
|
||||
disk: &cachers.DiskCache{Dir: d},
|
||||
verbose: *verbose,
|
||||
}
|
||||
if *cigocachedURL != "" {
|
||||
log.Printf("Using cigocached at %s", *cigocachedURL)
|
||||
c.gocached = &gocachedClient{
|
||||
baseURL: *cigocachedURL,
|
||||
cl: httpClient(),
|
||||
accessToken: *token,
|
||||
verbose: *verbose,
|
||||
}
|
||||
}
|
||||
var p *cacheproc.Process
|
||||
p = &cacheproc.Process{
|
||||
Close: func() error {
|
||||
log.Printf("gocacheprog: closing; %d gets (%d hits, %d misses, %d errors); %d puts (%d errors)",
|
||||
p.Gets.Load(), p.GetHits.Load(), p.GetMisses.Load(), p.GetErrors.Load(), p.Puts.Load(), p.PutErrors.Load())
|
||||
return c.close()
|
||||
},
|
||||
Get: c.get,
|
||||
Put: c.put,
|
||||
}
|
||||
|
||||
if err := p.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func httpClient() *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err == nil {
|
||||
// This does not run in a tailnet. We serve corp.ts.net
|
||||
// TLS certs, and override DNS resolution to lookup the
|
||||
// private IP for the VM by its hostname.
|
||||
if vm, ok := strings.CutSuffix(host, ".corp.ts.net"); ok {
|
||||
addr = net.JoinHostPort(vm, port)
|
||||
}
|
||||
}
|
||||
var d net.Dialer
|
||||
return d.DialContext(ctx, network, addr)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type cigocacher struct {
|
||||
disk *cachers.DiskCache
|
||||
gocached *gocachedClient
|
||||
verbose bool
|
||||
|
||||
getNanos atomic.Int64 // total nanoseconds spent in gets
|
||||
putNanos atomic.Int64 // total nanoseconds spent in puts
|
||||
getHTTP atomic.Int64 // HTTP get requests made
|
||||
getHTTPBytes atomic.Int64 // HTTP get bytes transferred
|
||||
getHTTPHits atomic.Int64 // HTTP get hits
|
||||
getHTTPMisses atomic.Int64 // HTTP get misses
|
||||
getHTTPErrors atomic.Int64 // HTTP get errors ignored on best-effort basis
|
||||
getHTTPNanos atomic.Int64 // total nanoseconds spent in HTTP gets
|
||||
putHTTP atomic.Int64 // HTTP put requests made
|
||||
putHTTPBytes atomic.Int64 // HTTP put bytes transferred
|
||||
putHTTPErrors atomic.Int64 // HTTP put errors ignored on best-effort basis
|
||||
putHTTPNanos atomic.Int64 // total nanoseconds spent in HTTP puts
|
||||
}
|
||||
|
||||
func (c *cigocacher) get(ctx context.Context, actionID string) (outputID, diskPath string, err error) {
|
||||
t0 := time.Now()
|
||||
defer func() {
|
||||
c.getNanos.Add(time.Since(t0).Nanoseconds())
|
||||
}()
|
||||
if c.gocached == nil {
|
||||
return c.disk.Get(ctx, actionID)
|
||||
}
|
||||
|
||||
outputID, diskPath, err = c.disk.Get(ctx, actionID)
|
||||
if err == nil && outputID != "" {
|
||||
return outputID, diskPath, nil
|
||||
}
|
||||
|
||||
c.getHTTP.Add(1)
|
||||
t0HTTP := time.Now()
|
||||
defer func() {
|
||||
c.getHTTPNanos.Add(time.Since(t0HTTP).Nanoseconds())
|
||||
}()
|
||||
outputID, res, err := c.gocached.get(ctx, actionID)
|
||||
if err != nil {
|
||||
c.getHTTPErrors.Add(1)
|
||||
return "", "", nil
|
||||
}
|
||||
if outputID == "" || res == nil {
|
||||
c.getHTTPMisses.Add(1)
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
// TODO(tomhjp): make sure we timeout if cigocached disappears, but for some
|
||||
// reason, this seemed to tank network performance.
|
||||
// ctx, cancel := context.WithTimeout(ctx, httpTimeout(res.ContentLength))
|
||||
// defer cancel()
|
||||
diskPath, err = c.disk.Put(ctx, actionID, outputID, res.ContentLength, res.Body)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("error filling disk cache from HTTP: %w", err)
|
||||
}
|
||||
|
||||
c.getHTTPHits.Add(1)
|
||||
c.getHTTPBytes.Add(res.ContentLength)
|
||||
return outputID, diskPath, nil
|
||||
}
|
||||
|
||||
func (c *cigocacher) put(ctx context.Context, actionID, outputID string, size int64, r io.Reader) (diskPath string, err error) {
|
||||
t0 := time.Now()
|
||||
defer func() {
|
||||
c.putNanos.Add(time.Since(t0).Nanoseconds())
|
||||
}()
|
||||
if c.gocached == nil {
|
||||
return c.disk.Put(ctx, actionID, outputID, size, r)
|
||||
}
|
||||
|
||||
c.putHTTP.Add(1)
|
||||
var diskReader, httpReader io.Reader
|
||||
tee := &bestEffortTeeReader{r: r}
|
||||
if size == 0 {
|
||||
// Special case the empty file so NewRequest sets "Content-Length: 0",
|
||||
// as opposed to thinking we didn't set it and not being able to sniff its size
|
||||
// from the type.
|
||||
diskReader, httpReader = bytes.NewReader(nil), bytes.NewReader(nil)
|
||||
} else {
|
||||
pr, pw := io.Pipe()
|
||||
defer pw.Close()
|
||||
// The diskReader is in the driving seat. We will try to forward data
|
||||
// to httpReader as well, but only best-effort.
|
||||
diskReader = tee
|
||||
tee.w = pw
|
||||
httpReader = pr
|
||||
}
|
||||
httpErrCh := make(chan error)
|
||||
go func() {
|
||||
// TODO(tomhjp): make sure we timeout if cigocached disappears, but for some
|
||||
// reason, this seemed to tank network performance.
|
||||
// ctx, cancel := context.WithTimeout(ctx, httpTimeout(size))
|
||||
// defer cancel()
|
||||
t0HTTP := time.Now()
|
||||
defer func() {
|
||||
c.putHTTPNanos.Add(time.Since(t0HTTP).Nanoseconds())
|
||||
}()
|
||||
httpErrCh <- c.gocached.put(ctx, actionID, outputID, size, httpReader)
|
||||
}()
|
||||
|
||||
diskPath, err = c.disk.Put(ctx, actionID, outputID, size, diskReader)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error writing to disk cache: %w", errors.Join(err, tee.err))
|
||||
}
|
||||
|
||||
select {
|
||||
case err := <-httpErrCh:
|
||||
if err != nil {
|
||||
c.putHTTPErrors.Add(1)
|
||||
} else {
|
||||
c.putHTTPBytes.Add(size)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
}
|
||||
|
||||
return diskPath, nil
|
||||
}
|
||||
|
||||
func (c *cigocacher) close() error {
|
||||
log.Printf("cigocacher HTTP stats: %d gets (%.1fMiB, %.2fs, %d hits, %d misses, %d errors ignored); %d puts (%.1fMiB, %.2fs, %d errors ignored)",
|
||||
c.getHTTP.Load(), float64(c.getHTTPBytes.Load())/float64(1<<20), float64(c.getHTTPNanos.Load())/float64(time.Second), c.getHTTPHits.Load(), c.getHTTPMisses.Load(), c.getHTTPErrors.Load(),
|
||||
c.putHTTP.Load(), float64(c.putHTTPBytes.Load())/float64(1<<20), float64(c.putHTTPNanos.Load())/float64(time.Second), c.putHTTPErrors.Load())
|
||||
if !c.verbose || c.gocached == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
stats, err := c.gocached.fetchStats()
|
||||
if err != nil {
|
||||
log.Printf("error fetching gocached stats: %v", err)
|
||||
} else {
|
||||
log.Printf("gocached session stats: %s", stats)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchAccessToken(cl *http.Client, idTokenURL, idTokenRequestToken, gocachedURL string) (string, error) {
|
||||
req, err := http.NewRequest("GET", idTokenURL+"&audience=gocached", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+idTokenRequestToken)
|
||||
resp, err := cl.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
type idTokenResp struct {
|
||||
Value string `json:"value"`
|
||||
}
|
||||
var idToken idTokenResp
|
||||
if err := jsonv1.NewDecoder(resp.Body).Decode(&idToken); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
req, _ = http.NewRequest("POST", gocachedURL+"/auth/exchange-token", strings.NewReader(`{"jwt":"`+idToken.Value+`"}`))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
resp, err = cl.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
type accessTokenResp struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
var accessToken accessTokenResp
|
||||
if err := jsonv1.NewDecoder(resp.Body).Decode(&accessToken); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return accessToken.AccessToken, nil
|
||||
}
|
||||
|
||||
type bestEffortTeeReader struct {
|
||||
r io.Reader
|
||||
w io.WriteCloser
|
||||
err error
|
||||
}
|
||||
|
||||
func (t *bestEffortTeeReader) Read(p []byte) (int, error) {
|
||||
n, err := t.r.Read(p)
|
||||
if n > 0 && t.w != nil {
|
||||
if _, err := t.w.Write(p[:n]); err != nil {
|
||||
t.err = errors.Join(err, t.w.Close())
|
||||
t.w = nil
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
115
cmd/cigocacher/http.go
Normal file
115
cmd/cigocacher/http.go
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type gocachedClient struct {
|
||||
baseURL string // base URL of the cacher server, like "http://localhost:31364".
|
||||
cl *http.Client // http.Client to use.
|
||||
accessToken string // Bearer token to use in the Authorization header.
|
||||
verbose bool
|
||||
}
|
||||
|
||||
// drainAndClose reads and throws away a small bounded amount of data. This is a
|
||||
// best-effort attempt to allow connection reuse; Go's HTTP/1 Transport won't
|
||||
// reuse a TCP connection unless you fully consume HTTP responses.
|
||||
func drainAndClose(body io.ReadCloser) {
|
||||
io.CopyN(io.Discard, body, 4<<10)
|
||||
body.Close()
|
||||
}
|
||||
|
||||
func tryReadErrorMessage(res *http.Response) []byte {
|
||||
msg, _ := io.ReadAll(io.LimitReader(res.Body, 4<<10))
|
||||
return msg
|
||||
}
|
||||
|
||||
func (c *gocachedClient) get(ctx context.Context, actionID string) (outputID string, resp *http.Response, err error) {
|
||||
// TODO(tomhjp): make sure we timeout if cigocached disappears, but for some
|
||||
// reason, this seemed to tank network performance.
|
||||
// // Set a generous upper limit on the time we'll wait for a response. We'll
|
||||
// // shorten this deadline later once we know the content length.
|
||||
// ctx, cancel := context.WithTimeout(ctx, time.Minute)
|
||||
// defer cancel()
|
||||
req, _ := http.NewRequestWithContext(ctx, "GET", c.baseURL+"/action/"+actionID, nil)
|
||||
req.Header.Set("Want-Object", "1") // opt in to single roundtrip protocol
|
||||
if c.accessToken != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.accessToken)
|
||||
}
|
||||
|
||||
res, err := c.cl.Do(req)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
defer func() {
|
||||
if resp == nil {
|
||||
drainAndClose(res.Body)
|
||||
}
|
||||
}()
|
||||
if res.StatusCode == http.StatusNotFound {
|
||||
return "", nil, nil
|
||||
}
|
||||
if res.StatusCode != http.StatusOK {
|
||||
msg := tryReadErrorMessage(res)
|
||||
if c.verbose {
|
||||
log.Printf("error GET /action/%s: %v, %s", actionID, res.Status, msg)
|
||||
}
|
||||
return "", nil, fmt.Errorf("unexpected GET /action/%s status %v", actionID, res.Status)
|
||||
}
|
||||
|
||||
outputID = res.Header.Get("Go-Output-Id")
|
||||
if outputID == "" {
|
||||
return "", nil, fmt.Errorf("missing Go-Output-Id header in response")
|
||||
}
|
||||
if res.ContentLength == -1 {
|
||||
return "", nil, fmt.Errorf("no Content-Length from server")
|
||||
}
|
||||
return outputID, res, nil
|
||||
}
|
||||
|
||||
func (c *gocachedClient) put(ctx context.Context, actionID, outputID string, size int64, body io.Reader) error {
|
||||
req, _ := http.NewRequestWithContext(ctx, "PUT", c.baseURL+"/"+actionID+"/"+outputID, body)
|
||||
req.ContentLength = size
|
||||
if c.accessToken != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.accessToken)
|
||||
}
|
||||
res, err := c.cl.Do(req)
|
||||
if err != nil {
|
||||
if c.verbose {
|
||||
log.Printf("error PUT /%s/%s: %v", actionID, outputID, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusNoContent {
|
||||
msg := tryReadErrorMessage(res)
|
||||
if c.verbose {
|
||||
log.Printf("error PUT /%s/%s: %v, %s", actionID, outputID, res.Status, msg)
|
||||
}
|
||||
return fmt.Errorf("unexpected PUT /%s/%s status %v", actionID, outputID, res.Status)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *gocachedClient) fetchStats() (string, error) {
|
||||
req, _ := http.NewRequest("GET", c.baseURL+"/session/stats", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+c.accessToken)
|
||||
resp, err := c.cl.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
@ -30,9 +30,9 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
|
||||
github.com/prometheus/client_model/go from github.com/prometheus/client_golang/prometheus+
|
||||
github.com/prometheus/common/expfmt from github.com/prometheus/client_golang/prometheus+
|
||||
github.com/prometheus/common/model from github.com/prometheus/client_golang/prometheus+
|
||||
LD github.com/prometheus/procfs from github.com/prometheus/client_golang/prometheus
|
||||
LD github.com/prometheus/procfs/internal/fs from github.com/prometheus/procfs
|
||||
LD github.com/prometheus/procfs/internal/util from github.com/prometheus/procfs
|
||||
L github.com/prometheus/procfs from github.com/prometheus/client_golang/prometheus
|
||||
L github.com/prometheus/procfs/internal/fs from github.com/prometheus/procfs
|
||||
L github.com/prometheus/procfs/internal/util from github.com/prometheus/procfs
|
||||
W 💣 github.com/tailscale/go-winio from tailscale.com/safesocket
|
||||
W 💣 github.com/tailscale/go-winio/internal/fs from github.com/tailscale/go-winio
|
||||
W 💣 github.com/tailscale/go-winio/internal/socket from github.com/tailscale/go-winio
|
||||
@ -72,7 +72,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
|
||||
google.golang.org/protobuf/reflect/protoregistry from google.golang.org/protobuf/encoding/prototext+
|
||||
google.golang.org/protobuf/runtime/protoiface from google.golang.org/protobuf/internal/impl+
|
||||
google.golang.org/protobuf/runtime/protoimpl from github.com/prometheus/client_model/go+
|
||||
google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+
|
||||
💣 google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+
|
||||
tailscale.com from tailscale.com/version
|
||||
💣 tailscale.com/atomicfile from tailscale.com/cmd/derper+
|
||||
tailscale.com/client/local from tailscale.com/derp/derpserver
|
||||
|
||||
@ -71,8 +71,9 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
||||
github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0
|
||||
github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/huff0+
|
||||
💣 github.com/klauspost/compress/internal/le from github.com/klauspost/compress/huff0+
|
||||
github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe+
|
||||
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe
|
||||
github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd
|
||||
github.com/mailru/easyjson/buffer from github.com/mailru/easyjson/jwriter
|
||||
💣 github.com/mailru/easyjson/jlexer from github.com/go-openapi/swag
|
||||
@ -94,6 +95,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
||||
github.com/prometheus/client_golang/prometheus/collectors from sigs.k8s.io/controller-runtime/pkg/internal/controller/metrics+
|
||||
github.com/prometheus/client_golang/prometheus/internal from github.com/prometheus/client_golang/prometheus+
|
||||
github.com/prometheus/client_golang/prometheus/promhttp from sigs.k8s.io/controller-runtime/pkg/metrics/server+
|
||||
github.com/prometheus/client_golang/prometheus/promhttp/internal from github.com/prometheus/client_golang/prometheus/promhttp
|
||||
github.com/prometheus/client_model/go from github.com/prometheus/client_golang/prometheus+
|
||||
github.com/prometheus/common/expfmt from github.com/prometheus/client_golang/prometheus+
|
||||
github.com/prometheus/common/model from github.com/prometheus/client_golang/prometheus+
|
||||
@ -180,10 +182,10 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
||||
google.golang.org/protobuf/reflect/protoregistry from github.com/golang/protobuf/proto+
|
||||
google.golang.org/protobuf/runtime/protoiface from github.com/golang/protobuf/proto+
|
||||
google.golang.org/protobuf/runtime/protoimpl from github.com/golang/protobuf/proto+
|
||||
google.golang.org/protobuf/types/descriptorpb from github.com/google/gnostic-models/openapiv3+
|
||||
google.golang.org/protobuf/types/gofeaturespb from google.golang.org/protobuf/reflect/protodesc
|
||||
google.golang.org/protobuf/types/known/anypb from github.com/google/gnostic-models/compiler+
|
||||
google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+
|
||||
💣 google.golang.org/protobuf/types/descriptorpb from github.com/google/gnostic-models/openapiv3+
|
||||
💣 google.golang.org/protobuf/types/gofeaturespb from google.golang.org/protobuf/reflect/protodesc
|
||||
💣 google.golang.org/protobuf/types/known/anypb from github.com/google/gnostic-models/compiler+
|
||||
💣 google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+
|
||||
gopkg.in/evanphx/json-patch.v4 from k8s.io/client-go/testing
|
||||
gopkg.in/inf.v0 from k8s.io/apimachinery/pkg/api/resource
|
||||
gopkg.in/yaml.v3 from github.com/go-openapi/swag+
|
||||
|
||||
@ -14,9 +14,9 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar
|
||||
github.com/prometheus/client_model/go from github.com/prometheus/client_golang/prometheus+
|
||||
github.com/prometheus/common/expfmt from github.com/prometheus/client_golang/prometheus+
|
||||
github.com/prometheus/common/model from github.com/prometheus/client_golang/prometheus+
|
||||
LD github.com/prometheus/procfs from github.com/prometheus/client_golang/prometheus
|
||||
LD github.com/prometheus/procfs/internal/fs from github.com/prometheus/procfs
|
||||
LD github.com/prometheus/procfs/internal/util from github.com/prometheus/procfs
|
||||
L github.com/prometheus/procfs from github.com/prometheus/client_golang/prometheus
|
||||
L github.com/prometheus/procfs/internal/fs from github.com/prometheus/procfs
|
||||
L github.com/prometheus/procfs/internal/util from github.com/prometheus/procfs
|
||||
💣 go4.org/mem from tailscale.com/metrics+
|
||||
go4.org/netipx from tailscale.com/net/tsaddr
|
||||
google.golang.org/protobuf/encoding/protodelim from github.com/prometheus/common/expfmt
|
||||
@ -47,7 +47,7 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar
|
||||
google.golang.org/protobuf/reflect/protoregistry from google.golang.org/protobuf/encoding/prototext+
|
||||
google.golang.org/protobuf/runtime/protoiface from google.golang.org/protobuf/internal/impl+
|
||||
google.golang.org/protobuf/runtime/protoimpl from github.com/prometheus/client_model/go+
|
||||
google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+
|
||||
💣 google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+
|
||||
tailscale.com from tailscale.com/version
|
||||
tailscale.com/envknob from tailscale.com/tsweb+
|
||||
tailscale.com/feature from tailscale.com/tsweb
|
||||
|
||||
@ -16,6 +16,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0
|
||||
github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/huff0+
|
||||
💣 github.com/klauspost/compress/internal/le from github.com/klauspost/compress/huff0+
|
||||
github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe
|
||||
github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd
|
||||
|
||||
@ -20,6 +20,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0
|
||||
github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/huff0+
|
||||
💣 github.com/klauspost/compress/internal/le from github.com/klauspost/compress/huff0+
|
||||
github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe
|
||||
github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd
|
||||
|
||||
@ -139,6 +139,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0
|
||||
github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/huff0+
|
||||
💣 github.com/klauspost/compress/internal/le from github.com/klauspost/compress/huff0+
|
||||
github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe
|
||||
github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd
|
||||
|
||||
@ -36,6 +36,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
||||
github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0
|
||||
github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/huff0+
|
||||
💣 github.com/klauspost/compress/internal/le from github.com/klauspost/compress/huff0+
|
||||
github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe
|
||||
github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd
|
||||
|
||||
@ -151,5 +151,4 @@
|
||||
});
|
||||
};
|
||||
}
|
||||
# nix-direnv cache busting line: sha256-3jAfCtp714acePnwgdNto8Sj3vFwtpO9os6IwXQ07A4=
|
||||
|
||||
# nix-direnv cache busting line: sha256-jJSSXMyUqcJoZuqfSlBsKDQezyqS+jDkRglMMjG1K8g=
|
||||
|
||||
15
go.mod
15
go.mod
@ -16,6 +16,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.58
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.75.3
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.7
|
||||
github.com/bradfitz/go-tool-cache v0.0.0-20251113223507-0124e698e0bd
|
||||
github.com/bramvdbogaerde/go-scp v1.4.0
|
||||
github.com/cilium/ebpf v0.15.0
|
||||
github.com/coder/websocket v1.8.12
|
||||
@ -60,7 +61,7 @@ require (
|
||||
github.com/jellydator/ttlcache/v3 v3.1.0
|
||||
github.com/jsimonetti/rtnetlink v1.4.0
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/klauspost/compress v1.17.11
|
||||
github.com/klauspost/compress v1.18.0
|
||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
@ -74,8 +75,8 @@ require (
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkg/sftp v1.13.6
|
||||
github.com/prometheus-community/pro-bing v0.4.0
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/prometheus/common v0.55.0
|
||||
github.com/prometheus/client_golang v1.23.0
|
||||
github.com/prometheus/common v0.65.0
|
||||
github.com/prometheus/prometheus v0.49.2-0.20240125131847-c3b8ef1694ff
|
||||
github.com/safchain/ethtool v0.3.0
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
@ -103,7 +104,7 @@ require (
|
||||
go4.org/mem v0.0.0-20240501181205-ae6ca9944745
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.45.0
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
|
||||
golang.org/x/mod v0.30.0
|
||||
golang.org/x/net v0.47.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
@ -355,8 +356,8 @@ require (
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/polyfloyd/go-errorlint v1.4.8 // indirect
|
||||
github.com/prometheus/client_model v0.6.1
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.2
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/quasilyte/go-ruleguard v0.4.2 // indirect
|
||||
github.com/quasilyte/gogrep v0.5.0 // indirect
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
|
||||
@ -414,7 +415,7 @@ require (
|
||||
golang.org/x/image v0.27.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
google.golang.org/protobuf v1.36.3 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
|
||||
@ -1 +1 @@
|
||||
sha256-3jAfCtp714acePnwgdNto8Sj3vFwtpO9os6IwXQ07A4=
|
||||
sha256-jJSSXMyUqcJoZuqfSlBsKDQezyqS+jDkRglMMjG1K8g=
|
||||
|
||||
30
go.sum
30
go.sum
@ -186,6 +186,8 @@ github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
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/bradfitz/go-tool-cache v0.0.0-20251113223507-0124e698e0bd h1:1Df3FBmfyUCIQ4eKzAPXIWTfewY89L0fWPWO56zWCyI=
|
||||
github.com/bradfitz/go-tool-cache v0.0.0-20251113223507-0124e698e0bd/go.mod h1:2+xptBAd0m2kZ1wLO4AYZhldLEFPy+KeGwmnlXLvy+w=
|
||||
github.com/bramvdbogaerde/go-scp v1.4.0 h1:jKMwpwCbcX1KyvDbm/PDJuXcMuNVlLGi0Q0reuzjyKY=
|
||||
github.com/bramvdbogaerde/go-scp v1.4.0/go.mod h1:on2aH5AxaFb2G0N5Vsdy6B0Ml7k9HuHSwfo1y0QzAbQ=
|
||||
github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY=
|
||||
@ -662,8 +664,8 @@ github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/
|
||||
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/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@ -840,29 +842,29 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
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_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
|
||||
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
|
||||
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/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
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/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/prometheus/prometheus v0.49.2-0.20240125131847-c3b8ef1694ff h1:X1Tly81aZ22DA1fxBdfvR3iw8+yFoUBUHMEd+AX/ZXI=
|
||||
github.com/prometheus/prometheus v0.49.2-0.20240125131847-c3b8ef1694ff/go.mod h1:FvE8dtQ1Ww63IlyKBn1V4s+zMwF9kHkVNkQBR1pM4CU=
|
||||
github.com/puzpuzpuz/xsync v1.5.2 h1:yRAP4wqSOZG+/4pxJ08fPTwrfL0IzE/LKQ/cw509qGY=
|
||||
@ -1140,8 +1142,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||
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-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8=
|
||||
@ -1498,8 +1500,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||
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.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
|
||||
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/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=
|
||||
|
||||
@ -16,4 +16,4 @@
|
||||
) {
|
||||
src = ./.;
|
||||
}).shellNix
|
||||
# nix-direnv cache busting line: sha256-3jAfCtp714acePnwgdNto8Sj3vFwtpO9os6IwXQ07A4=
|
||||
# nix-direnv cache busting line: sha256-jJSSXMyUqcJoZuqfSlBsKDQezyqS+jDkRglMMjG1K8g=
|
||||
|
||||
@ -36,6 +36,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
||||
github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0
|
||||
github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/huff0+
|
||||
💣 github.com/klauspost/compress/internal/le from github.com/klauspost/compress/huff0+
|
||||
github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe
|
||||
github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user