diff --git a/Makefile b/Makefile index d44046290..c5b617bfb 100644 --- a/Makefile +++ b/Makefile @@ -77,13 +77,13 @@ publishdevoperator: ## Build and publish k8s-operator image to location specifie @test "${REPO}" != "ghcr.io/tailscale/k8s-operator" || (echo "REPO=... must not be ghcr.io/tailscale/k8s-operator" && exit 1) TAGS=latest REPOS=${REPO} PUSH=true TARGET=operator ./build_docker.sh -publishdevnameserver: ## Build and publish nameserver to location specified by ${REPO} +publishdevk8snameserver: ## Build and publish k8s-nameserver image to location specified by ${REPO} @test -n "${REPO}" || (echo "REPO=... required; e.g. REPO=ghcr.io/${USER}/tailscale" && exit 1) @test "${REPO}" != "tailscale/tailscale" || (echo "REPO=... must not be tailscale/tailscale" && exit 1) @test "${REPO}" != "ghcr.io/tailscale/tailscale" || (echo "REPO=... must not be ghcr.io/tailscale/tailscale" && exit 1) - @test "${REPO}" != "tailscale/nameserver" || (echo "REPO=... must not be tailscale/nameserver" && exit 1) - @test "${REPO}" != "ghcr.io/tailscale/nameserver" || (echo "REPO=... must not be ghcr.io/tailscale/nameserver" && exit 1) - TAGS=latest REPOS=${REPO} PUSH=true TARGET=nameserver ./build_docker.sh + @test "${REPO}" != "tailscale/k8s-nameserver" || (echo "REPO=... must not be tailscale/k8s-nameserver" && exit 1) + @test "${REPO}" != "ghcr.io/tailscale/k8s-nameserver" || (echo "REPO=... must not be ghcr.io/k8s-tailscale/nameserver" && exit 1) + TAGS=latest REPOS=${REPO} PUSH=true TARGET=k8s-nameserver ./build_docker.sh help: ## Show this help @echo "\nSpecify a command. The choices are:\n" diff --git a/build_docker.sh b/build_docker.sh index 9f5834557..d1d84042b 100755 --- a/build_docker.sh +++ b/build_docker.sh @@ -67,20 +67,20 @@ case "$TARGET" in --push="${PUSH}" \ /usr/local/bin/operator ;; - nameserver) - DEFAULT_REPOS="tailscale/nameserver" + k8s-nameserver) + DEFAULT_REPOS="tailscale/k8s-nameserver" REPOS="${REPOS:-${DEFAULT_REPOS}}" go run github.com/tailscale/mkctr \ - --gopaths="tailscale.com/cmd/nameserver:/usr/local/bin/nameserver" \ + --gopaths="tailscale.com/cmd/k8s-nameserver:/usr/local/bin/k8s-nameserver" \ --ldflags=" \ -X tailscale.com/version.longStamp=${VERSION_LONG} \ -X tailscale.com/version.shortStamp=${VERSION_SHORT} \ -X tailscale.com/version.gitCommitStamp=${VERSION_GIT_HASH}" \ --base="${BASE}" \ - --tags="${TAGS}" \ + --tags="v0.0.4refactor" \ --repos="${REPOS}" \ --push="${PUSH}" \ - /usr/local/bin/nameserver + /usr/local/bin/k8s-nameserver ;; *) echo "unknown target: $TARGET" diff --git a/cmd/nameserver/main.go b/cmd/k8s-nameserver/main.go similarity index 52% rename from cmd/nameserver/main.go rename to cmd/k8s-nameserver/main.go index 60bb9956b..866e608b2 100644 --- a/cmd/nameserver/main.go +++ b/cmd/k8s-nameserver/main.go @@ -20,45 +20,31 @@ import ( ) const ( - defaultDNSConfigDir = "/config" - defaultDNSFile = "dns.json" + defaultDNSConfigDir = "/tmp/dns" + defaultDNSFile = "dnsconfig.json" ) -type nameserver struct { - // config file holds FQDN to IP address mappings - configFilePath string - res resolver.Resolver - logf logger.Logf -} - func main() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + logger := log.Printf res := resolver.New(logger, nil, nil, &tsdial.Dialer{Logf: logger}) - ns := &nameserver{ - configFilePath: fmt.Sprintf("%s/%s", defaultDNSConfigDir, defaultDNSFile), - logf: logger, - res: *res, // TODO (irbekrm): linter error here + var configReader configReaderFunc = func() ([]byte, error) { + return os.ReadFile(fmt.Sprintf("%s/%s", defaultDNSConfigDir, defaultDNSFile)) } - // ensure resolver config is updated before starting to serve - err := ns.updateResolverConfig() - if err != nil { - logger("error updating resolver conf: %v", err) - panic(err) - } - logger("Hosts configured") - + c := make(chan string) watcher, err := fsnotify.NewWatcher() if err != nil { - logger("error starting file watcher: %v", err) + panic(err) } defer watcher.Close() go func() { - logger("starting DNS file watch") + logger("starting file watch for %s", defaultDNSConfigDir) for { - logger("in DNS file watch...") select { // TODO (irbekrm): it appears like we get a whole bunch // of different events (except for the WRITE one that @@ -69,6 +55,7 @@ func main() { case event, ok := <-watcher.Events: if !ok { logger("watcher finished") + cancel() return } // it seems like an update to the file has a @@ -79,32 +66,40 @@ func main() { // other events too as we run in a container and // there shouldn't be random changes to file // metadata - logger("a %v event detected, updating DNS config...", event) - // resolver locks config on updates so this is safe - err := ns.updateResolverConfig() - if err != nil { - logger("error updating resolver conf: %v", err) - continue - } - logger("Hosts updated") + msg := fmt.Sprintf("new file event: %v", event) + c <- msg + case err, ok := <-watcher.Errors: if !ok { - logger("watcher finished") + logger("errors watcher finished: %v", err) + cancel() return } if err != nil { - logger("error watching DNS config: %v", err) + logger("error watching directory: %w", err) + cancel() + return } } } - }() err = watcher.Add(defaultDNSConfigDir) if err != nil { - panic(fmt.Sprintf("error setting up DNS config watch: %v", err)) + panic(err) } - addr, err := net.ResolveUDPAddr("udp", ":53") + ns := &nameserver{ + configReader: configReader, + configWatcher: c, + logger: logger, + res: *res, // TODO (irbekrm): linter error here + } + + if err := ns.run(ctx, cancel); err != nil { + panic(fmt.Errorf("error running nameserver: %w", err)) + } + + addr, err := net.ResolveUDPAddr("udp", ":1053") if err != nil { panic("error resolving UDP address") } @@ -112,18 +107,22 @@ func main() { if err != nil { panic(fmt.Sprintf("error opening udp connection: %v", err)) } - defer conn.Close() - logger("nameserver listening on: %v", addr) + go func() { + <-ctx.Done() + conn.Close() + }() + + logger("k8s-nameserver listening on: %v", addr) for { payloadBuff := make([]byte, 10000) metadataBuff := make([]byte, 512) _, _, _, addr, err := conn.ReadMsgUDP(payloadBuff, metadataBuff) if err != nil { - logger("error reading from UDP socket: %v", err) - continue + panic(err) } - dnsAnswer, err := ns.res.Query(context.Background(), payloadBuff, addr.AddrPort()) + logger("query is %#+v", string(payloadBuff)) + dnsAnswer, err := ns.query(ctx, payloadBuff, addr.AddrPort()) if err != nil { logger("error doing DNS query: %v", err) // reply with the dnsAnswer anyway- in some cases @@ -133,31 +132,69 @@ func main() { } } +type nameserver struct { + configReader configReaderFunc + configWatcher <-chan string + res resolver.Resolver + logger logger.Logf +} + +type configReaderFunc func() ([]byte, error) + +// run ensures that resolver configuration is up to date with regards to its +// source. will update config once before returning and keep monitoring it in a +// thread. +func (n *nameserver) run(ctx context.Context, cancelF context.CancelFunc) error { + go func() { + for { + select { + case <-ctx.Done(): + n.logger("nameserver exiting") + return + case <-n.configWatcher: + n.logger("attempting to update resolver config...") + if err := n.updateResolverConfig(); err != nil { + n.logger("error updating resolver config: %w", err) + cancelF() + } + n.logger("successfully updated resolver config") + } + } + }() + if err := n.updateResolverConfig(); err != nil { + return fmt.Errorf("error updating resolver config: %w", err) + } + n.logger("successfully updated resolver config") + return nil +} + +func (n *nameserver) query(ctx context.Context, payload []byte, add netip.AddrPort) ([]byte, error) { + return n.res.Query(ctx, payload, add) +} + func (n *nameserver) updateResolverConfig() error { - // file is mounted to pod from a configmap so it cannot not exist - dnsCfgBytes, err := os.ReadFile(n.configFilePath) + dnsCfgBytes, err := n.configReader() if err != nil { - n.logf("error reading configFile: %v", err) + n.logger("error reading config: %v", err) return err } dnsCfgM := make(map[string]string) err = json.Unmarshal(dnsCfgBytes, &dnsCfgM) if err != nil { - n.logf("error unmarshaling json: %v", err) + n.logger("error unmarshaling json: %v", err) return err } c := resolver.Config{} c.Hosts = make(map[dnsname.FQDN][]netip.Addr) - // TODO (irbekrm): ensure that it handles the case of empty configmap for key, val := range dnsCfgM { fqdn, err := dnsname.ToFQDN(key) if err != nil { - n.logf("invalid DNS config: cannot convert %s to FQDN: %v", key, err) + n.logger("invalid DNS config: cannot convert %s to FQDN: %v", key, err) return err } ip, err := netip.ParseAddr(val) if err != nil { - n.logf("invalid DNS config: cannot convert %s to netip.Addr: %v", val, err) + n.logger("invalid DNS config: cannot convert %s to netip.Addr: %v", val, err) return err } c.Hosts[fqdn] = []netip.Addr{ip} diff --git a/cmd/k8s-nameserver/main_test.go b/cmd/k8s-nameserver/main_test.go new file mode 100644 index 000000000..a478b6760 --- /dev/null +++ b/cmd/k8s-nameserver/main_test.go @@ -0,0 +1,181 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !plan9 + +package main + +import ( + "context" + "log" + "net/netip" + "reflect" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "golang.org/x/net/dns/dnsmessage" + "tailscale.com/net/dns/resolver" + "tailscale.com/net/tsdial" +) + +func TestNameserver(t *testing.T) { + + // Setup + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + hostConfig := "{\"foo.bar.ts.net.\": \"10.20.30.40\"}" + + var mockConfigReader configReaderFunc = func() ([]byte, error) { + return []byte(hostConfig), nil + } + configWatcher := make(chan string) + logger := log.Printf + res := resolver.New(logger, nil, nil, &tsdial.Dialer{Logf: logger}) + + ns := &nameserver{ + configReader: mockConfigReader, + configWatcher: configWatcher, + logger: logger, + res: *res, + } + assert.NoError(t, ns.run(ctx, cancel), "error running nameserver") + + // Test that nameserver can resolve a DNS name from provided hosts config + + wantedResponse := dnsmessage.Message{ + Header: dnsmessage.Header{ + ID: 0x0, + Response: true, + OpCode: 0, + Authoritative: true, + Truncated: false, + RecursionDesired: false, + RecursionAvailable: false, + AuthenticData: false, + CheckingDisabled: false, + RCode: dnsmessage.RCodeSuccess, + }, + + Answers: []dnsmessage.Resource{{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName("foo.bar.ts.net."), + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET, + TTL: 0x258, + Length: 0x4, + }, + Body: &dnsmessage.AResource{ + A: [4]byte{10, 20, 30, 40}, + }, + }}, + Questions: []dnsmessage.Question{ + { + Name: dnsmessage.MustNewName("foo.bar.ts.net."), + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET, + }, + }, + Additionals: []dnsmessage.Resource{}, + Authorities: []dnsmessage.Resource{}, + } + testQuery := dnsmessage.Message{ + Header: dnsmessage.Header{Authoritative: true}, + Questions: []dnsmessage.Question{ + { + Name: dnsmessage.MustNewName("foo.bar.ts.net."), + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET, + }, + }, + } + testAddr, err := netip.ParseAddrPort("10.40.30.20:0") + assert.NoError(t, err, "error parsing IP address") + packedTestQuery, err := testQuery.Pack() + assert.NoError(t, err, "error parsing DNS query") + answer, err := ns.query(ctx, packedTestQuery, testAddr) + assert.NoError(t, err, "error querying nameserver") + var gotResponse dnsmessage.Message + assert.NoError(t, gotResponse.Unpack(answer), "error unpacking DNS answer") + assert.Equal(t, gotResponse, wantedResponse) + + // Test that nameserver's hosts config gets dynamically updated + + newHostConfig := "{\"baz.bar.ts.net.\": \"10.40.30.20\"}" + var newMockConfigReader configReaderFunc = func() ([]byte, error) { + return []byte(newHostConfig), nil + } + ns.configReader = newMockConfigReader + + timeout := 3 * time.Second + timer := time.NewTimer(timeout) + select { + case <-timer.C: + t.Fatalf("nameserver failed to process config update within %v", timeout) + case configWatcher <- "config update": + } + wantedResponse = dnsmessage.Message{ + Header: dnsmessage.Header{ + ID: 0x0, + Response: true, + OpCode: 0, + Authoritative: true, + Truncated: false, + RecursionDesired: false, + RecursionAvailable: false, + AuthenticData: false, + CheckingDisabled: false, + RCode: dnsmessage.RCodeSuccess, + }, + + Answers: []dnsmessage.Resource{{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName("baz.bar.ts.net."), + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET, + TTL: 0x258, + Length: 0x4, + }, + Body: &dnsmessage.AResource{ + A: [4]byte{10, 40, 30, 20}, + }, + }}, + Questions: []dnsmessage.Question{ + { + Name: dnsmessage.MustNewName("baz.bar.ts.net."), + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET, + }, + }, + Additionals: []dnsmessage.Resource{}, + Authorities: []dnsmessage.Resource{}, + } + testQuery = dnsmessage.Message{ + Header: dnsmessage.Header{Authoritative: true}, + Questions: []dnsmessage.Question{ + { + Name: dnsmessage.MustNewName("baz.bar.ts.net."), + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET, + }, + }, + } + packedTestQuery, err = testQuery.Pack() + assert.NoError(t, err, "error parsing DNS query") + + // retry a couple times as the nameserver will have eventually processed + // the update + assert.Eventually(t, func() bool { + answer, err = ns.query(ctx, packedTestQuery, testAddr) + assert.NoError(t, err, "error querying nameserver") + gotResponse = dnsmessage.Message{} + + assert.NoError(t, gotResponse.Unpack(answer), "error unpacking DNS answer") + if reflect.DeepEqual(wantedResponse, gotResponse) { + return true + } + return false + }, time.Second*5, time.Second) +} diff --git a/cmd/k8s-operator/dnsreconciler.go b/cmd/k8s-operator/dnsreconciler.go new file mode 100644 index 000000000..dd8586233 --- /dev/null +++ b/cmd/k8s-operator/dnsreconciler.go @@ -0,0 +1,269 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// tailscale-operator provides a way to expose services running in a Kubernetes +// cluster to your Tailnet and expose Tailnet services to your cluster workloads. +package main + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/coredns/caddy/caddyfile" + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +const ( + defaultClusterDNSNamespace = "kube-system" + + kubeDNSStubDomainsKey = "stubDomains" + + coreDNSCorefileKey = "Corefile" + tsNetKey = "ts.net" +) + +var ( + // If you add a new one here also update the operator's RBAC + // TODO (irbekrm): make it possible for users to configure configmap + // names/namespaces via an operator flag + knownKubeDNSConfigMapNames = []string{"kube-dns"} + // CoreDNS Helm chart generates this name depending on what name users + // have given to CoreDNS release. By default this will be + // 'coredns-coredns' + // https://github.com/coredns/helm/blob/562d3c8809db9edbad89ae2006a4bd81c34b7b8f/charts/coredns/templates/configmap.yaml#L6 + knownCoreDNSConfigMapNames = []string{"coredns", "coredns-coredns"} +) + +// dnsReconciler knows how to update common cluster DNS setups to add a stub ts.net +// nameserver +type dnsReconciler struct { + client.Client + operatorNamespace string + logger *zap.SugaredLogger +} + +func (r *dnsReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) { + res = reconcile.Result{} + key := req.NamespacedName + logger := r.logger.With("service", req.Name, req.Namespace) + logger.Info("starting reconcile") + defer logger.Info("finished reconcile") + + svc := &corev1.Service{} + // get the ts.net nameserver service, check if it has cluster IP set + err = r.Get(ctx, key, svc) + if apierrors.IsNotFound(err) { + logger.Info("nameserver Service not found, waiting...") + return res, nil + } + if err != nil { + logger.Errorf("error retrieving nameserver Service: %v", err) + return res, err + } + if svc.Spec.ClusterIP == "" || svc.Spec.ClusterIP == "None" { + logger.Info("namserver Service not yet ready, waiting...") + return res, nil + } + + tsNetNS := svc.Spec.ClusterIP + + // We don't have a reliable way how to determine what DNS the cluster is + // actually using so we just try to find and modify kube-dns/CoreDNS + // configs + kubeDNSCM := &corev1.ConfigMap{} + kubeDNSFound := false + for _, cmName := range knownKubeDNSConfigMapNames { + nsName := types.NamespacedName{Name: cmName, Namespace: defaultClusterDNSNamespace} + err := r.Get(ctx, nsName, kubeDNSCM) + if apierrors.IsNotFound(err) { + logger.Debugf("looking for kube-dns config, configmap %s/%s not found", defaultClusterDNSNamespace, cmName) + continue + } + if err != nil { + logger.Errorf("error trying to retrieve kube-dns config: %v", err) + return res, err + } + logger.Infof("kube-dns config found in configmap %s/%s", defaultClusterDNSNamespace, cmName) + kubeDNSFound = true + // presumably there will only ever be one + break + } + // it is possible that both kube-dns and CoreDNS are deployed and we + // don't have a reliable way to tell which one is used, so update both + coreDNSCM := &corev1.ConfigMap{} + coreDNSFound := false + for _, cmName := range knownCoreDNSConfigMapNames { + nsName := types.NamespacedName{Name: cmName, Namespace: defaultClusterDNSNamespace} + err := r.Get(ctx, nsName, coreDNSCM) + if apierrors.IsNotFound(err) { + logger.Debugf("looking for coreDNS config, configmap %s/%s not found", defaultClusterDNSNamespace, cmName) + continue + } + if err != nil { + logger.Errorf("error trying to retrieve CoreDNS config: %v", err) + return res, err + } + logger.Infof("CoreDNS config found in configmap %s/%s", defaultClusterDNSNamespace, cmName) + coreDNSFound = true + // presumably there will only ever be one + break + } + + if !kubeDNSFound && !coreDNSFound { + logger.Info("neither kube-dns nor CoreDNS config was found. Users who want to use Tailscale egress will need to configure ts.net DNS manually") + return res, nil + } + + if kubeDNSFound { + logger.Infof("ensuring that kube-dns config in ConfigMap %s/%s contains ts.net stub nameserver", defaultClusterDNSNamespace, kubeDNSCM.Name) + + stubDomains := make(map[string][]string) + if kubeDNSCM.Data == nil { + kubeDNSCM.Data = make(map[string]string) + } + if _, ok := kubeDNSCM.Data[kubeDNSStubDomainsKey]; ok { + err = json.Unmarshal([]byte(kubeDNSCM.Data[kubeDNSStubDomainsKey]), &stubDomains) + if err != nil { + logger.Errorf("error unmarshalling kube-dns config: %v", err) + return res, err + } + } + if _, ok := stubDomains[tsNetKey]; !ok { + stubDomains[tsNetKey] = make([]string, 1) + } + if stubDomains[tsNetKey][0] != tsNetNS { + stubDomains[tsNetKey][0] = tsNetNS + stubDomainsBytes, err := json.Marshal(stubDomains) + if err != nil { + logger.Errorf("error marshaling stub domains: %v", err) + return res, err + } + (*kubeDNSCM).Data[kubeDNSStubDomainsKey] = string(stubDomainsBytes) + if err := r.Update(ctx, kubeDNSCM); err != nil { + logger.Errorf("error updating kube-dns config: %v", err) + return res, err + } + logger.Infof("kube-dns config in ConfigMap %s/%s updated with ts.net stubserver at %s", defaultClusterDNSNamespace, kubeDNSCM.Name, svc.Spec.ClusterIP) + } else { + logger.Debugf("kube-dns config in ConfigMap %s/%s already up to date with ts.net stubserver at %s", defaultClusterDNSNamespace, kubeDNSCM.Name, svc.Spec.ClusterIP) + } + } + + if coreDNSFound { + // coreDNS does not appear to have defaults where it doesn't need Corefile to + // contain some configuration, so if this is unset something is off and we don't + // know what to do + if _, ok := coreDNSCM.Data[coreDNSCorefileKey]; !ok { + logger.Infof("found what appears to be a core-dns config in ConfigMap %s/%s, but it does not contain a Corefile, do nothing", defaultClusterDNSNamespace, coreDNSCM.Name) + return res, nil + } + corefileBytes := []byte(coreDNSCM.Data[coreDNSCorefileKey]) + // do things to unmarshal Corefile and update it if needed + b, err := caddyfile.ToJSON(corefileBytes) + if err != nil { + logger.Errorf("error converting Caddyfile to JSON: %v", err) + return res, err + } + + cf := &caddyfile.EncodedCaddyfile{} + err = json.Unmarshal(b, cf) + if err != nil { + logger.Errorf("error unmarshalling Caddyfile: %v", err) + return res, err + } + + foundTSNetDirective := false + needsUpdate := false + for i, serverBlock := range *cf { + // We are looking for a server block that has a single key 'ts.net' + if (len(serverBlock.Keys) != 1) || serverBlock.Keys[0] != tsNetKey { + continue + } + foundTSNetDirective = true + + // check if forward directive needs updating + currentNs, err := nsFromForwardDirective(serverBlock.Body) + if err != nil { + logger.Errorf("error retrieving current ts.net namserver from Corefile forward directive: %v", err) + return res, err + } + if tsNetNS != currentNs { + newForwardDirective := forwardDirectiveForNS(tsNetNS) + serverBlock.Body = newForwardDirective + (*cf)[i] = serverBlock + needsUpdate = true + logger.Infof("updated forward directive in ts.net serverblock for Corefile: %+#v", newForwardDirective) + } + break + } + if !foundTSNetDirective { + tsNetServerBlock := serverBlockForNS(tsNetNS) + (*cf) = append((*cf), tsNetServerBlock) + needsUpdate = true + logger.Infof("adding a new ts.net server block to Corefile: %+#v", tsNetServerBlock) + } + + if needsUpdate { + cfBytes, err := json.Marshal(cf) + if err != nil { + logger.Errorf("error marshalling updated CoreDNS config: %v", err) + return res, err + } + // updated Caddyfile + updatedCF, err := caddyfile.FromJSON(cfBytes) + if err != nil { + logger.Errorf("error converting updated CoreDNS config to Corefile: %v", err) + return res, err + } + // TODO (irbekrm): can we somehow validate that this is a valid Corefile? + coreDNSCM.Data[coreDNSCorefileKey] = string(updatedCF) + + // TODO (irbekrm): should probably SSA here + err = r.Update(ctx, coreDNSCM) + if err != nil { + logger.Errorf("error updating CoreDNS configmap: %v", err) + return res, err + } + } + + } + + return res, nil +} + +func forwardDirectiveForNS(ip string) [][]interface{} { + return [][]interface{}{{"forward", ".", ip}} +} + +func serverBlockForNS(ip string) caddyfile.EncodedServerBlock { + directive := forwardDirectiveForNS(ip) + return caddyfile.EncodedServerBlock{ + Keys: []string{tsNetKey}, + Body: directive, + } +} + +func nsFromForwardDirective(directive [][]interface{}) (ip string, _ error) { + // this is a directive created by forwardDirectiveForNS func and + // shouldn't have been modified by anyone + if len(directive) != 1 { + return "", fmt.Errorf("unexpected length of ts.net forward directive, expected 1 got %d", len(directive)) + } + + statement := directive[0] + + if len(statement) != 3 { + return "", fmt.Errorf("unexpected ts.net forward statement %v, expected 3 elements, got %d", statement, len(statement)) + } + ip, ok := statement[2].(string) + if !ok { + return "", fmt.Errorf("cannot convert %v to string", statement[2]) + } + return ip, nil +} diff --git a/cmd/k8s-operator/hostscm.go b/cmd/k8s-operator/hostscm.go new file mode 100644 index 000000000..8345e14d4 --- /dev/null +++ b/cmd/k8s-operator/hostscm.go @@ -0,0 +1,116 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !plan9 + +// tailscale-operator provides a way to expose services running in a Kubernetes +// cluster to your Tailnet. +package main + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "tailscale.com/client/tailscale/apitype" +) + +const dnsConfigKey = "dns.json" + +// hostsCMConfig contains the config needed to update ts.net config for a +// particular egress proxy +type hostsCMConfig struct { + // IP of the Tailscale service that we are setting up egress for + targetIP string + // serviceLabels identify the proxy service + serviceLabels map[string]string +} + +// hostsCMProvisioner knows how to update ts.net nameserver config as egress +// proxy Services get added/deleted +type hostsCMProvisioner struct { + // Client reads from cache first, then kube-apiserver, writes to + // kube-apiserver + client.Client + // namespace in which tailscale resources get provisioned + tsNamespace string + // localClient knows how to talk to tailscaled local API + localAPIClient localClient +} + +type localClient interface { + WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, error) +} + +// Provision ensures that ts.net nameserver config has been updated with a +// mapping of Tailscale service to its egress proxy kube Service IP. If +// successful, returns the Tailscale service FQDN +func (h *hostsCMProvisioner) Provision(ctx context.Context, logger *zap.SugaredLogger, hcc *hostsCMConfig) (string, error) { + ip := fmt.Sprintf("%s:0", hcc.targetIP) + whois, err := h.localAPIClient.WhoIs(ctx, ip) + if err != nil { + logger.Errorf("error determining tailscale service: %v", err) + return "", err + } + fqdn := whois.Node.Name + fqdn = strings.TrimSuffix(fqdn, ".") + + logger.Debugf("ensuring a ts.net record for %s: %s", ip, fqdn) + + proxySvc, err := getSingleObject[corev1.Service](ctx, h.Client, h.tsNamespace, hcc.serviceLabels) + if apierrors.IsNotFound(err) { + // we will reconcile again on proxy Service creation/update + // event and the hosts config will get updated then + logger.Debugf("proxy Service not yet created waiting...") + return "", nil + } + if err != nil { + logger.Errorf("error retrieving proxy Service: %v", err) + return "", err + } + + if proxySvc == nil || proxySvc.Spec.ClusterIP == "" || proxySvc.Spec.ClusterIP == "None" { + // we will reconcile again on proxy Service creation/update + // event and the hosts config will get updated then + logger.Infof("proxy Service for %s not yet ready, waiting...", fqdn) + return "", nil + } + + cm := &corev1.ConfigMap{} + err = h.Get(ctx, types.NamespacedName{Name: dnsConfigMapName, Namespace: h.tsNamespace}, cm) + if err != nil { + logger.Errorf("error retrieving hosts config: %v", err) + return "", err + } + + hosts := make(map[string]string) + if cm.Data[dnsConfigKey] != "" { + if err := json.Unmarshal([]byte(cm.Data[dnsConfigKey]), &hosts); err != nil { + logger.Errorf("error unmarshaling hosts config %v", err) + return "", err + } + } + hosts[fqdn] = proxySvc.Spec.ClusterIP + hostsBytes, err := json.Marshal(hosts) + if err != nil { + logger.Errorf("error marshaling hosts config %v", err) + return "", err + } + + cm.Data[dnsConfigKey] = string(hostsBytes) + + // TODO (irbekrm): probably better to SSA here + // TODO (irbekrm): check diff only apply update if needed + if err := h.Update(ctx, cm); err != nil { + logger.Errorf("failed to update ts.net DNS config: %v", err) + return "", err + } + + return fqdn, nil +} diff --git a/cmd/k8s-operator/manifests/nameserver.yaml b/cmd/k8s-operator/manifests/nameserver.yaml index 3cdf8691c..2e293a918 100644 --- a/cmd/k8s-operator/manifests/nameserver.yaml +++ b/cmd/k8s-operator/manifests/nameserver.yaml @@ -31,7 +31,7 @@ spec: ports: - name: udp protocol: UDP - containerPort: 53 + containerPort: 1053 volumeMounts: - name: dnsconfig mountPath: /config @@ -55,7 +55,7 @@ spec: app: nameserver ports: - name: udp - targetPort: 53 + targetPort: 1053 port: 53 protocol: UDP --- diff --git a/cmd/k8s-operator/manifests/operator.yaml b/cmd/k8s-operator/manifests/operator.yaml index 4da7a4dae..c3a86415f 100644 --- a/cmd/k8s-operator/manifests/operator.yaml +++ b/cmd/k8s-operator/manifests/operator.yaml @@ -79,6 +79,56 @@ rules: - apiGroups: ["apps"] resources: ["statefulsets"] verbs: ["*"] +- apiGroups: + - "" + resourceNames: + - dnsconfig + resources: + - configmaps + verbs: + - get + - watch + - list + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: tailscaledns + namespace: kube-system +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - list + - watch + - get +- apiGroups: + - "" + resources: + - configmaps + verbs: + - update + resourceNames: + - kube-dns + - coredns + - coredns-coredns +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: tailscaledns + namespace: kube-system +subjects: +- kind: ServiceAccount + name: operator + namespace: tailscale +roleRef: + kind: Role + name: tailscaledns + apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index 139101cc8..f0af61504 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -9,6 +9,7 @@ package main import ( "context" + "flag" "os" "strings" "time" @@ -20,6 +21,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/builder" @@ -41,11 +43,30 @@ import ( "tailscale.com/version" ) +const ( + dnsConfigMapName = "dnsconfig" + + tsNetNSService = "nameserver" +) + +type reconcilersConfig struct { + enableDNS bool + logger *zap.SugaredLogger + tsNamespace string + restConfig *rest.Config + tsClient *tailscale.Client + localAPIClient *tailscale.LocalClient + proxyImage string + proxyPriorityClassName string + tags string +} + func main() { // Required to use our client API. We're fine with the instability since the // client lives in the same repo as this code. tailscale.I_Acknowledge_This_API_Is_Unstable = true + // TODO (irbekrm): make these into flags var ( tsNamespace = defaultEnv("OPERATOR_NAMESPACE", "") tslogging = defaultEnv("OPERATOR_LOGGING", "info") @@ -53,8 +74,12 @@ func main() { priorityClassName = defaultEnv("PROXY_PRIORITY_CLASS_NAME", "") tags = defaultEnv("PROXY_TAGS", "tag:k8s") shouldRunAuthProxy = defaultBool("AUTH_PROXY", false) + tsEnableDNS bool ) + flag.BoolVar(&tsEnableDNS, "enable-dns", false, "If set to true, egress proxying to Tailscale services will be configured in such a way that cluster workloads will be able to use Tailscale services' MagicDNS names. (Additional manual configuration may be required and ts.net nameserver must be deployed.)") + flag.Parse() + var opts []kzap.Opts switch tslogging { case "info": @@ -67,19 +92,33 @@ func main() { zlog := kzap.NewRaw(opts...).Sugar() logf.SetLogger(zapr.NewLogger(zlog.Desugar())) - s, tsClient := initTSNet(zlog) + zlog.Infof("enable DNS: %v", tsEnableDNS) + os.Exit(1) + + s, tsClient, localAPIClient := initTSNet(zlog) defer s.Close() restConfig := config.GetConfigOrDie() if shouldRunAuthProxy { launchAuthProxy(zlog, restConfig, s) } - startReconcilers(zlog, tsNamespace, restConfig, tsClient, image, priorityClassName, tags) + rc := &reconcilersConfig{ + enableDNS: tsEnableDNS, + logger: zlog, + tsNamespace: tsNamespace, + restConfig: restConfig, + proxyImage: image, + proxyPriorityClassName: priorityClassName, + tags: tags, + tsClient: tsClient, + localAPIClient: localAPIClient, + } + startReconcilers(rc) } // initTSNet initializes the tsnet.Server and logs in to Tailscale. It uses the // CLIENT_ID_FILE and CLIENT_SECRET_FILE environment variables to authenticate // with Tailscale. -func initTSNet(zlog *zap.SugaredLogger) (*tsnet.Server, *tailscale.Client) { +func initTSNet(zlog *zap.SugaredLogger) (*tsnet.Server, *tailscale.Client, *tailscale.LocalClient) { hostinfo.SetApp("k8s-operator") var ( clientIDPath = defaultEnv("CLIENT_ID_FILE", "") @@ -177,16 +216,16 @@ waitOnline: } time.Sleep(time.Second) } - return s, tsClient + return s, tsClient, lc } // startReconcilers starts the controller-runtime manager and registers the // ServiceReconciler. -func startReconcilers(zlog *zap.SugaredLogger, tsNamespace string, restConfig *rest.Config, tsClient *tailscale.Client, image, priorityClassName, tags string) { +func startReconcilers(config *reconcilersConfig) { var ( isDefaultLoadBalancer = defaultBool("OPERATOR_DEFAULT_LOAD_BALANCER", false) ) - startlog := zlog.Named("startReconcilers") + startlog := config.logger.Named("startReconcilers") // For secrets and statefulsets, we only get permission to touch the objects // in the controller's own namespace. This cannot be expressed by // .Watches(...) below, instead you have to add a per-type field selector to @@ -194,16 +233,39 @@ func startReconcilers(zlog *zap.SugaredLogger, tsNamespace string, restConfig *r // implicitly filter what parts of the world the builder code gets to see at // all. nsFilter := cache.ByObject{ - Field: client.InNamespace(tsNamespace).AsSelector(), + Field: client.InNamespace(config.tsNamespace).AsSelector(), } - mgr, err := manager.New(restConfig, manager.Options{ - Cache: cache.Options{ - ByObject: map[client.Object]cache.ByObject{ - &corev1.Secret{}: nsFilter, - &appsv1.StatefulSet{}: nsFilter, - }, + + cacheOpts := cache.Options{ + ByObject: map[client.Object]cache.ByObject{ + &corev1.Secret{}: nsFilter, + &appsv1.StatefulSet{}: nsFilter, }, + } + // we only need to watch ConfigMaps if ts.net DNS is enabled + if config.enableDNS { + startlog.Info("DNS enabled, will be watching configmaps") + tsNSCMName := cache.ByObject{ + Field: fields.SelectorFromSet(fields.Set{"metadata.name": dnsConfigMapName}), + } + + // build cache filter for ConfigMaps. We only want to watch the one that + // holds ts.net nameserver config + the ones that might hold cluster DNS + // config + cmFilter := cache.ByObject{ + Namespaces: map[string]cache.Config{ + config.tsNamespace: { + FieldSelector: tsNSCMName.Field, + }, + defaultClusterDNSNamespace: {}, // it doesn't seem like we can OR a field selector so cache all configmaps in this namespace + }, + } + cacheOpts.ByObject[&corev1.ConfigMap{}] = cmFilter + } + mgr, err := manager.New(config.restConfig, manager.Options{ + Cache: cacheOpts, }) + if err != nil { startlog.Fatalf("could not create manager: %v", err) } @@ -222,28 +284,50 @@ func startReconcilers(zlog *zap.SugaredLogger, tsNamespace string, restConfig *r }, } }) + eventRecorder := mgr.GetEventRecorderFor("tailscale-operator") ssr := &tailscaleSTSReconciler{ Client: mgr.GetClient(), - tsClient: tsClient, - defaultTags: strings.Split(tags, ","), - operatorNamespace: tsNamespace, - proxyImage: image, - proxyPriorityClassName: priorityClassName, + tsClient: config.tsClient, + defaultTags: strings.Split(config.tags, ","), + operatorNamespace: config.tsNamespace, + proxyImage: config.proxyImage, + proxyPriorityClassName: config.proxyPriorityClassName, + UseDNS: config.enableDNS, } - err = builder. + + hp := &hostsCMProvisioner{ + Client: mgr.GetClient(), + tsNamespace: config.tsNamespace, + localAPIClient: config.localAPIClient, + } + b := builder. ControllerManagedBy(mgr). For(&corev1.Service{}). Watches(&appsv1.StatefulSet{}, reconcileFilter). - Watches(&corev1.Secret{}, reconcileFilter). - Complete(&ServiceReconciler{ - ssr: ssr, - Client: mgr.GetClient(), - logger: zlog.Named("service-reconciler"), - isDefaultLoadBalancer: isDefaultLoadBalancer, + Watches(&corev1.Secret{}, reconcileFilter) + + if config.enableDNS { + cmEventHandler := handler.EnqueueRequestsFromMapFunc(func(_ context.Context, o client.Object) []reconcile.Request { + // currently we cache the hosts configmap, but do not trigger + // reconciles if it has changed so any manual modifications to + // it will not always be immediately overriden. Probably + // eventually we want to do that- but make sure our reconciles + // are not too expensive first + return nil }) + b = b.Watches(&corev1.ConfigMap{}, cmEventHandler) + } + err = b.Complete(&ServiceReconciler{ + ssr: ssr, + Client: mgr.GetClient(), + logger: config.logger.Named("service-reconciler"), + isDefaultLoadBalancer: isDefaultLoadBalancer, + hostsProvisioner: hp, + useDNS: config.enableDNS, + }) if err != nil { - startlog.Fatalf("could not create controller: %v", err) + startlog.Fatalf("could not create service reconciler: %v", err) } err = builder. ControllerManagedBy(mgr). @@ -254,10 +338,67 @@ func startReconcilers(zlog *zap.SugaredLogger, tsNamespace string, restConfig *r ssr: ssr, recorder: eventRecorder, Client: mgr.GetClient(), - logger: zlog.Named("ingress-reconciler"), + logger: config.logger.Named("ingress-reconciler"), }) if err != nil { - startlog.Fatalf("could not create controller: %v", err) + startlog.Fatalf("could not create ingress reconciler: %v", err) + } + + if config.enableDNS { + startlog.Info("enabling ts.net DNS name resolution") + dnsR := &dnsReconciler{ + Client: mgr.GetClient(), + logger: config.logger.Named("dns-reconciler"), + operatorNamespace: config.tsNamespace, + } + + // the only Service that dnsReconciler is interested in is that of the + // ts.net nameserver + dnsReconcilerSvcFilter := handler.EnqueueRequestsFromMapFunc(func(_ context.Context, o client.Object) []reconcile.Request { + if o.GetName() != tsNetNSService || o.GetNamespace() != config.tsNamespace { + return nil + } + return []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Namespace: config.tsNamespace, + Name: tsNetNSService, + }, + }, + } + }) + + // the only configmaps that the dnsReconciler is interested in are those + // that hold kube-dns/CoreDNS configuration + dnsReconcilerCMFilter := handler.EnqueueRequestsFromMapFunc(func(_ context.Context, o client.Object) []reconcile.Request { + if o.GetNamespace() != defaultClusterDNSNamespace { + return nil + } + + for _, name := range append(knownKubeDNSConfigMapNames, knownCoreDNSConfigMapNames...) { + if name == o.GetName() { + return []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Namespace: config.tsNamespace, + Name: tsNetNSService, + }, + }, + } + } + } + return nil + }) + + err = builder. + ControllerManagedBy(mgr). + Named("dnsreconciler"). + Watches(&corev1.Service{}, dnsReconcilerSvcFilter). + Watches(&corev1.ConfigMap{}, dnsReconcilerCMFilter). + Complete(dnsR) + if err != nil { + startlog.Fatalf("could not create dns reconciler: %v", err) + } } startlog.Infof("Startup complete, operator running, version: %s", version.Long()) diff --git a/cmd/k8s-operator/sts.go b/cmd/k8s-operator/sts.go index a706835a2..47cd47cf9 100644 --- a/cmd/k8s-operator/sts.go +++ b/cmd/k8s-operator/sts.go @@ -76,13 +76,16 @@ type tailscaleSTSReconciler struct { operatorNamespace string proxyImage string proxyPriorityClassName string + // whether ts.net DNS resolution has been enabled for this operator + // instance + UseDNS bool } // Provision ensures that the StatefulSet for the given service is running and // up to date. func (a *tailscaleSTSReconciler) Provision(ctx context.Context, logger *zap.SugaredLogger, sts *tailscaleSTSConfig) (*corev1.Service, error) { // Do full reconcile. - hsvc, err := a.reconcileHeadlessService(ctx, logger, sts) + hsvc, err := a.reconcileProxyService(ctx, logger, sts) if err != nil { return nil, fmt.Errorf("failed to reconcile headless service: %w", err) } @@ -152,22 +155,38 @@ func (a *tailscaleSTSReconciler) Cleanup(ctx context.Context, logger *zap.Sugare return true, nil } -func (a *tailscaleSTSReconciler) reconcileHeadlessService(ctx context.Context, logger *zap.SugaredLogger, sts *tailscaleSTSConfig) (*corev1.Service, error) { - hsvc := &corev1.Service{ +func (a *tailscaleSTSReconciler) reconcileProxyService(ctx context.Context, logger *zap.SugaredLogger, sts *tailscaleSTSConfig) (*corev1.Service, error) { + proxysvc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "ts-" + sts.ParentResourceName + "-", Namespace: a.operatorNamespace, Labels: sts.ChildResourceLabels, }, Spec: corev1.ServiceSpec{ - ClusterIP: "None", Selector: map[string]string{ "app": sts.ParentResourceUID, }, }, } + // for ingress we create a headless Service + if sts.ClusterTargetIP != "" || (sts.TailnetTargetIP != "" && !a.UseDNS) { + proxysvc.Spec.ClusterIP = corev1.ClusterIPNone + } else if sts.TailnetTargetIP != "" { + proxysvc.Spec.Ports = []corev1.ServicePort{ + { + Name: "https", + Protocol: "TCP", + Port: 443, + }, + { + Name: "http", + Protocol: "TCP", + Port: 80, + }, + } + } logger.Debugf("reconciling headless service for StatefulSet") - return createOrUpdate(ctx, a.Client, a.operatorNamespace, hsvc, func(svc *corev1.Service) { svc.Spec = hsvc.Spec }) + return createOrUpdate(ctx, a.Client, a.operatorNamespace, proxysvc, func(svc *corev1.Service) { svc.Spec = proxysvc.Spec }) } func (a *tailscaleSTSReconciler) createOrGetSecret(ctx context.Context, logger *zap.SugaredLogger, stsC *tailscaleSTSConfig, hsvc *corev1.Service) (string, error) { diff --git a/cmd/k8s-operator/svc.go b/cmd/k8s-operator/svc.go index 3bab3532a..2bd44f7a6 100644 --- a/cmd/k8s-operator/svc.go +++ b/cmd/k8s-operator/svc.go @@ -24,6 +24,9 @@ type ServiceReconciler struct { ssr *tailscaleSTSReconciler logger *zap.SugaredLogger isDefaultLoadBalancer bool + hostsProvisioner *hostsCMProvisioner + // whether egress Services should be referred to by ts.net DNS names + useDNS bool } func childResourceLabels(name, ns, typ string) map[string]string { @@ -132,17 +135,37 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga TailnetTargetIP: svc.Annotations[AnnotationTailnetTargetIP], } - var hsvc *corev1.Service - if hsvc, err = a.ssr.Provision(ctx, logger, sts); err != nil { + var proxySvc *corev1.Service + if proxySvc, err = a.ssr.Provision(ctx, logger, sts); err != nil { return fmt.Errorf("failed to provision: %w", err) } + // Only used for egress proxy. If operator has been configured to use + // DNS this will be the MagicDNS name of the egress service. If the + // operator has not been configured to use DNS, this will be the + // Kubernetes DNS name of the proxy Service. + inClusterFQDN := fmt.Sprintf("%s.%s.svc", proxySvc.Name, proxySvc.Namespace) + + // ensure that ts.net nameserver has a record for the new egress service + if a.hasTailnetTargetAnnotation(svc) && a.useDNS { + // update hosts + hostsConfig := &hostsCMConfig{ + targetIP: svc.Annotations[AnnotationTailnetTargetIP], + serviceLabels: crl, + } + fqdn, err := a.hostsProvisioner.Provision(ctx, logger, hostsConfig) + if err != nil { + return fmt.Errorf("error provisioning ts.net config: %v", err) + } + inClusterFQDN = fqdn + } + if a.hasTailnetTargetAnnotation(svc) { - headlessSvcName := hsvc.Name + "." + hsvc.Namespace + ".svc" - if svc.Spec.ExternalName != headlessSvcName || svc.Spec.Type != corev1.ServiceTypeExternalName { - svc.Spec.ExternalName = headlessSvcName + if svc.Spec.ExternalName != inClusterFQDN || svc.Spec.Type != corev1.ServiceTypeExternalName { + svc.Spec.ExternalName = inClusterFQDN svc.Spec.Selector = nil svc.Spec.Type = corev1.ServiceTypeExternalName + logger.Infof("updating service to %+#v", svc) if err := a.Update(ctx, svc); err != nil { return fmt.Errorf("failed to update service: %w", err) } diff --git a/go.mod b/go.mod index d0e175b46..ef21c351a 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64 github.com/aws/aws-sdk-go-v2/service/s3 v1.33.0 github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 + github.com/coredns/caddy v1.1.1 github.com/coreos/go-iptables v0.6.0 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/creack/pty v1.1.18 @@ -53,8 +54,8 @@ require ( github.com/peterbourgon/ff/v3 v3.3.0 github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.5 - github.com/prometheus/client_golang v1.15.1 - github.com/prometheus/common v0.42.0 + github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/common v0.44.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502 @@ -71,19 +72,19 @@ require ( github.com/u-root/u-root v0.11.0 github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 - go.uber.org/zap v1.24.0 + go.uber.org/zap v1.25.0 go4.org/mem v0.0.0-20220726221520-4f986261bf13 go4.org/netipx v0.0.0-20230728180743-ad4cb58a6516 golang.org/x/crypto v0.12.0 golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 golang.org/x/mod v0.11.0 golang.org/x/net v0.14.0 - golang.org/x/oauth2 v0.7.0 + golang.org/x/oauth2 v0.8.0 golang.org/x/sync v0.2.0 golang.org/x/sys v0.11.0 golang.org/x/term v0.11.0 golang.org/x/time v0.3.0 - golang.org/x/tools v0.9.1 + golang.org/x/tools v0.9.3 golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 golang.zx2c4.com/wireguard/windows v0.5.3 gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f @@ -91,16 +92,19 @@ require ( 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.27.2 - k8s.io/apimachinery v0.27.2 - k8s.io/client-go v0.27.2 + k8s.io/api v0.28.0 + k8s.io/apimachinery v0.28.0 + k8s.io/client-go v0.28.0 nhooyr.io/websocket v1.8.7 - sigs.k8s.io/controller-runtime v0.15.0 + sigs.k8s.io/controller-runtime v0.16.0 sigs.k8s.io/yaml v1.3.0 software.sslmate.com/src/go-pkcs12 v0.2.0 ) -require github.com/gorilla/securecookie v1.1.1 // indirect +require ( + github.com/google/gnostic-models v0.6.8 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect +) require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect @@ -203,7 +207,6 @@ require ( github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/gnostic v0.6.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 // indirect github.com/google/rpmpack v0.5.0 // indirect @@ -281,7 +284,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polyfloyd/go-errorlint v1.4.1 // indirect github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/quasilyte/go-ruleguard v0.3.19 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect @@ -334,12 +337,11 @@ require ( 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 golang.org/x/image v0.7.0 // indirect golang.org/x/text v0.12.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -348,10 +350,10 @@ 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.27.2 // indirect - k8s.io/component-base v0.27.2 // indirect + k8s.io/apiextensions-apiserver v0.28.0 // indirect + k8s.io/component-base v0.28.0 // indirect k8s.io/klog/v2 v2.100.1 // indirect - k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect + k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect mvdan.cc/gofumpt v0.5.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect diff --git a/go.sum b/go.sum index f9e62235f..cfa85e4a0 100644 --- a/go.sum +++ b/go.sum @@ -76,7 +76,8 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa 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= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= github.com/ProtonMail/go-crypto v0.0.0-20230626094100-7e9e0395ebec h1:vV3RryLxt42+ZIVOFbYJCH1jsZNTNmj2NYru5zfx+4E= @@ -104,10 +105,13 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/ashanbrown/forbidigo v1.5.1 h1:WXhzLjOlnuDYPYQo/eFlcFMi8X/kLfvWLYu6CSoebis= github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= @@ -152,8 +156,9 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.18.10 h1:6UbNM/KJhMBfOI5+lpVcJ/8OA7c github.com/aws/aws-sdk-go-v2/service/sts v1.18.10/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -162,6 +167,8 @@ github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7 github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= @@ -170,7 +177,6 @@ github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/butuzov/ireturn v0.2.0 h1:kCHi+YzC150GE98WFuZQu9yrTn6GEydO2AuPLbTgnO4= github.com/butuzov/ireturn v0.2.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= @@ -180,8 +186,10 @@ github.com/caarlos0/testfs v0.4.4 h1:3PHvzHi5Lt+g332CiShwS8ogTgS3HjrmzZxCm6JCDr8 github.com/caarlos0/testfs v0.4.4/go.mod h1:bRN55zgG4XCUVVHZCeU+/Tz1Q6AxEJOEJTliBy+1DMk= github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM= github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -201,13 +209,18 @@ github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0= +github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -234,7 +247,6 @@ github.com/docker/docker v23.0.5+incompatible h1:DaxtlTJjFSnLOXVNUBU1+6kXGz2lpDo github.com/docker/docker v23.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dsnet/try v0.0.3 h1:ptR59SsrcFUYbT/FhAbKTV6iLkeD6O18qfIWRml2fqI= github.com/dsnet/try v0.0.3/go.mod h1:WBM8tRpUmnXXhY1U6/S8dt6UWdHTQ7y8A5YSkRCkq40= github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= @@ -248,7 +260,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= @@ -264,9 +275,11 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -275,7 +288,6 @@ github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= @@ -308,6 +320,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -418,8 +432,10 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +github.com/google/cel-go v0.16.0 h1:DG9YQ8nFCFXAs/FDDwBxmL1tpKNrdlGUM9U3537bX/Y= +github.com/google/cel-go v0.16.0/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -497,7 +513,11 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -591,7 +611,6 @@ github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -694,10 +713,10 @@ github.com/nunnatsa/ginkgolinter v0.11.2 h1:xzQpAsEyZe5F1RMy2Z5kn8UFCGiWfKqJOUd2 github.com/nunnatsa/ginkgolinter v0.11.2/go.mod h1:dJIGXYXbkBswqa/pIzG0QlVTTDSBMxDoCFwhsl4Uras= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= -github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= @@ -736,8 +755,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= -github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= 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= @@ -748,15 +767,15 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 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.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= @@ -768,7 +787,6 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -821,7 +839,6 @@ github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -839,6 +856,7 @@ github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YE github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -932,9 +950,6 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= @@ -952,24 +967,48 @@ 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/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= +go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= +go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= +go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= +go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= +go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= 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.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= +go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= go4.org/mem v0.0.0-20220726221520-4f986261bf13 h1:CbZeCBZ0aZj8EfVgnqQcYZgf0lpZ3H9rmp5nkDTAst8= go4.org/mem v0.0.0-20220726221520-4f986261bf13/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= go4.org/netipx v0.0.0-20230728180743-ad4cb58a6516 h1:X66ZEoMN2SuaoI/dfZVYobB6E5zjZyyHUMWlCA7MgGE= @@ -1078,7 +1117,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -1100,8 +1138,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1204,7 +1242,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -1293,8 +1330,8 @@ golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1303,8 +1340,8 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= -gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc= -gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1355,7 +1392,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -1369,7 +1405,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 h1:9NWlQfY2ePejTmfwUH1OWwmznFa+0kKcHGPDvcPza9M= +google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1383,12 +1424,11 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1401,7 +1441,6 @@ 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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1415,12 +1454,13 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1428,7 +1468,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/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= @@ -1452,20 +1491,24 @@ 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.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= -k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= -k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= -k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= -k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= -k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= -k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= -k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= -k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= -k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= +k8s.io/api v0.28.0 h1:3j3VPWmN9tTDI68NETBWlDiA9qOiGJ7sdKeufehBYsM= +k8s.io/api v0.28.0/go.mod h1:0l8NZJzB0i/etuWnIXcwfIv+xnDOhL3lLW919AWYDuY= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= +k8s.io/apimachinery v0.28.0 h1:ScHS2AG16UlYWk63r46oU3D5y54T53cVI5mMJwwqFNA= +k8s.io/apimachinery v0.28.0/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= +k8s.io/apiserver v0.28.0 h1:wVh7bK6Xj7hq+5ntInysTeQRAOqqFoKGUOW2yj8DXrY= +k8s.io/apiserver v0.28.0/go.mod h1:MvLmtxhQ0Tb1SZk4hfJBjs8iqr5nhYeaFSaoEcz7Lk4= +k8s.io/client-go v0.28.0 h1:ebcPRDZsCjpj62+cMk1eGNX1QkMdRmQ6lmz5BLoFWeM= +k8s.io/client-go v0.28.0/go.mod h1:0Asy9Xt3U98RypWJmU1ZrRAGKhP6NqDPmptlAzK2kMc= +k8s.io/component-base v0.28.0 h1:HQKy1enJrOeJlTlN4a6dU09wtmXaUvThC0irImfqyxI= +k8s.io/component-base v0.28.0/go.mod h1:Yyf3+ZypLfMydVzuLBqJ5V7Kx6WwDr/5cN+dFjw1FNk= 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= -k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/kms v0.28.0 h1:BwJhU9qPcJhHLUcQjtelOSjYti+1/caJLr+4jHbKzTA= +k8s.io/kms v0.28.0/go.mod h1:CNU792ls92v2Ye7Vn1jn+xLqYtUSezDZNVu6PLbJyrU= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= @@ -1481,8 +1524,10 @@ nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= -sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= +sigs.k8s.io/controller-runtime v0.16.0 h1:5koYaaRVBHDr0LZAJjO5dWzUjMsh6cwa7q1Mmusrdvk= +sigs.k8s.io/controller-runtime v0.16.0/go.mod h1:77DnuwA8+J7AO0njzv3wbNlMOnGuLrwFr8JPNwx3J7g= 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=