Compare commits
10 Commits
s/eq
...
unraid-web
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dc9edde90 | ||
|
|
b15d8525d0 | ||
|
|
0d7303b798 | ||
|
|
d1ce7a9b5e | ||
|
|
5def4f4a1c | ||
|
|
1c6ff310ae | ||
|
|
48605226dd | ||
|
|
f46c1aede0 | ||
|
|
73d128238e | ||
|
|
787fc41fa4 |
@@ -1,177 +0,0 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Equaler is a tool to automate the creation of an Equals method.
|
||||
//
|
||||
// This tool assumes that if a type you give it contains another named struct
|
||||
// type, that type will also have an Equal method, and that all fields are
|
||||
// comparable unless explicitly excluded.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"tailscale.com/util/codegen"
|
||||
)
|
||||
|
||||
var (
|
||||
flagTypes = flag.String("type", "", "comma-separated list of types; required")
|
||||
flagBuildTags = flag.String("tags", "", "compiler build tags to apply")
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("equaler: ")
|
||||
flag.Parse()
|
||||
if len(*flagTypes) == 0 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
typeNames := strings.Split(*flagTypes, ",")
|
||||
|
||||
pkg, namedTypes, err := codegen.LoadTypes(*flagBuildTags, ".")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
it := codegen.NewImportTracker(pkg.Types)
|
||||
buf := new(bytes.Buffer)
|
||||
for _, typeName := range typeNames {
|
||||
typ, ok := namedTypes[typeName]
|
||||
if !ok {
|
||||
log.Fatalf("could not find type %s", typeName)
|
||||
}
|
||||
gen(buf, it, typ, typeNames)
|
||||
}
|
||||
|
||||
cloneOutput := pkg.Name + "_equal.go"
|
||||
if err := codegen.WritePackageFile("tailscale.com/cmd/equaler", pkg, cloneOutput, it, buf); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func gen(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, typeNames []string) {
|
||||
t, ok := typ.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
name := typ.Obj().Name()
|
||||
fmt.Fprintf(buf, "// Equal reports whether a and b are equal.\n")
|
||||
fmt.Fprintf(buf, "func (a *%s) Equal(b *%s) bool {\n", name, name)
|
||||
writef := func(format string, args ...any) {
|
||||
fmt.Fprintf(buf, "\t"+format+"\n", args...)
|
||||
}
|
||||
writef("if a == b {")
|
||||
writef("\treturn true")
|
||||
writef("}")
|
||||
|
||||
writef("return a != nil && b != nil &&")
|
||||
for i := 0; i < t.NumFields(); i++ {
|
||||
fname := t.Field(i).Name()
|
||||
ft := t.Field(i).Type()
|
||||
|
||||
// Fields which are explicitly ignored are skipped.
|
||||
if codegen.HasNoEqual(t.Tag(i)) {
|
||||
writef("\t// Skipping %s because of codegen:noequal", fname)
|
||||
continue
|
||||
}
|
||||
|
||||
// Fields which are named types that have an Equal() method, get that method used
|
||||
if named, _ := ft.(*types.Named); named != nil {
|
||||
if implementsEqual(ft) || slices.Contains(typeNames, named.Obj().Name()) {
|
||||
writef("\ta.%s.Equal(b.%s) &&", fname, fname)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Fields which are just values are directly compared, unless they have an Equal() method.
|
||||
if !codegen.ContainsPointers(ft) {
|
||||
writef("\ta.%s == b.%s &&", fname, fname)
|
||||
continue
|
||||
}
|
||||
|
||||
switch ft := ft.Underlying().(type) {
|
||||
case *types.Pointer:
|
||||
if named, _ := ft.Elem().(*types.Named); named != nil {
|
||||
if slices.Contains(typeNames, named.Obj().Name()) || implementsEqual(ft) {
|
||||
writef("\t((a.%s == nil) == (b.%s == nil)) && (a.%s == nil || a.%s.Equal(b.%s)) &&", fname, fname, fname, fname, fname)
|
||||
continue
|
||||
}
|
||||
if implementsEqual(ft.Elem()) {
|
||||
writef("\t((a.%s == nil) == (b.%s == nil)) && (a.%s == nil || a.%s.Equal(*b.%s)) &&", fname, fname, fname, fname, fname)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !codegen.ContainsPointers(ft.Elem()) {
|
||||
writef("\t((a.%s == nil) == (b.%s == nil)) && (a.%s == nil || *a.%s == *b.%s) &&", fname, fname, fname, fname, fname)
|
||||
continue
|
||||
}
|
||||
log.Fatalf("unimplemented: %s (%T)", fname, ft)
|
||||
case *types.Slice:
|
||||
// Empty slices and nil slices are different.
|
||||
writef("\t((a.%s == nil) == (b.%s == nil)) &&", fname, fname)
|
||||
if named, _ := ft.Elem().(*types.Named); named != nil {
|
||||
if implementsEqual(ft.Elem()) {
|
||||
it.Import("golang.org/x/exp/slices")
|
||||
writef("\tslices.EqualFunc(a.%s, b.%s, func(aa %s, bb %s) bool {return aa.Equal(bb)}) &&", fname, fname, named.Obj().Name(), named.Obj().Name())
|
||||
continue
|
||||
}
|
||||
if slices.Contains(typeNames, named.Obj().Name()) || implementsEqual(types.NewPointer(ft.Elem())) {
|
||||
it.Import("golang.org/x/exp/slices")
|
||||
writef("\tslices.EqualFunc(a.%s, b.%s, func(aa %s, bb %s) bool {return aa.Equal(&bb)}) &&", fname, fname, named.Obj().Name(), named.Obj().Name())
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !codegen.ContainsPointers(ft.Elem()) {
|
||||
it.Import("golang.org/x/exp/slices")
|
||||
writef("\tslices.Equal(a.%s, b.%s) &&", fname, fname)
|
||||
continue
|
||||
}
|
||||
log.Fatalf("unimplemented: %s (%T)", fname, ft)
|
||||
case *types.Map:
|
||||
if !codegen.ContainsPointers(ft.Elem()) {
|
||||
it.Import("golang.org/x/exp/maps")
|
||||
writef("\tmaps.Equal(a.%s, b.%s) &&", fname, fname)
|
||||
continue
|
||||
}
|
||||
log.Fatalf("unimplemented: %s (%T)", fname, ft)
|
||||
default:
|
||||
log.Fatalf("unimplemented: %s (%T)", fname, ft)
|
||||
}
|
||||
}
|
||||
writef("\ttrue")
|
||||
fmt.Fprintf(buf, "}\n\n")
|
||||
|
||||
buf.Write(codegen.AssertStructUnchanged(t, name, "Equal", it))
|
||||
}
|
||||
|
||||
// hasBasicUnderlying reports true when typ.Underlying() is a slice or a map.
|
||||
func hasBasicUnderlying(typ types.Type) bool {
|
||||
switch typ.Underlying().(type) {
|
||||
case *types.Slice, *types.Map:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// implementsEqual reports whether typ has an Equal(typ) bool method.
|
||||
func implementsEqual(typ types.Type) bool {
|
||||
return types.Implements(typ, types.NewInterfaceType(
|
||||
[]*types.Func{types.NewFunc(
|
||||
token.NoPos, nil, "Equal", types.NewSignatureType(
|
||||
types.NewVar(token.NoPos, nil, "a", typ),
|
||||
nil, nil,
|
||||
types.NewTuple(types.NewVar(token.NoPos, nil, "b", typ)),
|
||||
types.NewTuple(types.NewVar(token.NoPos, nil, "", types.Typ[types.Bool])), false))},
|
||||
[]types.Type{},
|
||||
))
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func isSystemdSystem() bool {
|
||||
return false
|
||||
}
|
||||
switch distro.Get() {
|
||||
case distro.QNAP, distro.Gokrazy, distro.Synology:
|
||||
case distro.QNAP, distro.Gokrazy, distro.Synology, distro.Unraid:
|
||||
return false
|
||||
}
|
||||
_, err := exec.LookPath("systemctl")
|
||||
|
||||
@@ -61,6 +61,8 @@ type tmplData struct {
|
||||
TUNMode bool
|
||||
IsSynology bool
|
||||
DSMVersion int // 6 or 7, if IsSynology=true
|
||||
IsUnraid bool
|
||||
UnraidToken string
|
||||
IPNVersion string
|
||||
}
|
||||
|
||||
@@ -440,6 +442,8 @@ func webHandler(w http.ResponseWriter, r *http.Request) {
|
||||
LicensesURL: licensesURL(),
|
||||
TUNMode: st.TUN,
|
||||
IsSynology: distro.Get() == distro.Synology || envknob.Bool("TS_FAKE_SYNOLOGY"),
|
||||
IsUnraid: distro.Get() == distro.Unraid,
|
||||
UnraidToken: os.Getenv("UNRAID_CSRF_TOKEN"),
|
||||
DSMVersion: distro.DSMVersion(),
|
||||
IPNVersion: versionShort,
|
||||
}
|
||||
|
||||
@@ -116,10 +116,12 @@
|
||||
<a class="text-xs text-gray-500 hover:text-gray-600" href="{{ .LicensesURL }}">Open Source Licenses</a>
|
||||
</footer>
|
||||
<script>(function () {
|
||||
const advertiseExitNode = {{.AdvertiseExitNode}};
|
||||
const advertiseExitNode = {{ .AdvertiseExitNode }};
|
||||
const isUnraid = {{ .IsUnraid }};
|
||||
const unraidCsrfToken = "{{ .UnraidToken }}";
|
||||
let fetchingUrl = false;
|
||||
var data = {
|
||||
AdvertiseRoutes: "{{.AdvertiseRoutes}}",
|
||||
AdvertiseRoutes: "{{ .AdvertiseRoutes }}",
|
||||
AdvertiseExitNode: advertiseExitNode,
|
||||
Reauthenticate: false,
|
||||
ForceLogout: false
|
||||
@@ -141,15 +143,25 @@ function postData(e) {
|
||||
}
|
||||
const nextUrl = new URL(window.location);
|
||||
nextUrl.search = nextParams.toString()
|
||||
const url = nextUrl.toString();
|
||||
|
||||
let contentType = "application/json";
|
||||
let body = JSON.stringify(data);
|
||||
if (isUnraid) {
|
||||
const params = new URLSearchParams();
|
||||
params.append("csrf_token", unraidCsrfToken);
|
||||
params.append("ts_data", JSON.stringify(data));
|
||||
body = params.toString();
|
||||
contentType = "application/x-www-form-urlencoded;charset=UTF-8";
|
||||
}
|
||||
|
||||
const url = nextUrl.toString();
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": contentType,
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
body: body
|
||||
}).then(res => res.json()).then(res => {
|
||||
fetchingUrl = false;
|
||||
const err = res["error"];
|
||||
@@ -158,7 +170,11 @@ function postData(e) {
|
||||
}
|
||||
const url = res["url"];
|
||||
if (url) {
|
||||
document.location.href = url;
|
||||
if(isUnraid) {
|
||||
window.open(url, "_blank");
|
||||
} else {
|
||||
document.location.href = url;
|
||||
}
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
func configureTaildrop(logf logger.Logf, lb *ipnlocal.LocalBackend) {
|
||||
dg := distro.Get()
|
||||
switch dg {
|
||||
case distro.Synology, distro.TrueNAS, distro.QNAP:
|
||||
case distro.Synology, distro.TrueNAS, distro.QNAP, distro.Unraid:
|
||||
// See if they have a "Taildrop" share.
|
||||
// See https://github.com/tailscale/tailscale/issues/2179#issuecomment-982821319
|
||||
path, err := findTaildropDir(dg)
|
||||
@@ -42,6 +42,8 @@ func findTaildropDir(dg distro.Distro) (string, error) {
|
||||
return findTrueNASTaildropDir(name)
|
||||
case distro.QNAP:
|
||||
return findQnapTaildropDir(name)
|
||||
case distro.Unraid:
|
||||
return findUnraidTaildropDir(name)
|
||||
}
|
||||
return "", fmt.Errorf("%s is an unsupported distro for Taildrop dir", dg)
|
||||
}
|
||||
@@ -103,3 +105,25 @@ func findQnapTaildropDir(name string) (string, error) {
|
||||
}
|
||||
return "", fmt.Errorf("shared folder %q not found", name)
|
||||
}
|
||||
|
||||
// findUnraidTaildropDir looks for a directory linked at
|
||||
// /var/lib/tailscale/Taildrop. This is a symlink to the
|
||||
// path specified by the user in the Unraid Web UI
|
||||
func findUnraidTaildropDir(name string) (string, error) {
|
||||
dir := fmt.Sprintf("/var/lib/tailscale/%s", name)
|
||||
_, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("symlink %q not found", name)
|
||||
}
|
||||
|
||||
fullpath, err := filepath.EvalSymlinks(dir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("symlink %q to shared folder not valid", name)
|
||||
}
|
||||
|
||||
fi, err := os.Stat(fullpath)
|
||||
if err == nil && fi.IsDir() {
|
||||
return dir, nil // return the symlink
|
||||
}
|
||||
return "", fmt.Errorf("shared folder %q not found", name)
|
||||
}
|
||||
|
||||
@@ -457,13 +457,24 @@ var applyDiskConfigErr error
|
||||
// ApplyDiskConfigError returns the most recent result of ApplyDiskConfig.
|
||||
func ApplyDiskConfigError() error { return applyDiskConfigErr }
|
||||
|
||||
// ApplyDiskConfig returns a platform-specific config file of environment keys/values and
|
||||
// applies them. On Linux and Unix operating systems, it's a no-op and always returns nil.
|
||||
// If no platform-specific config file is found, it also returns nil.
|
||||
// ApplyDiskConfig returns a platform-specific config file of environment
|
||||
// keys/values and applies them. On Linux and Unix operating systems, it's a
|
||||
// no-op and always returns nil. If no platform-specific config file is found,
|
||||
// it also returns nil.
|
||||
//
|
||||
// It exists primarily for Windows and macOS to make it easy to apply
|
||||
// environment variables to a running service in a way similar to modifying
|
||||
// /etc/default/tailscaled on Linux.
|
||||
//
|
||||
// It exists primarily for Windows to make it easy to apply environment variables to
|
||||
// a running service in a way similar to modifying /etc/default/tailscaled on Linux.
|
||||
// On Windows, you use %ProgramData%\Tailscale\tailscaled-env.txt instead.
|
||||
//
|
||||
// On macOS, use one of:
|
||||
//
|
||||
// - ~/Library/Containers/io.tailscale.ipn.macsys/Data/tailscaled-env.txt
|
||||
// for standalone macOS GUI builds
|
||||
// - ~/Library/Containers/io.tailscale.ipn.macos.network-extension/Data/tailscaled-env.txt
|
||||
// for App Store builds
|
||||
// - /etc/tailscale/tailscaled-env.txt for tailscaled-on-macOS (homebrew, etc)
|
||||
func ApplyDiskConfig() (err error) {
|
||||
var f *os.File
|
||||
defer func() {
|
||||
@@ -512,9 +523,15 @@ func getPlatformEnvFile() string {
|
||||
return "/etc/tailscale/tailscaled-env.txt"
|
||||
}
|
||||
case "darwin":
|
||||
// TODO(bradfitz): figure this out. There are three ways to run
|
||||
// Tailscale on macOS (tailscaled, GUI App Store, GUI System Extension)
|
||||
// and we should deal with all three.
|
||||
if version.IsSandboxedMacOS() { // the two GUI variants (App Store or separate download)
|
||||
// This will be user-visible as ~/Library/Containers/$VARIANT/Data/tailscaled-env.txt
|
||||
// where $VARIANT is "io.tailscale.ipn.macsys" for macsys (downloadable mac GUI builds)
|
||||
// or "io.tailscale.ipn.macos.network-extension" for App Store builds.
|
||||
return filepath.Join(os.Getenv("HOME"), "tailscaled-env.txt")
|
||||
} else {
|
||||
// Open source / homebrew variable, running tailscaled-on-macOS.
|
||||
return "/etc/tailscale/tailscaled-env.txt"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -115,4 +115,4 @@
|
||||
in
|
||||
flake-utils.lib.eachDefaultSystem (system: flakeForSystem nixpkgs system);
|
||||
}
|
||||
# nix-direnv cache busting line: sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM=
|
||||
# nix-direnv cache busting line: sha256-7L+dvS++UNfMVcPUCbK/xuBPwtrzW4RpZTtcl7VCwQs=
|
||||
|
||||
21
go.mod
21
go.mod
@@ -78,23 +78,23 @@ require (
|
||||
golang.org/x/mod v0.10.0
|
||||
golang.org/x/net v0.9.0
|
||||
golang.org/x/oauth2 v0.7.0
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.7.0
|
||||
golang.org/x/sync v0.2.0
|
||||
golang.org/x/sys v0.8.0
|
||||
golang.org/x/term v0.7.0
|
||||
golang.org/x/time v0.3.0
|
||||
golang.org/x/tools v0.8.0
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||
gvisor.dev/gvisor v0.0.0-20230328175328-162ed5ef888d
|
||||
gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f
|
||||
honnef.co/go/tools v0.4.3
|
||||
inet.af/peercred v0.0.0-20210906144145-0893ea02156a
|
||||
inet.af/tcpproxy v0.0.0-20221017015627-91f861402626
|
||||
inet.af/wf v0.0.0-20221017222439-36129f591884
|
||||
k8s.io/api v0.25.0
|
||||
k8s.io/apimachinery v0.25.0
|
||||
k8s.io/client-go v0.25.0
|
||||
k8s.io/api v0.26.1
|
||||
k8s.io/apimachinery v0.26.1
|
||||
k8s.io/client-go v0.26.1
|
||||
nhooyr.io/websocket v1.8.7
|
||||
sigs.k8s.io/controller-runtime v0.13.1
|
||||
sigs.k8s.io/controller-runtime v0.14.6
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
software.sslmate.com/src/go-pkcs12 v0.2.0
|
||||
)
|
||||
@@ -203,7 +203,7 @@ require (
|
||||
github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 // indirect
|
||||
github.com/google/rpmpack v0.0.0-20221120200012-98b63d62fd77 // indirect
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 // indirect
|
||||
github.com/goreleaser/chglog v0.1.2 // indirect
|
||||
github.com/goreleaser/chglog v0.4.2 // indirect
|
||||
github.com/goreleaser/fileglob v0.3.1 // indirect
|
||||
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
|
||||
github.com/gostaticanalysis/comment v1.4.2 // indirect
|
||||
@@ -328,6 +328,7 @@ require (
|
||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
||||
github.com/yeya24/promlinter v0.2.0 // indirect
|
||||
gitlab.com/bosi/decorder v0.2.3 // indirect
|
||||
gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53 // indirect
|
||||
@@ -342,8 +343,8 @@ require (
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
howett.net/plist v1.0.0 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.25.0 // indirect
|
||||
k8s.io/component-base v0.25.0 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.26.1 // indirect
|
||||
k8s.io/component-base v0.26.1 // indirect
|
||||
k8s.io/klog/v2 v2.100.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
|
||||
|
||||
@@ -1 +1 @@
|
||||
sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM=
|
||||
sha256-7L+dvS++UNfMVcPUCbK/xuBPwtrzW4RpZTtcl7VCwQs=
|
||||
|
||||
50
go.sum
50
go.sum
@@ -526,11 +526,13 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
||||
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/gookit/color v1.3.1/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
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/goreleaser/chglog v0.1.2 h1:tdzAb/ILeMnphzI9zQ7Nkq+T8R9qyXli8GydD8plFRY=
|
||||
github.com/goreleaser/chglog v0.1.2/go.mod h1:tTZsFuSZK4epDXfjMkxzcGbrIOXprf0JFp47BjIr3B8=
|
||||
github.com/goreleaser/chglog v0.4.2 h1:afmbT1d7lX/q+GF8wv3a1Dofs2j/Y9YkiCpGemWR6mI=
|
||||
github.com/goreleaser/chglog v0.4.2/go.mod h1:u/F03un4hMCQrp65qSWCkkC6T+G7YLKZ+AM2mITE47s=
|
||||
github.com/goreleaser/fileglob v0.3.1 h1:OTFDWqUUHjQazk2N5GdUqEbqT/grBnRARaAXsV07q1Y=
|
||||
github.com/goreleaser/fileglob v0.3.1/go.mod h1:kNcPrPzjCp+Ox3jmXLU5QEsjhqrtLBm6OnXAif8KRl8=
|
||||
github.com/goreleaser/nfpm v1.10.3 h1:NzpWKKzSFr7JOn55XN0SskyFOjP6BkvRt3JujoX8fws=
|
||||
@@ -646,6 +648,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
@@ -821,14 +824,13 @@ github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3L
|
||||
github.com/nunnatsa/ginkgolinter v0.11.2 h1:xzQpAsEyZe5F1RMy2Z5kn8UFCGiWfKqJOUd2ZzBXA4M=
|
||||
github.com/nunnatsa/ginkgolinter v0.11.2/go.mod h1:dJIGXYXbkBswqa/pIzG0QlVTTDSBMxDoCFwhsl4Uras=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
|
||||
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
@@ -984,7 +986,9 @@ github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXi
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI=
|
||||
github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00=
|
||||
@@ -1153,6 +1157,8 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
||||
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/digitalxero/go-conventional-commit v1.0.7 h1:8/dO6WWG+98PMhlZowt/YjuiKhqhGlOCwlIV8SqqGh8=
|
||||
gitlab.com/digitalxero/go-conventional-commit v1.0.7/go.mod h1:05Xc2BFsSyC5tKhK0y+P3bs0AwUtNuTp+mTpbCU/DZ0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
@@ -1166,7 +1172,7 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@@ -1336,8 +1342,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-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.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-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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=
|
||||
@@ -1425,8 +1432,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/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-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
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=
|
||||
@@ -1686,7 +1693,6 @@ gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
@@ -1708,8 +1714,8 @@ gopkg.in/yaml.v3 v3.0.0/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=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gvisor.dev/gvisor v0.0.0-20230328175328-162ed5ef888d h1:pzPNKWBCLdzu7KGiFnFGuvKsLf+pNkOzHSK6zJ9tMKY=
|
||||
gvisor.dev/gvisor v0.0.0-20230328175328-162ed5ef888d/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
|
||||
gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f h1:8GE2MRjGiFmfpon8dekPI08jEuNMQzSffVHgdupcO4E=
|
||||
gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
|
||||
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=
|
||||
@@ -1728,16 +1734,16 @@ inet.af/tcpproxy v0.0.0-20221017015627-91f861402626 h1:2dMP3Ox/Wh5BiItwOt4jxRsfz
|
||||
inet.af/tcpproxy v0.0.0-20221017015627-91f861402626/go.mod h1:Tojt5kmHpDIR2jMojxzZK2w2ZR7OILODmUo2gaSwjrk=
|
||||
inet.af/wf v0.0.0-20221017222439-36129f591884 h1:zg9snq3Cpy50lWuVqDYM7AIRVTtU50y5WXETMFohW/Q=
|
||||
inet.af/wf v0.0.0-20221017222439-36129f591884/go.mod h1:bSAQ38BYbY68uwpasXOTZo22dKGy9SNvI6PZFeKomZE=
|
||||
k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0=
|
||||
k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk=
|
||||
k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY=
|
||||
k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E=
|
||||
k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU=
|
||||
k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
|
||||
k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
|
||||
k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
|
||||
k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y=
|
||||
k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk=
|
||||
k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ=
|
||||
k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg=
|
||||
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
|
||||
k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM=
|
||||
k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ=
|
||||
k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
|
||||
k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU=
|
||||
k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE=
|
||||
k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4=
|
||||
k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU=
|
||||
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
|
||||
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
|
||||
@@ -1761,8 +1767,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/controller-runtime v0.13.1 h1:tUsRCSJVM1QQOOeViGeX3GMT3dQF1eePPw6sEE3xSlg=
|
||||
sigs.k8s.io/controller-runtime v0.13.1/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI=
|
||||
sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA=
|
||||
sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
||||
|
||||
@@ -95,6 +95,8 @@ func linuxVersionMeta() (meta versionMeta) {
|
||||
propFile = "/etc.defaults/VERSION"
|
||||
case distro.OpenWrt:
|
||||
propFile = "/etc/openwrt_release"
|
||||
case distro.Unraid:
|
||||
propFile = "/etc/unraid-version"
|
||||
case distro.WDMyCloud:
|
||||
slurp, _ := os.ReadFile("/etc/version")
|
||||
meta.DistroVersion = string(bytes.TrimSpace(slurp))
|
||||
@@ -153,6 +155,8 @@ func linuxVersionMeta() (meta versionMeta) {
|
||||
meta.DistroVersion = m["productversion"]
|
||||
case distro.OpenWrt:
|
||||
meta.DistroVersion = m["DISTRIB_RELEASE"]
|
||||
case distro.Unraid:
|
||||
meta.DistroVersion = m["version"]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import (
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/util/clientmetric"
|
||||
"tailscale.com/util/multierr"
|
||||
"tailscale.com/version/distro"
|
||||
"tailscale.com/wgengine"
|
||||
"tailscale.com/wgengine/filter"
|
||||
)
|
||||
@@ -1090,6 +1091,10 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, errNoTaildrop.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if distro.Get() == distro.Unraid && !h.ps.directFileMode {
|
||||
http.Error(w, "Taildrop folder not configured or accessible", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
rawPath := r.URL.EscapedPath()
|
||||
suffix, ok := strings.CutPrefix(rawPath, "/v0/put/")
|
||||
if !ok {
|
||||
|
||||
@@ -321,6 +321,17 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEST_URL="https://pkgs.tailscale.com/"
|
||||
RC=0
|
||||
TEST_OUT=$($CURL "$TEST_URL" 2>&1) || RC=$?
|
||||
if [ $RC != 0 ]; then
|
||||
echo "The installer cannot reach $TEST_URL"
|
||||
echo "Please make sure that your machine has internet access."
|
||||
echo "Test output:"
|
||||
echo $TEST_OUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 2: having detected an OS we support, is it one of the
|
||||
# versions we support?
|
||||
OS_UNSUPPORTED=
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
) {
|
||||
src = ./.;
|
||||
}).shellNix
|
||||
# nix-direnv cache busting line: sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM=
|
||||
# nix-direnv cache busting line: sha256-7L+dvS++UNfMVcPUCbK/xuBPwtrzW4RpZTtcl7VCwQs=
|
||||
|
||||
@@ -5,9 +5,8 @@ package tailcfg
|
||||
|
||||
//go:generate go run tailscale.com/cmd/viewer --type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan --clonefunc
|
||||
|
||||
//go:generage go run tailscale.com/cmd/equaler --type Node,Hostinfo,NetInfo,Service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -498,7 +497,7 @@ const (
|
||||
|
||||
// Service represents a service running on a node.
|
||||
type Service struct {
|
||||
_ structs.Incomparable `codegen:"noequal"`
|
||||
_ structs.Incomparable
|
||||
|
||||
// Proto is the type of service. It's usually the constant TCP
|
||||
// or UDP ("tcp" or "udp"), but it can also be one of the
|
||||
@@ -583,6 +582,9 @@ type Hostinfo struct {
|
||||
Cloud string `json:",omitempty"`
|
||||
Userspace opt.Bool `json:",omitempty"` // if the client is running in userspace (netstack) mode
|
||||
UserspaceRouter opt.Bool `json:",omitempty"` // if the client's subnet router is running in userspace (netstack) mode
|
||||
|
||||
// NOTE: any new fields containing pointers in this type
|
||||
// require changes to Hostinfo.Equal.
|
||||
}
|
||||
|
||||
// TailscaleSSHEnabled reports whether or not this node is acting as a
|
||||
@@ -662,7 +664,9 @@ type NetInfo struct {
|
||||
// This should only be updated rarely, or when there's a
|
||||
// material change, as any change here also gets uploaded to
|
||||
// the control plane.
|
||||
DERPLatency map[string]float64 `json:",omitempty" codegen:"noequal"`
|
||||
DERPLatency map[string]float64 `json:",omitempty"`
|
||||
|
||||
// Update BasicallyEqual when adding fields.
|
||||
}
|
||||
|
||||
func (ni *NetInfo) String() string {
|
||||
@@ -700,6 +704,40 @@ func conciseOptBool(b opt.Bool, trueVal string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// BasicallyEqual reports whether ni and ni2 are basically equal, ignoring
|
||||
// changes in DERP ServerLatency & RegionLatency.
|
||||
func (ni *NetInfo) BasicallyEqual(ni2 *NetInfo) bool {
|
||||
if (ni == nil) != (ni2 == nil) {
|
||||
return false
|
||||
}
|
||||
if ni == nil {
|
||||
return true
|
||||
}
|
||||
return ni.MappingVariesByDestIP == ni2.MappingVariesByDestIP &&
|
||||
ni.HairPinning == ni2.HairPinning &&
|
||||
ni.WorkingIPv6 == ni2.WorkingIPv6 &&
|
||||
ni.OSHasIPv6 == ni2.OSHasIPv6 &&
|
||||
ni.WorkingUDP == ni2.WorkingUDP &&
|
||||
ni.WorkingICMPv4 == ni2.WorkingICMPv4 &&
|
||||
ni.HavePortMap == ni2.HavePortMap &&
|
||||
ni.UPnP == ni2.UPnP &&
|
||||
ni.PMP == ni2.PMP &&
|
||||
ni.PCP == ni2.PCP &&
|
||||
ni.PreferredDERP == ni2.PreferredDERP &&
|
||||
ni.LinkType == ni2.LinkType
|
||||
}
|
||||
|
||||
// Equal reports whether h and h2 are equal.
|
||||
func (h *Hostinfo) Equal(h2 *Hostinfo) bool {
|
||||
if h == nil && h2 == nil {
|
||||
return true
|
||||
}
|
||||
if (h == nil) != (h2 == nil) {
|
||||
return false
|
||||
}
|
||||
return reflect.DeepEqual(h, h2)
|
||||
}
|
||||
|
||||
// HowUnequal returns a list of paths through Hostinfo where h and h2 differ.
|
||||
// If they differ in nil-ness, the path is "nil", otherwise the path is like
|
||||
// "ShieldsUp" or "NetInfo.nil" or "NetInfo.PCP".
|
||||
@@ -1651,6 +1689,82 @@ func (id UserID) String() string { return fmt.Sprintf("userid:%x", int64(id)) }
|
||||
func (id LoginID) String() string { return fmt.Sprintf("loginid:%x", int64(id)) }
|
||||
func (id NodeID) String() string { return fmt.Sprintf("nodeid:%x", int64(id)) }
|
||||
|
||||
// Equal reports whether n and n2 are equal.
|
||||
func (n *Node) Equal(n2 *Node) bool {
|
||||
if n == nil && n2 == nil {
|
||||
return true
|
||||
}
|
||||
return n != nil && n2 != nil &&
|
||||
n.ID == n2.ID &&
|
||||
n.StableID == n2.StableID &&
|
||||
n.Name == n2.Name &&
|
||||
n.User == n2.User &&
|
||||
n.Sharer == n2.Sharer &&
|
||||
n.UnsignedPeerAPIOnly == n2.UnsignedPeerAPIOnly &&
|
||||
n.Key == n2.Key &&
|
||||
n.KeyExpiry.Equal(n2.KeyExpiry) &&
|
||||
bytes.Equal(n.KeySignature, n2.KeySignature) &&
|
||||
n.Machine == n2.Machine &&
|
||||
n.DiscoKey == n2.DiscoKey &&
|
||||
eqPtr(n.Online, n2.Online) &&
|
||||
eqCIDRs(n.Addresses, n2.Addresses) &&
|
||||
eqCIDRs(n.AllowedIPs, n2.AllowedIPs) &&
|
||||
eqCIDRs(n.PrimaryRoutes, n2.PrimaryRoutes) &&
|
||||
eqStrings(n.Endpoints, n2.Endpoints) &&
|
||||
n.DERP == n2.DERP &&
|
||||
n.Cap == n2.Cap &&
|
||||
n.Hostinfo.Equal(n2.Hostinfo) &&
|
||||
n.Created.Equal(n2.Created) &&
|
||||
eqTimePtr(n.LastSeen, n2.LastSeen) &&
|
||||
n.MachineAuthorized == n2.MachineAuthorized &&
|
||||
eqStrings(n.Capabilities, n2.Capabilities) &&
|
||||
n.ComputedName == n2.ComputedName &&
|
||||
n.computedHostIfDifferent == n2.computedHostIfDifferent &&
|
||||
n.ComputedNameWithHost == n2.ComputedNameWithHost &&
|
||||
eqStrings(n.Tags, n2.Tags) &&
|
||||
n.Expired == n2.Expired &&
|
||||
eqPtr(n.SelfNodeV4MasqAddrForThisPeer, n2.SelfNodeV4MasqAddrForThisPeer) &&
|
||||
n.IsWireGuardOnly == n2.IsWireGuardOnly
|
||||
}
|
||||
|
||||
func eqPtr[T comparable](a, b *T) bool {
|
||||
if a == b { // covers nil
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return *a == *b
|
||||
}
|
||||
|
||||
func eqStrings(a, b []string) bool {
|
||||
if len(a) != len(b) || ((a == nil) != (b == nil)) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func eqCIDRs(a, b []netip.Prefix) bool {
|
||||
if len(a) != len(b) || ((a == nil) != (b == nil)) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func eqTimePtr(a, b *time.Time) bool {
|
||||
return ((a == nil) == (b == nil)) && (a == nil || a.Equal(*b))
|
||||
}
|
||||
|
||||
// Oauth2Token is a copy of golang.org/x/oauth2.Token, to avoid the
|
||||
// go.mod dependency on App Engine and grpc, which was causing problems.
|
||||
// All we actually needed was this struct on the client side.
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Code generated by tailscale.com/cmd/equaler; DO NOT EDIT.
|
||||
|
||||
package tailcfg
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/opt"
|
||||
"tailscale.com/types/structs"
|
||||
"tailscale.com/types/tkatype"
|
||||
)
|
||||
|
||||
// Equal reports whether a and b are equal.
|
||||
func (a *Node) Equal(b *Node) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
return a != nil && b != nil &&
|
||||
a.ID == b.ID &&
|
||||
a.StableID == b.StableID &&
|
||||
a.Name == b.Name &&
|
||||
a.User == b.User &&
|
||||
a.Sharer == b.Sharer &&
|
||||
a.Key == b.Key &&
|
||||
a.KeyExpiry.Equal(b.KeyExpiry) &&
|
||||
((a.KeySignature == nil) == (b.KeySignature == nil)) &&
|
||||
slices.Equal(a.KeySignature, b.KeySignature) &&
|
||||
a.Machine == b.Machine &&
|
||||
a.DiscoKey == b.DiscoKey &&
|
||||
((a.Addresses == nil) == (b.Addresses == nil)) &&
|
||||
slices.Equal(a.Addresses, b.Addresses) &&
|
||||
((a.AllowedIPs == nil) == (b.AllowedIPs == nil)) &&
|
||||
slices.Equal(a.AllowedIPs, b.AllowedIPs) &&
|
||||
((a.Endpoints == nil) == (b.Endpoints == nil)) &&
|
||||
slices.Equal(a.Endpoints, b.Endpoints) &&
|
||||
a.DERP == b.DERP &&
|
||||
a.Hostinfo.Equal(b.Hostinfo) &&
|
||||
a.Created.Equal(b.Created) &&
|
||||
a.Cap == b.Cap &&
|
||||
((a.Tags == nil) == (b.Tags == nil)) &&
|
||||
slices.Equal(a.Tags, b.Tags) &&
|
||||
((a.PrimaryRoutes == nil) == (b.PrimaryRoutes == nil)) &&
|
||||
slices.Equal(a.PrimaryRoutes, b.PrimaryRoutes) &&
|
||||
((a.LastSeen == nil) == (b.LastSeen == nil)) && (a.LastSeen == nil || a.LastSeen.Equal(*b.LastSeen)) &&
|
||||
((a.Online == nil) == (b.Online == nil)) && (a.Online == nil || *a.Online == *b.Online) &&
|
||||
a.KeepAlive == b.KeepAlive &&
|
||||
a.MachineAuthorized == b.MachineAuthorized &&
|
||||
((a.Capabilities == nil) == (b.Capabilities == nil)) &&
|
||||
slices.Equal(a.Capabilities, b.Capabilities) &&
|
||||
a.UnsignedPeerAPIOnly == b.UnsignedPeerAPIOnly &&
|
||||
a.ComputedName == b.ComputedName &&
|
||||
a.computedHostIfDifferent == b.computedHostIfDifferent &&
|
||||
a.ComputedNameWithHost == b.ComputedNameWithHost &&
|
||||
a.DataPlaneAuditLogID == b.DataPlaneAuditLogID &&
|
||||
a.Expired == b.Expired &&
|
||||
((a.SelfNodeV4MasqAddrForThisPeer == nil) == (b.SelfNodeV4MasqAddrForThisPeer == nil)) && (a.SelfNodeV4MasqAddrForThisPeer == nil || *a.SelfNodeV4MasqAddrForThisPeer == *b.SelfNodeV4MasqAddrForThisPeer) &&
|
||||
a.IsWireGuardOnly == b.IsWireGuardOnly &&
|
||||
true
|
||||
}
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _NodeEqualNeedsRegeneration = Node(struct {
|
||||
ID NodeID
|
||||
StableID StableNodeID
|
||||
Name string
|
||||
User UserID
|
||||
Sharer UserID
|
||||
Key key.NodePublic
|
||||
KeyExpiry time.Time
|
||||
KeySignature tkatype.MarshaledSignature
|
||||
Machine key.MachinePublic
|
||||
DiscoKey key.DiscoPublic
|
||||
Addresses []netip.Prefix
|
||||
AllowedIPs []netip.Prefix
|
||||
Endpoints []string
|
||||
DERP string
|
||||
Hostinfo HostinfoView
|
||||
Created time.Time
|
||||
Cap CapabilityVersion
|
||||
Tags []string
|
||||
PrimaryRoutes []netip.Prefix
|
||||
LastSeen *time.Time
|
||||
Online *bool
|
||||
KeepAlive bool
|
||||
MachineAuthorized bool
|
||||
Capabilities []string
|
||||
UnsignedPeerAPIOnly bool
|
||||
ComputedName string
|
||||
computedHostIfDifferent string
|
||||
ComputedNameWithHost string
|
||||
DataPlaneAuditLogID string
|
||||
Expired bool
|
||||
SelfNodeV4MasqAddrForThisPeer *netip.Addr
|
||||
IsWireGuardOnly bool
|
||||
}{})
|
||||
|
||||
// Equal reports whether a and b are equal.
|
||||
func (a *Hostinfo) Equal(b *Hostinfo) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
return a != nil && b != nil &&
|
||||
a.IPNVersion == b.IPNVersion &&
|
||||
a.FrontendLogID == b.FrontendLogID &&
|
||||
a.BackendLogID == b.BackendLogID &&
|
||||
a.OS == b.OS &&
|
||||
a.OSVersion == b.OSVersion &&
|
||||
a.Container == b.Container &&
|
||||
a.Env == b.Env &&
|
||||
a.Distro == b.Distro &&
|
||||
a.DistroVersion == b.DistroVersion &&
|
||||
a.DistroCodeName == b.DistroCodeName &&
|
||||
a.App == b.App &&
|
||||
a.Desktop == b.Desktop &&
|
||||
a.Package == b.Package &&
|
||||
a.DeviceModel == b.DeviceModel &&
|
||||
a.PushDeviceToken == b.PushDeviceToken &&
|
||||
a.Hostname == b.Hostname &&
|
||||
a.ShieldsUp == b.ShieldsUp &&
|
||||
a.ShareeNode == b.ShareeNode &&
|
||||
a.NoLogsNoSupport == b.NoLogsNoSupport &&
|
||||
a.WireIngress == b.WireIngress &&
|
||||
a.AllowsUpdate == b.AllowsUpdate &&
|
||||
a.Machine == b.Machine &&
|
||||
a.GoArch == b.GoArch &&
|
||||
a.GoArchVar == b.GoArchVar &&
|
||||
a.GoVersion == b.GoVersion &&
|
||||
((a.RoutableIPs == nil) == (b.RoutableIPs == nil)) &&
|
||||
slices.Equal(a.RoutableIPs, b.RoutableIPs) &&
|
||||
((a.RequestTags == nil) == (b.RequestTags == nil)) &&
|
||||
slices.Equal(a.RequestTags, b.RequestTags) &&
|
||||
((a.Services == nil) == (b.Services == nil)) &&
|
||||
slices.EqualFunc(a.Services, b.Services, func(aa Service, bb Service) bool { return aa.Equal(&bb) }) &&
|
||||
((a.NetInfo == nil) == (b.NetInfo == nil)) && (a.NetInfo == nil || a.NetInfo.Equal(b.NetInfo)) &&
|
||||
((a.SSH_HostKeys == nil) == (b.SSH_HostKeys == nil)) &&
|
||||
slices.Equal(a.SSH_HostKeys, b.SSH_HostKeys) &&
|
||||
a.Cloud == b.Cloud &&
|
||||
a.Userspace == b.Userspace &&
|
||||
a.UserspaceRouter == b.UserspaceRouter &&
|
||||
true
|
||||
}
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _HostinfoEqualNeedsRegeneration = Hostinfo(struct {
|
||||
IPNVersion string
|
||||
FrontendLogID string
|
||||
BackendLogID string
|
||||
OS string
|
||||
OSVersion string
|
||||
Container opt.Bool
|
||||
Env string
|
||||
Distro string
|
||||
DistroVersion string
|
||||
DistroCodeName string
|
||||
App string
|
||||
Desktop opt.Bool
|
||||
Package string
|
||||
DeviceModel string
|
||||
PushDeviceToken string
|
||||
Hostname string
|
||||
ShieldsUp bool
|
||||
ShareeNode bool
|
||||
NoLogsNoSupport bool
|
||||
WireIngress bool
|
||||
AllowsUpdate bool
|
||||
Machine string
|
||||
GoArch string
|
||||
GoArchVar string
|
||||
GoVersion string
|
||||
RoutableIPs []netip.Prefix
|
||||
RequestTags []string
|
||||
Services []Service
|
||||
NetInfo *NetInfo
|
||||
SSH_HostKeys []string
|
||||
Cloud string
|
||||
Userspace opt.Bool
|
||||
UserspaceRouter opt.Bool
|
||||
}{})
|
||||
|
||||
// Equal reports whether a and b are equal.
|
||||
func (a *NetInfo) Equal(b *NetInfo) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
return a != nil && b != nil &&
|
||||
a.MappingVariesByDestIP == b.MappingVariesByDestIP &&
|
||||
a.HairPinning == b.HairPinning &&
|
||||
a.WorkingIPv6 == b.WorkingIPv6 &&
|
||||
a.OSHasIPv6 == b.OSHasIPv6 &&
|
||||
a.WorkingUDP == b.WorkingUDP &&
|
||||
a.WorkingICMPv4 == b.WorkingICMPv4 &&
|
||||
a.HavePortMap == b.HavePortMap &&
|
||||
a.UPnP == b.UPnP &&
|
||||
a.PMP == b.PMP &&
|
||||
a.PCP == b.PCP &&
|
||||
a.PreferredDERP == b.PreferredDERP &&
|
||||
a.LinkType == b.LinkType &&
|
||||
// Skipping DERPLatency because of codegen:noequal
|
||||
true
|
||||
}
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _NetInfoEqualNeedsRegeneration = NetInfo(struct {
|
||||
MappingVariesByDestIP opt.Bool
|
||||
HairPinning opt.Bool
|
||||
WorkingIPv6 opt.Bool
|
||||
OSHasIPv6 opt.Bool
|
||||
WorkingUDP opt.Bool
|
||||
WorkingICMPv4 opt.Bool
|
||||
HavePortMap bool
|
||||
UPnP opt.Bool
|
||||
PMP opt.Bool
|
||||
PCP opt.Bool
|
||||
PreferredDERP int
|
||||
LinkType string
|
||||
DERPLatency map[string]float64
|
||||
}{})
|
||||
|
||||
// Equal reports whether a and b are equal.
|
||||
func (a *Service) Equal(b *Service) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
return a != nil && b != nil &&
|
||||
// Skipping _ because of codegen:noequal
|
||||
a.Proto == b.Proto &&
|
||||
a.Port == b.Port &&
|
||||
a.Description == b.Description &&
|
||||
true
|
||||
}
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _ServiceEqualNeedsRegeneration = Service(struct {
|
||||
_ structs.Incomparable
|
||||
Proto ServiceProto
|
||||
Port uint16
|
||||
Description string
|
||||
}{})
|
||||
@@ -572,7 +572,7 @@ func TestNetInfoFields(t *testing.T) {
|
||||
"DERPLatency",
|
||||
}
|
||||
if have := fieldsOf(reflect.TypeOf(NetInfo{})); !reflect.DeepEqual(have, handled) {
|
||||
t.Errorf("NetInfo.Clone/Equal check might be out of sync\nfields: %q\nhandled: %q\n",
|
||||
t.Errorf("NetInfo.Clone/BasicallyEqually check might be out of sync\nfields: %q\nhandled: %q\n",
|
||||
have, handled)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,6 @@ func (v NetInfoView) LinkType() string { return v.ж.LinkType }
|
||||
|
||||
func (v NetInfoView) DERPLatency() views.Map[string, float64] { return views.MapOf(v.ж.DERPLatency) }
|
||||
func (v NetInfoView) String() string { return v.ж.String() }
|
||||
func (v NetInfoView) Equal(v2 NetInfoView) bool { return v.ж.Equal(v2.ж) }
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _NetInfoViewNeedsRegeneration = NetInfo(struct {
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"golang.org/x/tools/imports"
|
||||
"tailscale.com/util/mak"
|
||||
@@ -48,13 +47,12 @@ func LoadTypes(buildTags string, pkgName string) (*packages.Package, map[string]
|
||||
// HasNoClone reports whether the provided tag has `codegen:noclone`.
|
||||
func HasNoClone(structTag string) bool {
|
||||
val := reflect.StructTag(structTag).Get("codegen")
|
||||
return slices.Contains(strings.Split(val, ","), "noclone")
|
||||
}
|
||||
|
||||
// HasNoEqual reports whether the provided tag has `codegen:noequal`.
|
||||
func HasNoEqual(structTag string) bool {
|
||||
val := reflect.StructTag(structTag).Get("codegen")
|
||||
return slices.Contains(strings.Split(val, ","), "noequal")
|
||||
for _, v := range strings.Split(val, ",") {
|
||||
if v == "noclone" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const copyrightHeader = `// Copyright (c) Tailscale Inc & AUTHORS
|
||||
|
||||
@@ -29,6 +29,7 @@ const (
|
||||
TrueNAS = Distro("truenas")
|
||||
Gokrazy = Distro("gokrazy")
|
||||
WDMyCloud = Distro("wdmycloud")
|
||||
Unraid = Distro("unraid")
|
||||
)
|
||||
|
||||
var distro lazy.SyncValue[Distro]
|
||||
@@ -90,6 +91,8 @@ func linuxDistro() Distro {
|
||||
return WDMyCloud
|
||||
case have("/usr/sbin/wd_crontab.sh"): // Western Digital MyCloud OS5
|
||||
return WDMyCloud
|
||||
case have("/etc/unraid-version"):
|
||||
return Unraid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -951,7 +951,7 @@ func (c *Conn) pickDERPFallback() int {
|
||||
func (c *Conn) callNetInfoCallback(ni *tailcfg.NetInfo) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if ni.Equal(c.netInfoLast) {
|
||||
if ni.BasicallyEqual(c.netInfoLast) {
|
||||
return
|
||||
}
|
||||
c.callNetInfoCallbackLocked(ni)
|
||||
|
||||
Reference in New Issue
Block a user