From fa8b02a83f856a06858b5c1d160a6abbb7df9e17 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 13 Oct 2022 16:00:08 +0200 Subject: [PATCH 01/23] tsic: Tailscale in Container abstraction Signed-off-by: Kristoffer Dalby --- integration/tsic/tsic.go | 217 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 integration/tsic/tsic.go diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go new file mode 100644 index 00000000..40a0e693 --- /dev/null +++ b/integration/tsic/tsic.go @@ -0,0 +1,217 @@ +package tsic + +import ( + "errors" + "fmt" + "log" + "net/netip" + "strings" + + "github.com/juanfont/headscale" + "github.com/juanfont/headscale/integration/dockertestutil" + "github.com/ory/dockertest/v3" + "github.com/ory/dockertest/v3/docker" +) + +const tsicHashLength = 6 +const dockerContextPath = "../." + +var errTailscalePingFailed = errors.New("ping failed") + +type TailscaleInContainer struct { + version string + Hostname string + + pool *dockertest.Pool + container *dockertest.Resource + network *dockertest.Network +} + +func New( + pool *dockertest.Pool, + version string, + network *dockertest.Network) (*TailscaleInContainer, error) { + hash, err := headscale.GenerateRandomStringDNSSafe(tsicHashLength) + if err != nil { + return nil, err + } + + hostname := fmt.Sprintf("ts-%s-%s", version, hash) + + // TODO(kradalby): figure out why we need to "refresh" the network here. + // network, err = dockertestutil.GetFirstOrCreateNetwork(pool, network.Network.Name) + // if err != nil { + // return nil, err + // } + + tailscaleOptions := &dockertest.RunOptions{ + Name: hostname, + Networks: []*dockertest.Network{network}, + Cmd: []string{ + "tailscaled", "--tun=tsdev", + }, + } + + // dockertest isnt very good at handling containers that has already + // been created, this is an attempt to make sure this container isnt + // present. + err = pool.RemoveContainerByName(hostname) + if err != nil { + return nil, err + } + + container, err := pool.BuildAndRunWithBuildOptions( + createTailscaleBuildOptions(version), + tailscaleOptions, + dockertestutil.DockerRestartPolicy, + dockertestutil.DockerAllowLocalIPv6, + dockertestutil.DockerAllowNetworkAdministration, + ) + if err != nil { + return nil, fmt.Errorf("could not start tailscale container: %w", err) + } + log.Printf("Created %s container\n", hostname) + + return &TailscaleInContainer{ + version: version, + Hostname: hostname, + + pool: pool, + container: container, + network: network, + }, nil +} + +func (t *TailscaleInContainer) Shutdown() error { + return t.pool.Purge(t.container) +} + +func (t *TailscaleInContainer) Up( + loginServer, authKey string, +) error { + command := []string{ + "tailscale", + "up", + "-login-server", + loginServer, + "--authkey", + authKey, + "--hostname", + t.Hostname, + } + + log.Println("Join command:", command) + log.Printf("Running join command for %s\n", t.Hostname) + _, _, err := dockertestutil.ExecuteCommand( + t.container, + command, + []string{}, + ) + if err != nil { + return err + } + log.Printf("%s joined\n", t.Hostname) + + return nil +} + +func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) { + ips := make([]netip.Addr, 0) + + command := []string{ + "tailscale", + "ip", + } + + result, _, err := dockertestutil.ExecuteCommand( + t.container, + command, + []string{}, + ) + if err != nil { + return []netip.Addr{}, err + } + + for _, address := range strings.Split(result, "\n") { + address = strings.TrimSuffix(address, "\n") + if len(address) < 1 { + continue + } + ip, err := netip.ParseAddr(address) + if err != nil { + return nil, err + } + ips = append(ips, ip) + } + + return ips, nil +} + +func (t *TailscaleInContainer) Ping(ip netip.Addr) error { + command := []string{ + "tailscale", "ping", + "--timeout=1s", + "--c=10", + "--until-direct=true", + ip.String(), + } + + result, _, err := dockertestutil.ExecuteCommand( + t.container, + command, + []string{}, + ) + if err != nil { + return err + } + + if !strings.Contains(result, "pong") { + return errTailscalePingFailed + } + + return nil +} + +func createTailscaleBuildOptions(version string) *dockertest.BuildOptions { + var tailscaleBuildOptions *dockertest.BuildOptions + switch version { + case "head": + tailscaleBuildOptions = &dockertest.BuildOptions{ + Dockerfile: "Dockerfile.tailscale-HEAD", + ContextDir: dockerContextPath, + BuildArgs: []docker.BuildArg{}, + } + case "unstable": + tailscaleBuildOptions = &dockertest.BuildOptions{ + Dockerfile: "Dockerfile.tailscale", + ContextDir: dockerContextPath, + BuildArgs: []docker.BuildArg{ + { + Name: "TAILSCALE_VERSION", + Value: "*", // Installs the latest version https://askubuntu.com/a/824926 + }, + { + Name: "TAILSCALE_CHANNEL", + Value: "unstable", + }, + }, + } + default: + tailscaleBuildOptions = &dockertest.BuildOptions{ + Dockerfile: "Dockerfile.tailscale", + ContextDir: dockerContextPath, + BuildArgs: []docker.BuildArg{ + { + Name: "TAILSCALE_VERSION", + Value: version, + }, + { + Name: "TAILSCALE_CHANNEL", + Value: "stable", + }, + }, + } + } + + return tailscaleBuildOptions +} From 308b9e78a1613e68ae8ee01f3b7da1e39de4a28e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 13 Oct 2022 16:00:22 +0200 Subject: [PATCH 02/23] Defince control server interface Signed-off-by: Kristoffer Dalby --- integration/control.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 integration/control.go diff --git a/integration/control.go b/integration/control.go new file mode 100644 index 00000000..bcda4a56 --- /dev/null +++ b/integration/control.go @@ -0,0 +1,13 @@ +package integration + +import v1 "github.com/juanfont/headscale/gen/go/headscale/v1" + +type ControlServer interface { + Shutdown() error + GetHealthEndpoint() string + GetEndpoint() string + WaitForReady() error + CreateNamespace(namespace string) error + CreateAuthKey(namespace string) (*v1.PreAuthKey, error) + ListNodes(namespace string) ([]*v1.Machine, error) +} From b331e3f7367ca7208be6541641421a9325a05a85 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 13 Oct 2022 16:01:23 +0200 Subject: [PATCH 03/23] hsic: ControlServer implementation of headscale in docker Signed-off-by: Kristoffer Dalby --- integration/hsic/hsic.go | 223 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 integration/hsic/hsic.go diff --git a/integration/hsic/hsic.go b/integration/hsic/hsic.go new file mode 100644 index 00000000..78b1ef3b --- /dev/null +++ b/integration/hsic/hsic.go @@ -0,0 +1,223 @@ +package hsic + +import ( + "encoding/json" + "errors" + "fmt" + "log" + "net/http" + "os" + "path" + + "github.com/juanfont/headscale" + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" + "github.com/juanfont/headscale/integration/dockertestutil" + "github.com/ory/dockertest/v3" + "github.com/ory/dockertest/v3/docker" +) + +const hsicHashLength = 6 +const dockerContextPath = "../." + +var errHeadscaleStatusCodeNotOk = errors.New("headscale status code not ok") + +type HeadscaleInContainer struct { + hostname string + port int + + pool *dockertest.Pool + container *dockertest.Resource + network *dockertest.Network +} + +func New( + pool *dockertest.Pool, + port int, + network *dockertest.Network) (*HeadscaleInContainer, error) { + hash, err := headscale.GenerateRandomStringDNSSafe(hsicHashLength) + if err != nil { + return nil, err + } + + headscaleBuildOptions := &dockertest.BuildOptions{ + Dockerfile: "Dockerfile", + ContextDir: dockerContextPath, + } + + hostname := fmt.Sprintf("hs-%s", hash) + portProto := fmt.Sprintf("%d/tcp", port) + dockerPort := docker.Port(portProto) + + currentPath, err := os.Getwd() + if err != nil { + return nil, fmt.Errorf("could not determine current path: %w", err) + } + + integrationConfigPath := path.Join(currentPath, "..", "integration_test", "etc") + + runOptions := &dockertest.RunOptions{ + Name: hostname, + // TODO(kradalby): Do something clever here, can we ditch the config repo? + // Always generate the config from code? + Mounts: []string{ + fmt.Sprintf("%s:/etc/headscale", integrationConfigPath), + }, + ExposedPorts: []string{portProto}, + // TODO(kradalby): WHY do we need to bind these now that we run fully in docker? + PortBindings: map[docker.Port][]docker.PortBinding{ + dockerPort: {{HostPort: fmt.Sprintf("%d", port)}}, + }, + Networks: []*dockertest.Network{network}, + Cmd: []string{"headscale", "serve"}, + } + + // dockertest isnt very good at handling containers that has already + // been created, this is an attempt to make sure this container isnt + // present. + err = pool.RemoveContainerByName(hostname) + if err != nil { + return nil, err + } + + container, err := pool.BuildAndRunWithBuildOptions( + headscaleBuildOptions, + runOptions, + dockertestutil.DockerRestartPolicy, + dockertestutil.DockerAllowLocalIPv6, + dockertestutil.DockerAllowNetworkAdministration, + ) + if err != nil { + return nil, fmt.Errorf("could not start headscale container: %w", err) + } + log.Printf("Created %s container\n", hostname) + + return &HeadscaleInContainer{ + hostname: hostname, + port: port, + + pool: pool, + container: container, + network: network, + }, nil +} + +func (t *HeadscaleInContainer) Shutdown() error { + return t.pool.Purge(t.container) +} + +func (t *HeadscaleInContainer) GetIP() string { + return t.container.GetIPInNetwork(t.network) +} + +func (t *HeadscaleInContainer) GetPort() string { + portProto := fmt.Sprintf("%d/tcp", t.port) + + return t.container.GetPort(portProto) +} + +func (t *HeadscaleInContainer) GetHealthEndpoint() string { + hostEndpoint := fmt.Sprintf("%s:%s", + t.GetIP(), + t.GetPort()) + + return fmt.Sprintf("http://%s/health", hostEndpoint) +} + +func (t *HeadscaleInContainer) GetEndpoint() string { + hostEndpoint := fmt.Sprintf("%s:%s", + t.GetIP(), + t.GetPort()) + + return fmt.Sprintf("http://%s", hostEndpoint) +} + +func (t *HeadscaleInContainer) WaitForReady() error { + url := t.GetHealthEndpoint() + + return t.pool.Retry(func() error { + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("headscale is not ready: %w", err) + } + + if resp.StatusCode != http.StatusOK { + return errHeadscaleStatusCodeNotOk + } + + return nil + }) +} + +func (t *HeadscaleInContainer) CreateNamespace( + namespace string, +) error { + command := []string{"headscale", "namespaces", "create", namespace} + + _, _, err := dockertestutil.ExecuteCommand( + t.container, + command, + []string{}, + ) + if err != nil { + return err + } + + return nil +} + +func (t *HeadscaleInContainer) CreateAuthKey( + namespace string, +) (*v1.PreAuthKey, error) { + command := []string{ + "headscale", + "--namespace", + namespace, + "preauthkeys", + "create", + "--reusable", + "--expiration", + "24h", + "--output", + "json", + } + + result, _, err := dockertestutil.ExecuteCommand( + t.container, + command, + []string{}, + ) + if err != nil { + return nil, fmt.Errorf("failed to execute create auth key command: %w", err) + } + + var preAuthKey v1.PreAuthKey + err = json.Unmarshal([]byte(result), &preAuthKey) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal auth key: %w", err) + } + + return &preAuthKey, nil +} + +func (t *HeadscaleInContainer) ListNodes( + namespace string, +) ([]*v1.Machine, error) { + command := []string{"headscale", "--namespace", namespace, "nodes", "list", "--output", "json"} + + result, _, err := dockertestutil.ExecuteCommand( + t.container, + command, + []string{}, + ) + if err != nil { + return nil, fmt.Errorf("failed to execute list node command: %w", err) + } + + var nodes []*v1.Machine + err = json.Unmarshal([]byte(result), &nodes) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal nodes: %w", err) + } + + return nodes, nil +} From f68ba7504f542bbe6fb6c1bbd6e3a86d6529ea86 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 13 Oct 2022 16:03:09 +0200 Subject: [PATCH 04/23] Move some helper functions into dockertestutil package Signed-off-by: Kristoffer Dalby --- integration/dockertestutil/config.go | 28 ++++++++ integration/dockertestutil/execute.go | 94 +++++++++++++++++++++++++++ integration/dockertestutil/network.go | 21 ++++++ 3 files changed, 143 insertions(+) create mode 100644 integration/dockertestutil/config.go create mode 100644 integration/dockertestutil/execute.go create mode 100644 integration/dockertestutil/network.go diff --git a/integration/dockertestutil/config.go b/integration/dockertestutil/config.go new file mode 100644 index 00000000..2a5ac144 --- /dev/null +++ b/integration/dockertestutil/config.go @@ -0,0 +1,28 @@ +package dockertestutil + +import "github.com/ory/dockertest/v3/docker" + +func DockerRestartPolicy(config *docker.HostConfig) { + // set AutoRemove to true so that stopped container goes away by itself on error *immediately*. + // when set to false, containers remain until the end of the integration test. + config.AutoRemove = false + config.RestartPolicy = docker.RestartPolicy{ + Name: "no", + } +} + +func DockerAllowLocalIPv6(config *docker.HostConfig) { + if config.Sysctls == nil { + config.Sysctls = make(map[string]string, 1) + } + config.Sysctls["net.ipv6.conf.all.disable_ipv6"] = "0" +} + +func DockerAllowNetworkAdministration(config *docker.HostConfig) { + config.CapAdd = append(config.CapAdd, "NET_ADMIN") + config.Mounts = append(config.Mounts, docker.HostMount{ + Type: "bind", + Source: "/dev/net/tun", + Target: "/dev/net/tun", + }) +} diff --git a/integration/dockertestutil/execute.go b/integration/dockertestutil/execute.go new file mode 100644 index 00000000..71afa698 --- /dev/null +++ b/integration/dockertestutil/execute.go @@ -0,0 +1,94 @@ +package dockertestutil + +import ( + "bytes" + "errors" + "fmt" + "time" + + "github.com/ory/dockertest/v3" +) + +const dockerExecuteTimeout = time.Second * 10 + +var ( + ErrDockertestCommandFailed = errors.New("dockertest command failed") + ErrDockertestCommandTimeout = errors.New("dockertest command timed out") +) + +type ExecuteCommandConfig struct { + timeout time.Duration +} + +type ExecuteCommandOption func(*ExecuteCommandConfig) error + +func ExecuteCommandTimeout(timeout time.Duration) ExecuteCommandOption { + return ExecuteCommandOption(func(conf *ExecuteCommandConfig) error { + conf.timeout = timeout + + return nil + }) +} + +func ExecuteCommand( + resource *dockertest.Resource, + cmd []string, + env []string, + options ...ExecuteCommandOption, +) (string, string, error) { + var stdout bytes.Buffer + var stderr bytes.Buffer + + execConfig := ExecuteCommandConfig{ + timeout: dockerExecuteTimeout, + } + + for _, opt := range options { + if err := opt(&execConfig); err != nil { + return "", "", fmt.Errorf("execute-command/options: %w", err) + } + } + + type result struct { + exitCode int + err error + } + + resultChan := make(chan result, 1) + + // Run your long running function in it's own goroutine and pass back it's + // response into our channel. + go func() { + exitCode, err := resource.Exec( + cmd, + dockertest.ExecOptions{ + Env: append(env, "HEADSCALE_LOG_LEVEL=disabled"), + StdOut: &stdout, + StdErr: &stderr, + }, + ) + resultChan <- result{exitCode, err} + }() + + // Listen on our channel AND a timeout channel - which ever happens first. + select { + case res := <-resultChan: + if res.err != nil { + return stdout.String(), stderr.String(), res.err + } + + if res.exitCode != 0 { + // Uncomment for debugging + // log.Println("Command: ", cmd) + // log.Println("stdout: ", stdout.String()) + // log.Println("stderr: ", stderr.String()) + + return stdout.String(), stderr.String(), ErrDockertestCommandFailed + } + + return stdout.String(), stderr.String(), nil + case <-time.After(execConfig.timeout): + + return stdout.String(), stderr.String(), ErrDockertestCommandTimeout + } +} diff --git a/integration/dockertestutil/network.go b/integration/dockertestutil/network.go new file mode 100644 index 00000000..b4ff87cf --- /dev/null +++ b/integration/dockertestutil/network.go @@ -0,0 +1,21 @@ +package dockertestutil + +import "github.com/ory/dockertest/v3" + +func GetFirstOrCreateNetwork(pool *dockertest.Pool, name string) (*dockertest.Network, error) { + networks, err := pool.NetworksByName(name) + if err != nil || len(networks) == 0 { + if _, err := pool.CreateNetwork(name); err == nil { + // Create does not give us an updated version of the resource, so we need to + // get it again. + networks, err := pool.NetworksByName(name) + if err != nil { + return nil, err + } + + return &networks[0], nil + } + } + + return &networks[0], nil +} From a9c3b14f79e4dc733f2fe2a69931908d74e7ce12 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 13 Oct 2022 16:03:38 +0200 Subject: [PATCH 05/23] Define a "scenario", which is a controlserver with nodes Signed-off-by: Kristoffer Dalby --- integration/scenario.go | 206 +++++++++++++++++++++++++++++++++++ integration/scenario_test.go | 149 +++++++++++++++++++++++++ 2 files changed, 355 insertions(+) create mode 100644 integration/scenario.go create mode 100644 integration/scenario_test.go diff --git a/integration/scenario.go b/integration/scenario.go new file mode 100644 index 00000000..d3cbf247 --- /dev/null +++ b/integration/scenario.go @@ -0,0 +1,206 @@ +package integration + +import ( + "errors" + "fmt" + "log" + "os" + "sync" + + "github.com/juanfont/headscale" + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" + "github.com/juanfont/headscale/integration/dockertestutil" + "github.com/juanfont/headscale/integration/hsic" + "github.com/juanfont/headscale/integration/tsic" + "github.com/ory/dockertest/v3" +) + +const scenarioHashLength = 6 + +var errNoHeadscaleAvailable = errors.New("no headscale available") +var errNoNamespaceAvailable = errors.New("no namespace available") + +type Namespace struct { + Clients map[string]*tsic.TailscaleInContainer + + createWaitGroup sync.WaitGroup + joinWaitGroup sync.WaitGroup +} + +// TODO(kradalby): make control server configurable, test test correctness with +// Tailscale SaaS. +type Scenario struct { + // TODO(kradalby): support multiple headcales for later, currently only + // use one. + controlServers map[string]ControlServer + + namespaces map[string]*Namespace + + pool *dockertest.Pool + network *dockertest.Network +} + +func NewScenario() (*Scenario, error) { + hash, err := headscale.GenerateRandomStringDNSSafe(scenarioHashLength) + if err != nil { + return nil, err + } + + pool, err := dockertest.NewPool("") + if err != nil { + return nil, fmt.Errorf("could not connect to docker: %w", err) + } + + networkName := fmt.Sprintf("hs-%s", hash) + if overrideNetworkName := os.Getenv("HEADSCALE_TEST_NETWORK_NAME"); overrideNetworkName != "" { + networkName = overrideNetworkName + } + + network, err := dockertestutil.GetFirstOrCreateNetwork(pool, networkName) + if err != nil { + return nil, fmt.Errorf("failed to create or get network: %w", err) + } + + return &Scenario{ + controlServers: make(map[string]ControlServer), + namespaces: make(map[string]*Namespace), + + pool: pool, + network: network, + }, nil +} + +func (s *Scenario) Shutdown() error { + for _, control := range s.controlServers { + err := control.Shutdown() + if err != nil { + return fmt.Errorf("failed to tear down control: %w", err) + } + } + + for namespaceName, namespace := range s.namespaces { + for _, client := range namespace.Clients { + log.Printf("removing client %s in namespace %s", client.Hostname, namespaceName) + err := client.Shutdown() + if err != nil { + return fmt.Errorf("failed to tear down client: %w", err) + } + } + } + + // TODO(kradalby): This breaks the "we need to create a network before we start" + // part, since we now run the tests in a container... + // if err := s.pool.RemoveNetwork(s.network); err != nil { + // return fmt.Errorf("failed to remove network: %w", err) + // } + + // TODO(kradalby): This seem redundant to the previous call + // if err := s.network.Close(); err != nil { + // return fmt.Errorf("failed to tear down network: %w", err) + // } + + return nil +} + +/// Headscale related stuff +// Note: These functions assume that there is a _single_ headscale instance for now + +// TODO(kradalby): make port and headscale configurable, multiple instances support? +func (s *Scenario) StartHeadscale() error { + headscale, err := hsic.New(s.pool, 8080, s.network) + if err != nil { + return fmt.Errorf("failed to create headscale container: %w", err) + } + + s.controlServers["headscale"] = headscale + + return nil +} + +func (s *Scenario) Headscale() *hsic.HeadscaleInContainer { + return s.controlServers["headscale"].(*hsic.HeadscaleInContainer) +} + +func (s *Scenario) CreatePreAuthKey(namespace string) (*v1.PreAuthKey, error) { + if headscale, ok := s.controlServers["headscale"]; ok { + key, err := headscale.CreateAuthKey(namespace) + if err != nil { + return nil, fmt.Errorf("failed to create namespace: %w", err) + } + + return key, nil + } + + return nil, fmt.Errorf("failed to create namespace: %w", errNoHeadscaleAvailable) +} + +func (s *Scenario) CreateNamespace(namespace string) error { + if headscale, ok := s.controlServers["headscale"]; ok { + err := headscale.CreateNamespace(namespace) + if err != nil { + return fmt.Errorf("failed to create namespace: %w", err) + } + + s.namespaces[namespace] = &Namespace{ + Clients: make(map[string]*tsic.TailscaleInContainer), + } + + return nil + } + + return fmt.Errorf("failed to create namespace: %w", errNoHeadscaleAvailable) +} + +/// Client related stuff + +func (s *Scenario) CreateTailscaleNodesInNamespace( + namespace string, + version string, + count int, +) error { + if ns, ok := s.namespaces[namespace]; ok { + for i := 0; i < count; i++ { + ns.createWaitGroup.Add(1) + + go func() { + defer ns.createWaitGroup.Done() + + // TODO(kradalby): error handle this + ts, err := tsic.New(s.pool, version, s.network) + if err != nil { + // return fmt.Errorf("failed to add tailscale node: %w", err) + fmt.Printf("failed to add tailscale node: %s", err) + } + + ns.Clients[ts.Hostname] = ts + }() + } + ns.createWaitGroup.Wait() + + return nil + } + + return fmt.Errorf("failed to add tailscale node: %w", errNoNamespaceAvailable) +} + +func (s *Scenario) RunTailscaleUp( + namespace, loginServer, authKey string, +) error { + if ns, ok := s.namespaces[namespace]; ok { + for _, client := range ns.Clients { + ns.joinWaitGroup.Add(1) + + go func() { + defer ns.joinWaitGroup.Done() + + // TODO(kradalby): error handle this + _ = client.Up(loginServer, authKey) + }() + } + ns.joinWaitGroup.Wait() + + return nil + } + + return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable) +} diff --git a/integration/scenario_test.go b/integration/scenario_test.go new file mode 100644 index 00000000..cb4aa859 --- /dev/null +++ b/integration/scenario_test.go @@ -0,0 +1,149 @@ +package integration + +import ( + "testing" + + "github.com/juanfont/headscale/integration/tsic" +) + +func TestHeadscale(t *testing.T) { + var err error + + scenario, err := NewScenario() + if err != nil { + t.Errorf("failed to create scenario: %s", err) + } + + t.Run("start-headscale", func(t *testing.T) { + err = scenario.StartHeadscale() + if err != nil { + t.Errorf("failed to create start headcale: %s", err) + } + + err = scenario.Headscale().WaitForReady() + if err != nil { + t.Errorf("headscale failed to become ready: %s", err) + } + + }) + + t.Run("create-namespace", func(t *testing.T) { + err := scenario.CreateNamespace("test-space") + if err != nil { + t.Errorf("failed to create namespace: %s", err) + } + + if _, ok := scenario.namespaces["test-space"]; !ok { + t.Errorf("namespace is not in scenario") + } + }) + + t.Run("create-auth-key", func(t *testing.T) { + _, err := scenario.CreatePreAuthKey("test-space") + if err != nil { + t.Errorf("failed to create preauthkey: %s", err) + } + }) + + err = scenario.Shutdown() + if err != nil { + t.Errorf("failed to tear down scenario: %s", err) + } +} + +func TestCreateTailscale(t *testing.T) { + var scenario *Scenario + var err error + + namespace := "only-create-containers" + + scenario, err = NewScenario() + if err != nil { + t.Errorf("failed to create scenario: %s", err) + } + + scenario.namespaces[namespace] = &Namespace{ + Clients: make(map[string]*tsic.TailscaleInContainer), + } + + t.Run("create-tailscale", func(t *testing.T) { + err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.32.0", 3) + if err != nil { + t.Errorf("failed to add tailscale nodes: %s", err) + } + + if clients := len(scenario.namespaces[namespace].Clients); clients != 3 { + t.Errorf("wrong number of tailscale clients: %d != %d", clients, 3) + } + }) + + err = scenario.Shutdown() + if err != nil { + t.Errorf("failed to tear down scenario: %s", err) + } +} + +func TestTailscaleNodesJoiningHeadcale(t *testing.T) { + var err error + + namespace := "join-node-test" + + scenario, err := NewScenario() + if err != nil { + t.Errorf("failed to create scenario: %s", err) + } + + t.Run("start-headscale", func(t *testing.T) { + err = scenario.StartHeadscale() + if err != nil { + t.Errorf("failed to create start headcale: %s", err) + } + + headscale := scenario.Headscale() + err = headscale.WaitForReady() + if err != nil { + t.Errorf("headscale failed to become ready: %s", err) + } + + }) + + t.Run("create-namespace", func(t *testing.T) { + err := scenario.CreateNamespace(namespace) + if err != nil { + t.Errorf("failed to create namespace: %s", err) + } + + if _, ok := scenario.namespaces[namespace]; !ok { + t.Errorf("namespace is not in scenario") + } + }) + + t.Run("create-tailscale", func(t *testing.T) { + err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.32.0", 2) + if err != nil { + t.Errorf("failed to add tailscale nodes: %s", err) + } + + if clients := len(scenario.namespaces[namespace].Clients); clients != 2 { + t.Errorf("wrong number of tailscale clients: %d != %d", clients, 2) + } + }) + + t.Run("join-headscale", func(t *testing.T) { + key, err := scenario.CreatePreAuthKey(namespace) + if err != nil { + t.Errorf("failed to create preauthkey: %s", err) + } + + err = scenario.RunTailscaleUp(namespace, scenario.Headscale().GetEndpoint(), key.GetKey()) + if err != nil { + t.Errorf("failed to login: %s", err) + } + + }) + + err = scenario.Shutdown() + if err != nil { + t.Errorf("failed to tear down scenario: %s", err) + } +} From eda432148687f467c4d425235aa8f75c5d8c83c8 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 14 Oct 2022 10:37:13 +0200 Subject: [PATCH 06/23] Skip integration tests on short or lack of docker Signed-off-by: Kristoffer Dalby --- integration/dockertestutil/config.go | 14 +++++++++++++- integration/scenario_test.go | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/integration/dockertestutil/config.go b/integration/dockertestutil/config.go index 2a5ac144..4dc3ee33 100644 --- a/integration/dockertestutil/config.go +++ b/integration/dockertestutil/config.go @@ -1,6 +1,18 @@ package dockertestutil -import "github.com/ory/dockertest/v3/docker" +import ( + "os" + + "github.com/ory/dockertest/v3/docker" +) + +func IsRunningInContainer() bool { + if _, err := os.Stat("/.dockerenv"); err != nil { + return false + } + + return true +} func DockerRestartPolicy(config *docker.HostConfig) { // set AutoRemove to true so that stopped container goes away by itself on error *immediately*. diff --git a/integration/scenario_test.go b/integration/scenario_test.go index cb4aa859..8811b2f8 100644 --- a/integration/scenario_test.go +++ b/integration/scenario_test.go @@ -3,10 +3,24 @@ package integration import ( "testing" + "github.com/juanfont/headscale/integration/dockertestutil" "github.com/juanfont/headscale/integration/tsic" ) +func IntegrationSkip(t *testing.T) { + t.Helper() + + if !dockertestutil.IsRunningInContainer() { + t.Skip("not running in docker, skipping") + } + + if testing.Short() { + t.Skip("skipping integration tests due to short flag") + } +} + func TestHeadscale(t *testing.T) { + IntegrationSkip(t) var err error scenario, err := NewScenario() @@ -52,6 +66,8 @@ func TestHeadscale(t *testing.T) { } func TestCreateTailscale(t *testing.T) { + IntegrationSkip(t) + var scenario *Scenario var err error @@ -84,6 +100,8 @@ func TestCreateTailscale(t *testing.T) { } func TestTailscaleNodesJoiningHeadcale(t *testing.T) { + IntegrationSkip(t) + var err error namespace := "join-node-test" From f109b54e7953a37198ddcb8b9ea1ea297ba3265c Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 14 Oct 2022 10:38:27 +0200 Subject: [PATCH 07/23] Join test suite container to network, allowing seperate networks Signed-off-by: Kristoffer Dalby --- integration/dockertestutil/network.go | 43 ++++++++++++++++++++++++++- integration/scenario.go | 16 ++++++---- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/integration/dockertestutil/network.go b/integration/dockertestutil/network.go index b4ff87cf..15c99082 100644 --- a/integration/dockertestutil/network.go +++ b/integration/dockertestutil/network.go @@ -1,6 +1,13 @@ package dockertestutil -import "github.com/ory/dockertest/v3" +import ( + "errors" + + "github.com/ory/dockertest/v3" + "github.com/ory/dockertest/v3/docker" +) + +var ErrContainerNotFound = errors.New("container not found") func GetFirstOrCreateNetwork(pool *dockertest.Pool, name string) (*dockertest.Network, error) { networks, err := pool.NetworksByName(name) @@ -19,3 +26,37 @@ func GetFirstOrCreateNetwork(pool *dockertest.Pool, name string) (*dockertest.Ne return &networks[0], nil } + +func AddContainerToNetwork( + pool *dockertest.Pool, + network *dockertest.Network, + testContainer string, +) error { + containers, err := pool.Client.ListContainers(docker.ListContainersOptions{ + All: true, + Filters: map[string][]string{ + "name": {testContainer}, + }, + }) + if err != nil { + return err + } + + err = pool.Client.ConnectNetwork(network.Network.ID, docker.NetworkConnectionOptions{ + Container: containers[0].ID, + }) + if err != nil { + return err + } + + // TODO(kradalby): This doesnt work reliably, but calling the exact same functions + // seem to work fine... + // if container, ok := pool.ContainerByName("/" + testContainer); ok { + // err := container.ConnectToNetwork(network) + // if err != nil { + // return err + // } + // } + + return nil +} diff --git a/integration/scenario.go b/integration/scenario.go index d3cbf247..b1b0719b 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -61,6 +61,14 @@ func NewScenario() (*Scenario, error) { return nil, fmt.Errorf("failed to create or get network: %w", err) } + // We run the test suite in a docker container that calls a couple of endpoints for + // readiness checks, this ensures that we can run the tests with individual networks + // and have the client reach the different containers + err = dockertestutil.AddContainerToNetwork(pool, network, "headscale-test-suite") + if err != nil { + return nil, fmt.Errorf("failed to add test suite container to network: %w", err) + } + return &Scenario{ controlServers: make(map[string]ControlServer), namespaces: make(map[string]*Namespace), @@ -88,11 +96,9 @@ func (s *Scenario) Shutdown() error { } } - // TODO(kradalby): This breaks the "we need to create a network before we start" - // part, since we now run the tests in a container... - // if err := s.pool.RemoveNetwork(s.network); err != nil { - // return fmt.Errorf("failed to remove network: %w", err) - // } + if err := s.pool.RemoveNetwork(s.network); err != nil { + return fmt.Errorf("failed to remove network: %w", err) + } // TODO(kradalby): This seem redundant to the previous call // if err := s.network.Close(); err != nil { From 25e39d9ff9b0da2b6a2d96633c234a067db16eb9 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 14 Oct 2022 12:17:59 +0200 Subject: [PATCH 08/23] Add get ips command to scenario Signed-off-by: Kristoffer Dalby --- integration/scenario.go | 18 ++++++++++++++++++ integration/tsic/tsic.go | 16 +++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/integration/scenario.go b/integration/scenario.go index b1b0719b..2f00daf8 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "log" + "net/netip" "os" "sync" @@ -210,3 +211,20 @@ func (s *Scenario) RunTailscaleUp( return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable) } + +func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) { + var ips []netip.Addr + if ns, ok := s.namespaces[namespace]; ok { + for _, client := range ns.Clients { + clientIps, err := client.IPs() + if err != nil { + return ips, fmt.Errorf("failed to get ips: %w", err) + } + ips = append(ips, clientIps...) + } + + return ips, nil + } + + return ips, fmt.Errorf("failed to get ips: %w", errNoNamespaceAvailable) +} diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 40a0e693..4bbba8e2 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -17,6 +17,7 @@ const tsicHashLength = 6 const dockerContextPath = "../." var errTailscalePingFailed = errors.New("ping failed") +var errTailscaleNotLoggedIn = errors.New("tailscale not logged in") type TailscaleInContainer struct { version string @@ -102,14 +103,17 @@ func (t *TailscaleInContainer) Up( log.Println("Join command:", command) log.Printf("Running join command for %s\n", t.Hostname) - _, _, err := dockertestutil.ExecuteCommand( + stdout, stderr, err := dockertestutil.ExecuteCommand( t.container, command, []string{}, ) if err != nil { + log.Printf("tailscale join stderr: %s\n", stderr) + return err } + log.Printf("tailscale join stdout: %s\n", stdout) log.Printf("%s joined\n", t.Hostname) return nil @@ -123,12 +127,18 @@ func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) { "ip", } - result, _, err := dockertestutil.ExecuteCommand( + result, stderr, err := dockertestutil.ExecuteCommand( t.container, command, []string{}, ) if err != nil { + log.Printf("failed commands stderr: %s\n", stderr) + + if strings.Contains(stderr, "NeedsLogin") { + return []netip.Addr{}, errTailscaleNotLoggedIn + } + return []netip.Addr{}, err } @@ -165,7 +175,7 @@ func (t *TailscaleInContainer) Ping(ip netip.Addr) error { return err } - if !strings.Contains(result, "pong") { + if !strings.Contains(result, "pong") || !strings.Contains(result, "is local") { return errTailscalePingFailed } From b0a4ee4dfeefa87a245b7a4fc95e60d2a67270ad Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 14 Oct 2022 12:18:28 +0200 Subject: [PATCH 09/23] test login with one node Signed-off-by: Kristoffer Dalby --- integration/scenario_test.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/integration/scenario_test.go b/integration/scenario_test.go index 8811b2f8..c13784b9 100644 --- a/integration/scenario_test.go +++ b/integration/scenario_test.go @@ -21,6 +21,7 @@ func IntegrationSkip(t *testing.T) { func TestHeadscale(t *testing.T) { IntegrationSkip(t) + var err error scenario, err := NewScenario() @@ -106,6 +107,8 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) { namespace := "join-node-test" + count := 1 + scenario, err := NewScenario() if err != nil { t.Errorf("failed to create scenario: %s", err) @@ -137,13 +140,13 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) { }) t.Run("create-tailscale", func(t *testing.T) { - err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.32.0", 2) + err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.30.2", count) if err != nil { t.Errorf("failed to add tailscale nodes: %s", err) } - if clients := len(scenario.namespaces[namespace].Clients); clients != 2 { - t.Errorf("wrong number of tailscale clients: %d != %d", clients, 2) + if clients := len(scenario.namespaces[namespace].Clients); clients != count { + t.Errorf("wrong number of tailscale clients: %d != %d", clients, count) } }) @@ -157,7 +160,17 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) { if err != nil { t.Errorf("failed to login: %s", err) } + }) + t.Run("get-ips", func(t *testing.T) { + ips, err := scenario.GetIPs(namespace) + if err != nil { + t.Errorf("failed to get tailscale ips: %s", err) + } + + if len(ips) != count*2 { + t.Errorf("got the wrong amount of tailscale ips, %d != %d", len(ips), count*2) + } }) err = scenario.Shutdown() From 13aa845c69db8a8fff44f17df2bf5d7a81d3dab3 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 14 Oct 2022 12:23:35 +0200 Subject: [PATCH 10/23] Add comment about scenario test Signed-off-by: Kristoffer Dalby --- integration/scenario_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integration/scenario_test.go b/integration/scenario_test.go index c13784b9..9e97bc31 100644 --- a/integration/scenario_test.go +++ b/integration/scenario_test.go @@ -7,6 +7,9 @@ import ( "github.com/juanfont/headscale/integration/tsic" ) +// This file is intendet to "test the test framework", by proxy it will also test +// some Headcsale/Tailscale stuff, but mostly in very simple ways. + func IntegrationSkip(t *testing.T) { t.Helper() From aef77a113ccca4734ef371cfd0996cbd61ef85c9 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 14 Oct 2022 12:38:34 +0200 Subject: [PATCH 11/23] use variable for namespace Signed-off-by: Kristoffer Dalby --- integration/scenario_test.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/integration/scenario_test.go b/integration/scenario_test.go index 9e97bc31..ff6f3e85 100644 --- a/integration/scenario_test.go +++ b/integration/scenario_test.go @@ -27,6 +27,8 @@ func TestHeadscale(t *testing.T) { var err error + namespace := "test-space" + scenario, err := NewScenario() if err != nil { t.Errorf("failed to create scenario: %s", err) @@ -46,18 +48,18 @@ func TestHeadscale(t *testing.T) { }) t.Run("create-namespace", func(t *testing.T) { - err := scenario.CreateNamespace("test-space") + err := scenario.CreateNamespace(namespace) if err != nil { t.Errorf("failed to create namespace: %s", err) } - if _, ok := scenario.namespaces["test-space"]; !ok { + if _, ok := scenario.namespaces[namespace]; !ok { t.Errorf("namespace is not in scenario") } }) t.Run("create-auth-key", func(t *testing.T) { - _, err := scenario.CreatePreAuthKey("test-space") + _, err := scenario.CreatePreAuthKey(namespace) if err != nil { t.Errorf("failed to create preauthkey: %s", err) } From 84f9f604b0fc083745ba1314f662de09c4493a0b Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 11:57:21 +0200 Subject: [PATCH 12/23] go mod tidy Signed-off-by: Kristoffer Dalby --- go.mod | 2 +- go.sum | 126 +-------------------------------------------------------- 2 files changed, 3 insertions(+), 125 deletions(-) diff --git a/go.mod b/go.mod index 24463c34..53f1fd91 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( github.com/AlecAivazis/survey/v2 v2.3.5 github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029 + github.com/cenkalti/backoff/v4 v4.1.3 github.com/coreos/go-oidc/v3 v3.3.0 github.com/deckarep/golang-set/v2 v2.1.0 github.com/efekarakus/termcolor v1.0.1 @@ -54,7 +55,6 @@ require ( github.com/akutz/memconn v0.1.0 // indirect github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/console v1.0.3 // indirect github.com/containerd/continuity v0.3.0 // indirect diff --git a/go.sum b/go.sum index 0567a055..180e7c37 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,6 @@ contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EU dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= -filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= -filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/mkcert v1.4.3 h1:axpnmtrZMM8u5Hf4N3UXxboGemMOV+Tn+e+pkHM6E3o= github.com/AlecAivazis/survey/v2 v2.3.5 h1:A8cYupsAZkjaUmhtTYv3sSqc7LO5mp1XDfqe5E/9wRQ= github.com/AlecAivazis/survey/v2 v2.3.5/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI= @@ -80,8 +78,6 @@ github.com/Antonboom/errname v0.1.5/go.mod h1:DugbBstvPFQbv/5uLcRRzfrNqKE9tVdVCq github.com/Antonboom/nilnil v0.1.0/go.mod h1:PhHLvRPSghY5Y7mX4TW+BHZQYo1A8flE5H20D3IPZBo= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= @@ -154,7 +150,6 @@ github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029/go.mod h1:Rpr5 github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 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 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -168,8 +163,6 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/cilium/ebpf v0.8.1 h1:bLSSEbBLqGPXxls55pGr5qWZaTqcmfDJHhou7t254ao= github.com/cilium/ebpf v0.8.1/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk= -github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= -github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -189,8 +182,6 @@ github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvA github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc/v3 v3.2.0 h1:2eR2MGR7thBXSQ2YbODlF0fcmgtliLCfr9iX6RW11fc= -github.com/coreos/go-oidc/v3 v3.2.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-oidc/v3 v3.3.0 h1:Y1LV3mP+QT3MEycATZpAiwfyN+uxZLqVbAHJUuOJEe4= github.com/coreos/go-oidc/v3 v3.3.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -224,18 +215,12 @@ github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCF github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61icFuZl6iKYs= github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= -github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ= github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= -github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/efekarakus/termcolor v1.0.1 h1:YAKFO3bnLrqZGTWyNLcYoSIAQFKVOmbqmDnwsU/znzg= @@ -273,10 +258,10 @@ github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASx 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= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/glebarez/go-sqlite v1.17.3 h1:Rji9ROVSTTfjuWD6j5B+8DtkNvPILoUC3xRhkQzGxvk= github.com/glebarez/go-sqlite v1.17.3/go.mod h1:Hg+PQuhUy98XCxWEJEaWob8x7lhJzhNYF1nZbUiRGIY= -github.com/glebarez/go-sqlite v1.18.1 h1:w0xtxKWktqYsUsXg//SQK+l1IcpKb3rGOQHmMptvL2U= -github.com/glebarez/go-sqlite v1.18.1/go.mod h1:ydXIGq2M4OzF4YyNhH129SPp7jWoVvgkEgb6pldmS0s= github.com/glebarez/sqlite v1.4.6 h1:D5uxD2f6UJ82cHnVtO2TZ9pqsLyto3fpDKHIk2OsR8A= github.com/glebarez/sqlite v1.4.6/go.mod h1:WYEtEFjhADPaPJqL/PGlbQQGINBA3eUAfDNbKFJf/zA= github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM= @@ -453,8 +438,6 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= -github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= -github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= @@ -484,10 +467,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 h1:BqHID5W5qnMkug0Z8UmL8tN0gAy4jQ+B4WFt8cCgluU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2/go.mod h1:ZbS3MZTZq/apAfAEHGoB5HbsQQstoqP92SjAqtQ9zeg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= @@ -511,8 +491,6 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -539,13 +517,8 @@ github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -558,8 +531,6 @@ github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8 github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.12.1 h1:rsDFzIpRk7xT4B8FufgpCCeyjdNpKyghZeSefViE5W8= github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono= -github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -568,7 +539,6 @@ github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5W github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -578,8 +548,6 @@ github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwX github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.3.0 h1:brH0pCGBDkBW07HWlN/oSBXrmo3WB0UvZd1pIuDcL8Y= github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= @@ -588,21 +556,16 @@ github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrU github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= github.com/jackc/pgtype v1.11.0 h1:u4uiGPz/1hryuXzyaBhSk6dnIyyG2683olG2OV+UUgs= github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.16.1 h1:JzTglcal01DrghUqt+PmzWsZx/Yh7SC/CTQmSBMTd0Y= github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ= -github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= -github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= @@ -610,8 +573,6 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= @@ -625,8 +586,6 @@ github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOv github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b h1:Yws7RV6kZr2O7PPdT+RkbSmmOponA8i/1DuGHe8BRsM= github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b/go.mod h1:TzDCVOZKUa79z6iXbbXqhtAflVgUKaFkZ21M5tK5tzY= -github.com/jsimonetti/rtnetlink v1.2.2 h1:Ok9vYMcpxfHyF/iRqNTYJPDLxVaVItvPamAhtzttDBY= -github.com/jsimonetti/rtnetlink v1.2.2/go.mod h1:T3BJ2qI9ZJFkUYWLrzECdcXhCvaGRfnMFmoYF0X8w2A= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -713,8 +672,6 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -725,8 +682,6 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -735,7 +690,6 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -749,8 +703,6 @@ github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfp github.com/mgechev/revive v1.1.2/go.mod h1:bnXsMr+ZTH09V5rssEI+jHAZ4z+ZdyhgO/zsy3EhK+0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= @@ -777,8 +729,6 @@ github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -822,8 +772,6 @@ github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 h1:+cz github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198/go.mod h1:j4h1pJW6ZcJTgMZWP3+7RlG3zTaP02aDZ/Qw0sppK7Q= github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw= github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg= -github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -845,8 +793,6 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/philip-bui/grpc-zerolog v1.0.1 h1:EMacvLRUd2O1K0eWod27ZP5CY1iTNkhBDLSN+Q4JEvA= @@ -900,8 +846,6 @@ github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5b github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= github.com/pterm/pterm v0.12.45 h1:5HATKLTDjl9D74b0x7yiHzFI7OADlSXK3yHrJNhRwZE= github.com/pterm/pterm v0.12.45/go.mod h1:hJgLlBafm45w/Hr0dKXxY//POD7CgowhePaG1sdPNBg= -github.com/puzpuzpuz/xsync v1.4.2 h1:3SmMNFuNaSHy1xsGGR8edy3Rzv0Ix3dOirPWtAnXvKk= -github.com/puzpuzpuz/xsync v1.4.2/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg= github.com/puzpuzpuz/xsync v1.4.3 h1:nS/Iqc4EnpJ8jm/MzJ+e3MUaP2Ys2mqXeEfoxoU0HaM= github.com/puzpuzpuz/xsync v1.4.3/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= @@ -916,8 +860,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.3.4 h1:3Z3Eu6FGHZWSfNKJTOUiPatWwfc7DzJRU04jFUqJODw= -github.com/rivo/uniseg v0.3.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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= @@ -925,16 +867,11 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w= github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= -github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -949,7 +886,6 @@ github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dms github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= @@ -969,8 +905,6 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -982,8 +916,6 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1026,8 +958,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= -github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tailscale/hujson v0.0.0-20220630195928-54599719472f h1:n4r/sJ92cBSBHK8n9lR1XLFr0OiTVeGfN5TR+9LaN7E= @@ -1068,8 +998,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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= @@ -1119,16 +1047,10 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= go4.org/mem v0.0.0-20210711025021-927187094b94 h1:OAAkygi2Js191AJP1Ds42MhJRgeofeKGjuoUqNp1QC4= go4.org/mem v0.0.0-20210711025021-927187094b94/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= -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-20220725152314-7e7bdc8411bf h1:IdwJUzqoIo5lkr2EOyKoe5qipUaEjbOKKY5+fzPBZ3A= -go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf/go.mod h1:+QXzaoURFd0rGDIjDNpyIkv+F9R7EmeKorvlKRnhqgA= go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d h1:ggxwEf5eu0l8v+87VhX1czFh8zJul3hK16Gmruxn7hw= go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1152,8 +1074,6 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1226,7 +1146,6 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -1257,7 +1176,6 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= @@ -1282,8 +1200,6 @@ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7 h1:dtndE8FcEta75/4kHF3AbpuWzV6f1LjnLrM4pe2SZrw= -golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 h1:2o1E+E8TpNLklK9nHiPiK1uzIYrIHt+cQx3ynCwq9V8= golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1299,8 +1215,6 @@ 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-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1406,20 +1320,14 @@ golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/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-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1428,8 +1336,6 @@ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8= golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1440,8 +1346,6 @@ 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 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y= -golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1449,8 +1353,6 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= -golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1571,8 +1473,6 @@ golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNq golang.zx2c4.com/wireguard v0.0.0-20210905140043-2ef39d47540c/go.mod h1:laHzsbfMhGSobUmruXWAyMKKHSqvIcrqZJMyHD+/3O8= golang.zx2c4.com/wireguard/windows v0.4.10 h1:HmjzJnb+G4NCdX+sfjsQlsxGPuYaThxRbZUZFLyR0/s= golang.zx2c4.com/wireguard/windows v0.4.10/go.mod h1:v7w/8FC48tTBm1IzScDVPEEb0/GjLta+T0ybpP9UWRg= -golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= -golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= 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= @@ -1709,8 +1609,6 @@ google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220808204814-fd01256a5276 h1:7PEE9xCtufpGJzrqweakEEnTh7YFELmnKm/ee+5jmfQ= -google.golang.org/genproto v0.0.0-20220808204814-fd01256a5276/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= google.golang.org/genproto v0.0.0-20220902135211-223410557253 h1:vXJMM8Shg7TGaYxZsQ++A/FOSlbDmDtWhS/o+3w/hj4= google.golang.org/genproto v0.0.0-20220902135211-223410557253/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1748,8 +1646,6 @@ google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1786,10 +1682,7 @@ gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/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/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -1807,14 +1700,10 @@ 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-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -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= -gorm.io/driver/postgres v1.3.8 h1:8bEphSAB69t3odsCR4NDzt581iZEWQuRM27Cg6KgfPY= -gorm.io/driver/postgres v1.3.8/go.mod h1:qB98Aj6AhRO/oyu/jmZsi/YM9g6UzVCjMxO/6frFvcA= gorm.io/driver/postgres v1.3.9 h1:lWGiVt5CijhQAg0PWB7Od1RNcBw/jS4d2cAScBcSDXg= gorm.io/driver/postgres v1.3.9/go.mod h1:qw/FeqjxmYqW5dBcYNBsnhQULIApQdk7YuuDPktVi1U= -gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= @@ -1836,7 +1725,6 @@ modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpN modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= @@ -1845,24 +1733,14 @@ modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o= modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.3 h1:MbsE18Y/xJMTxGGjq2Il6aZZf1YFUu6mnRZgQm/VUWQ= -modernc.org/libc v1.17.3/go.mod h1:9y68dPDczc/zwZupQ2yLX/HTAC4YY/u3grUCeD5fC9I= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1 h1:dkRh86wgmq/bJu2cAS2oqBCz/KsMZU7TUM4CibQ7eBs= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sqlite v1.17.3 h1:iE+coC5g17LtByDYDWKpR6m2Z9022YrSh3bumwOnIrI= modernc.org/sqlite v1.17.3/go.mod h1:10hPVYar9C0kfXuTWGz8s0XtB8uAGymUy51ZzStYe3k= -modernc.org/sqlite v1.18.1 h1:ko32eKt3jf7eqIkCgPAeHMBXw3riNSLhl2f3loEF7o8= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= From c90d0dd843e47cbbe5584725ff8c2b2387dd0b90 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 11:58:15 +0200 Subject: [PATCH 13/23] remove the need to bind host port Signed-off-by: Kristoffer Dalby --- integration/hsic/hsic.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/integration/hsic/hsic.go b/integration/hsic/hsic.go index 78b1ef3b..2b1eedc8 100644 --- a/integration/hsic/hsic.go +++ b/integration/hsic/hsic.go @@ -13,7 +13,6 @@ import ( v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/integration/dockertestutil" "github.com/ory/dockertest/v3" - "github.com/ory/dockertest/v3/docker" ) const hsicHashLength = 6 @@ -46,7 +45,6 @@ func New( hostname := fmt.Sprintf("hs-%s", hash) portProto := fmt.Sprintf("%d/tcp", port) - dockerPort := docker.Port(portProto) currentPath, err := os.Getwd() if err != nil { @@ -64,9 +62,6 @@ func New( }, ExposedPorts: []string{portProto}, // TODO(kradalby): WHY do we need to bind these now that we run fully in docker? - PortBindings: map[docker.Port][]docker.PortBinding{ - dockerPort: {{HostPort: fmt.Sprintf("%d", port)}}, - }, Networks: []*dockertest.Network{network}, Cmd: []string{"headscale", "serve"}, } @@ -116,17 +111,17 @@ func (t *HeadscaleInContainer) GetPort() string { } func (t *HeadscaleInContainer) GetHealthEndpoint() string { - hostEndpoint := fmt.Sprintf("%s:%s", + hostEndpoint := fmt.Sprintf("%s:%d", t.GetIP(), - t.GetPort()) + t.port) return fmt.Sprintf("http://%s/health", hostEndpoint) } func (t *HeadscaleInContainer) GetEndpoint() string { - hostEndpoint := fmt.Sprintf("%s:%s", + hostEndpoint := fmt.Sprintf("%s:%d", t.GetIP(), - t.GetPort()) + t.port) return fmt.Sprintf("http://%s", hostEndpoint) } @@ -134,6 +129,8 @@ func (t *HeadscaleInContainer) GetEndpoint() string { func (t *HeadscaleInContainer) WaitForReady() error { url := t.GetHealthEndpoint() + log.Printf("waiting for headscale to be ready at %s", url) + return t.pool.Retry(func() error { resp, err := http.Get(url) if err != nil { From 3951f3986875ec040543606f720bf811fa40242f Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 11:58:49 +0200 Subject: [PATCH 14/23] Add wait for peers and status to tsic Signed-off-by: Kristoffer Dalby --- integration/tsic/tsic.go | 88 +++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 4bbba8e2..2dfd852c 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -1,16 +1,19 @@ package tsic import ( + "encoding/json" "errors" "fmt" "log" "net/netip" "strings" + "github.com/cenkalti/backoff/v4" "github.com/juanfont/headscale" "github.com/juanfont/headscale/integration/dockertestutil" "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" + "tailscale.com/ipn/ipnstate" ) const tsicHashLength = 6 @@ -87,6 +90,10 @@ func (t *TailscaleInContainer) Shutdown() error { return t.pool.Purge(t.container) } +func (t *TailscaleInContainer) Version() string { + return t.version +} + func (t *TailscaleInContainer) Up( loginServer, authKey string, ) error { @@ -113,12 +120,17 @@ func (t *TailscaleInContainer) Up( return err } - log.Printf("tailscale join stdout: %s\n", stdout) + + if stdout != "" { + log.Printf("tailscale join stdout: %s\n", stdout) + } + log.Printf("%s joined\n", t.Hostname) return nil } +// TODO(kradalby): Make cached/lazy func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) { ips := make([]netip.Addr, 0) @@ -157,13 +169,11 @@ func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) { return ips, nil } -func (t *TailscaleInContainer) Ping(ip netip.Addr) error { +func (t *TailscaleInContainer) Status() (*ipnstate.Status, error) { command := []string{ - "tailscale", "ping", - "--timeout=1s", - "--c=10", - "--until-direct=true", - ip.String(), + "tailscale", + "status", + "--json", } result, _, err := dockertestutil.ExecuteCommand( @@ -172,14 +182,70 @@ func (t *TailscaleInContainer) Ping(ip netip.Addr) error { []string{}, ) if err != nil { - return err + return nil, fmt.Errorf("failed to execute tailscale status command: %w", err) } - if !strings.Contains(result, "pong") || !strings.Contains(result, "is local") { - return errTailscalePingFailed + var status ipnstate.Status + err = json.Unmarshal([]byte(result), &status) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal tailscale status: %w", err) } - return nil + return &status, err +} + +func (t *TailscaleInContainer) WaitForPeers(expected int) error { + return t.pool.Retry(func() error { + status, err := t.Status() + if err != nil { + return fmt.Errorf("failed to fetch tailscale status: %w", err) + } + + if peers := status.Peers(); len(peers) != expected { + return fmt.Errorf( + "tailscale client does not have the expected clients: %d out of %d", + len(peers), + expected, + ) + } + + return nil + }) +} + +// TODO(kradalby): Make multiping, go routine magic +func (t *TailscaleInContainer) Ping(ip netip.Addr) error { + return t.pool.Retry(func() error { + command := []string{ + "tailscale", "ping", + "--timeout=1s", + "--c=10", + "--until-direct=true", + ip.String(), + } + + result, _, err := dockertestutil.ExecuteCommand( + t.container, + command, + []string{}, + ) + if err != nil { + log.Printf( + "failed to run ping command from %s to %s, err: %s", + t.Hostname, + ip.String(), + err, + ) + return err + } + + if !strings.Contains(result, "pong") && !strings.Contains(result, "is local") { + return backoff.Permanent(errTailscalePingFailed) + } + + return nil + }) + } func createTailscaleBuildOptions(version string) *dockertest.BuildOptions { From 0db608a7b7e2cf979d2529dbfe624b10d93a75c6 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 11:59:28 +0200 Subject: [PATCH 15/23] Add tailscale versions, waiters and helpers for scenario Signed-off-by: Kristoffer Dalby --- integration/scenario.go | 118 +++++++++++++++++++++++++++++++++-- integration/scenario_test.go | 9 ++- 2 files changed, 118 insertions(+), 9 deletions(-) diff --git a/integration/scenario.go b/integration/scenario.go index 2f00daf8..3d664b5f 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -7,6 +7,7 @@ import ( "net/netip" "os" "sync" + "time" "github.com/juanfont/headscale" v1 "github.com/juanfont/headscale/gen/go/headscale/v1" @@ -20,12 +21,32 @@ const scenarioHashLength = 6 var errNoHeadscaleAvailable = errors.New("no headscale available") var errNoNamespaceAvailable = errors.New("no namespace available") +var TailscaleVersions = []string{ + "head", + "unstable", + "1.32.0", + "1.30.2", + "1.28.0", + "1.26.2", + "1.24.2", + "1.22.2", + "1.20.4", + "1.18.2", + "1.16.2", + + // These versions seem to fail when fetching from apt. + // "1.14.6", + // "1.12.4", + // "1.10.2", + // "1.8.7", +} type Namespace struct { Clients map[string]*tsic.TailscaleInContainer createWaitGroup sync.WaitGroup joinWaitGroup sync.WaitGroup + syncWaitGroup sync.WaitGroup } // TODO(kradalby): make control server configurable, test test correctness with @@ -52,6 +73,8 @@ func NewScenario() (*Scenario, error) { return nil, fmt.Errorf("could not connect to docker: %w", err) } + pool.MaxWait = 60 * time.Second + networkName := fmt.Sprintf("hs-%s", hash) if overrideNetworkName := os.Getenv("HEADSCALE_TEST_NETWORK_NAME"); overrideNetworkName != "" { networkName = overrideNetworkName @@ -162,11 +185,16 @@ func (s *Scenario) CreateNamespace(namespace string) error { func (s *Scenario) CreateTailscaleNodesInNamespace( namespace string, - version string, + requestedVersion string, count int, ) error { if ns, ok := s.namespaces[namespace]; ok { for i := 0; i < count; i++ { + version := requestedVersion + if requestedVersion == "all" { + version = TailscaleVersions[i%len(TailscaleVersions)] + } + ns.createWaitGroup.Add(1) go func() { @@ -197,12 +225,12 @@ func (s *Scenario) RunTailscaleUp( for _, client := range ns.Clients { ns.joinWaitGroup.Add(1) - go func() { + go func(c *tsic.TailscaleInContainer) { defer ns.joinWaitGroup.Done() // TODO(kradalby): error handle this - _ = client.Up(loginServer, authKey) - }() + _ = c.Up(loginServer, authKey) + }(client) } ns.joinWaitGroup.Wait() @@ -212,6 +240,75 @@ func (s *Scenario) RunTailscaleUp( return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable) } +func (s *Scenario) CountTailscale() int { + count := 0 + + for _, ns := range s.namespaces { + count += len(ns.Clients) + } + + return count +} + +func (s *Scenario) WaitForTailscaleSync() error { + tsCount := s.CountTailscale() + + for _, ns := range s.namespaces { + for _, client := range ns.Clients { + ns.syncWaitGroup.Add(1) + + go func(c *tsic.TailscaleInContainer) { + defer ns.syncWaitGroup.Done() + + // TODO(kradalby): error handle this + _ = c.WaitForPeers(tsCount) + }(client) + } + ns.syncWaitGroup.Wait() + } + + return nil +} + +// CreateHeadscaleEnv is a conventient method returning a set up Headcale +// test environment with nodes of all versions, joined to the server with X +// namespaces +func (s *Scenario) CreateHeadscaleEnv(namespaces map[string]int) error { + err := s.StartHeadscale() + if err != nil { + return err + } + + err = s.Headscale().WaitForReady() + if err != nil { + return err + } + + for namespaceName, clientCount := range namespaces { + err = s.CreateNamespace(namespaceName) + if err != nil { + return err + } + + err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount) + if err != nil { + return err + } + + key, err := s.CreatePreAuthKey(namespaceName) + if err != nil { + return err + } + + err = s.RunTailscaleUp(namespaceName, s.Headscale().GetEndpoint(), key.GetKey()) + if err != nil { + return err + } + } + + return nil +} + func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) { var ips []netip.Addr if ns, ok := s.namespaces[namespace]; ok { @@ -228,3 +325,16 @@ func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) { return ips, fmt.Errorf("failed to get ips: %w", errNoNamespaceAvailable) } + +func (s *Scenario) GetClients(namespace string) ([]*tsic.TailscaleInContainer, error) { + var clients []*tsic.TailscaleInContainer + if ns, ok := s.namespaces[namespace]; ok { + for _, client := range ns.Clients { + clients = append(clients, client) + } + + return clients, nil + } + + return clients, fmt.Errorf("failed to get clients: %w", errNoNamespaceAvailable) +} diff --git a/integration/scenario_test.go b/integration/scenario_test.go index ff6f3e85..e94e1d93 100644 --- a/integration/scenario_test.go +++ b/integration/scenario_test.go @@ -74,12 +74,9 @@ func TestHeadscale(t *testing.T) { func TestCreateTailscale(t *testing.T) { IntegrationSkip(t) - var scenario *Scenario - var err error - namespace := "only-create-containers" - scenario, err = NewScenario() + scenario, err := NewScenario() if err != nil { t.Errorf("failed to create scenario: %s", err) } @@ -89,7 +86,7 @@ func TestCreateTailscale(t *testing.T) { } t.Run("create-tailscale", func(t *testing.T) { - err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.32.0", 3) + err := scenario.CreateTailscaleNodesInNamespace(namespace, "all", 3) if err != nil { t.Errorf("failed to add tailscale nodes: %s", err) } @@ -97,6 +94,8 @@ func TestCreateTailscale(t *testing.T) { if clients := len(scenario.namespaces[namespace].Clients); clients != 3 { t.Errorf("wrong number of tailscale clients: %d != %d", clients, 3) } + + // TODO(kradalby): Test "all" version logic }) err = scenario.Shutdown() From 39bc6f7e01f9e008f349d408d5fbeef4f62ba390 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 11:59:43 +0200 Subject: [PATCH 16/23] Port PingAll test to new test suite Signed-off-by: Kristoffer Dalby --- integration/general_test.go | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 integration/general_test.go diff --git a/integration/general_test.go b/integration/general_test.go new file mode 100644 index 00000000..0b8db521 --- /dev/null +++ b/integration/general_test.go @@ -0,0 +1,78 @@ +package integration + +import ( + "net/netip" + "testing" + + "github.com/juanfont/headscale/integration/tsic" +) + +func TestPingAll(t *testing.T) { + IntegrationSkip(t) + + scenario, err := NewScenario() + if err != nil { + t.Errorf("failed to create scenario: %s", err) + } + + spec := map[string]int{ + "namespace1": len(TailscaleVersions), + "namespace2": len(TailscaleVersions), + } + + err = scenario.CreateHeadscaleEnv(spec) + if err != nil { + t.Errorf("failed to create headscale environment: %s", err) + } + + var allIps []netip.Addr + var allClients []*tsic.TailscaleInContainer + + for namespace, count := range spec { + ips, err := scenario.GetIPs(namespace) + if err != nil { + t.Errorf("failed to get tailscale ips: %s", err) + } + + if len(ips) != count*2 { + t.Errorf( + "got the wrong amount of tailscale ips, %d != %d", + len(ips), + count*2, + ) + } + + clients, err := scenario.GetClients(namespace) + if err != nil { + t.Errorf("failed to get tailscale clients: %s", err) + } + + allIps = append(allIps, ips...) + allClients = append(allClients, clients...) + } + + scenario.WaitForTailscaleSync() + if err != nil { + t.Errorf("failed wait for tailscale clients to be in sync: %s", err) + } + + success := 0 + + for _, client := range allClients { + for _, ip := range allIps { + err := client.Ping(ip) + if err != nil { + t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname, err) + } else { + success++ + } + } + } + + t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps)) + + err = scenario.Shutdown() + if err != nil { + t.Errorf("failed to tear down scenario: %s", err) + } +} From 2bf50bc20587fe685a8ca7cd5096dcfdd044772e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 12:03:51 +0200 Subject: [PATCH 17/23] Add new integration tests to ci Signed-off-by: Kristoffer Dalby --- .../workflows/test-integration-v2-general.yml | 40 +++++++++++++++++++ Makefile | 10 +++++ 2 files changed, 50 insertions(+) create mode 100644 .github/workflows/test-integration-v2-general.yml diff --git a/.github/workflows/test-integration-v2-general.yml b/.github/workflows/test-integration-v2-general.yml new file mode 100644 index 00000000..b76cc466 --- /dev/null +++ b/.github/workflows/test-integration-v2-general.yml @@ -0,0 +1,40 @@ +name: CI + +on: [pull_request] + +jobs: + integration-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 2 + + - name: Set Swap Space + uses: pierotofy/set-swap-space@master + with: + swap-size-gb: 10 + + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v14.1 + with: + files: | + *.nix + go.* + **/*.go + integration_test/ + config-example.yaml + + - uses: cachix/install-nix-action@v16 + if: steps.changed-files.outputs.any_changed == 'true' + + - name: Run general integration tests + if: steps.changed-files.outputs.any_changed == 'true' + uses: nick-fields/retry@v2 + with: + timeout_minutes: 240 + max_attempts: 5 + retry_on: error + command: nix develop --command -- make test_integration_v2_general diff --git a/Makefile b/Makefile index c5a2d88c..de890d20 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,16 @@ test_integration_oidc: -v /var/run/docker.sock:/var/run/docker.sock golang:1 \ go test -failfast -timeout 30m -count=1 -run IntegrationOIDC ./... +test_integration_v2_general: + docker run \ + -it --rm \ + -v ~/.cache/hs-integration-go:/go \ + --name headscale-test-suite \ + -v $$PWD:$$PWD -w $$PWD \ + -v /var/run/docker.sock:/var/run/docker.sock \ + golang:1 \ + go test ./... -timeout 15m -v + coverprofile_func: go tool cover -func=coverage.out From 4cb7d63e8b7082b95837351bf4d10cf070551da2 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 12:05:17 +0200 Subject: [PATCH 18/23] Set better names for different integration tests Signed-off-by: Kristoffer Dalby --- .github/workflows/test-integration-cli.yml | 2 +- .github/workflows/test-integration-derp.yml | 2 +- .github/workflows/test-integration-general.yml | 2 +- .github/workflows/test-integration-oidc.yml | 2 +- .github/workflows/test-integration-v2-general.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-integration-cli.yml b/.github/workflows/test-integration-cli.yml index 46f48fd2..de288fd9 100644 --- a/.github/workflows/test-integration-cli.yml +++ b/.github/workflows/test-integration-cli.yml @@ -3,7 +3,7 @@ name: CI on: [pull_request] jobs: - integration-test: + integration-test-cli: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/test-integration-derp.yml b/.github/workflows/test-integration-derp.yml index 7fd391bb..88b7cf47 100644 --- a/.github/workflows/test-integration-derp.yml +++ b/.github/workflows/test-integration-derp.yml @@ -3,7 +3,7 @@ name: CI on: [pull_request] jobs: - integration-test: + integration-test-derp: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/test-integration-general.yml b/.github/workflows/test-integration-general.yml index 278548dc..01b31d96 100644 --- a/.github/workflows/test-integration-general.yml +++ b/.github/workflows/test-integration-general.yml @@ -3,7 +3,7 @@ name: CI on: [pull_request] jobs: - integration-test: + integration-test-general: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/test-integration-oidc.yml b/.github/workflows/test-integration-oidc.yml index 0f2005c5..e8afc1bf 100644 --- a/.github/workflows/test-integration-oidc.yml +++ b/.github/workflows/test-integration-oidc.yml @@ -3,7 +3,7 @@ name: CI on: [pull_request] jobs: - integration-test: + integration-test-oidc: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/test-integration-v2-general.yml b/.github/workflows/test-integration-v2-general.yml index b76cc466..fdd98d07 100644 --- a/.github/workflows/test-integration-v2-general.yml +++ b/.github/workflows/test-integration-v2-general.yml @@ -3,7 +3,7 @@ name: CI on: [pull_request] jobs: - integration-test: + integration-test-v2-general: runs-on: ubuntu-latest steps: From 36ad0003a9e10ece2ecc903f6d43cd8ad4e54afd Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 12:09:10 +0200 Subject: [PATCH 19/23] golangci-lint --fix Signed-off-by: Kristoffer Dalby --- integration/hsic/hsic.go | 9 +++++--- integration/scenario.go | 44 +++++++++++++++++++----------------- integration/scenario_test.go | 2 -- integration/tsic/tsic.go | 20 +++++++++------- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/integration/hsic/hsic.go b/integration/hsic/hsic.go index 2b1eedc8..afe9b62c 100644 --- a/integration/hsic/hsic.go +++ b/integration/hsic/hsic.go @@ -15,8 +15,10 @@ import ( "github.com/ory/dockertest/v3" ) -const hsicHashLength = 6 -const dockerContextPath = "../." +const ( + hsicHashLength = 6 + dockerContextPath = "../." +) var errHeadscaleStatusCodeNotOk = errors.New("headscale status code not ok") @@ -32,7 +34,8 @@ type HeadscaleInContainer struct { func New( pool *dockertest.Pool, port int, - network *dockertest.Network) (*HeadscaleInContainer, error) { + network *dockertest.Network, +) (*HeadscaleInContainer, error) { hash, err := headscale.GenerateRandomStringDNSSafe(hsicHashLength) if err != nil { return nil, err diff --git a/integration/scenario.go b/integration/scenario.go index 3d664b5f..36c8a430 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -19,27 +19,29 @@ import ( const scenarioHashLength = 6 -var errNoHeadscaleAvailable = errors.New("no headscale available") -var errNoNamespaceAvailable = errors.New("no namespace available") -var TailscaleVersions = []string{ - "head", - "unstable", - "1.32.0", - "1.30.2", - "1.28.0", - "1.26.2", - "1.24.2", - "1.22.2", - "1.20.4", - "1.18.2", - "1.16.2", +var ( + errNoHeadscaleAvailable = errors.New("no headscale available") + errNoNamespaceAvailable = errors.New("no namespace available") + TailscaleVersions = []string{ + "head", + "unstable", + "1.32.0", + "1.30.2", + "1.28.0", + "1.26.2", + "1.24.2", + "1.22.2", + "1.20.4", + "1.18.2", + "1.16.2", - // These versions seem to fail when fetching from apt. - // "1.14.6", - // "1.12.4", - // "1.10.2", - // "1.8.7", -} + // These versions seem to fail when fetching from apt. + // "1.14.6", + // "1.12.4", + // "1.10.2", + // "1.8.7", + } +) type Namespace struct { Clients map[string]*tsic.TailscaleInContainer @@ -272,7 +274,7 @@ func (s *Scenario) WaitForTailscaleSync() error { // CreateHeadscaleEnv is a conventient method returning a set up Headcale // test environment with nodes of all versions, joined to the server with X -// namespaces +// namespaces. func (s *Scenario) CreateHeadscaleEnv(namespaces map[string]int) error { err := s.StartHeadscale() if err != nil { diff --git a/integration/scenario_test.go b/integration/scenario_test.go index e94e1d93..c1a51f30 100644 --- a/integration/scenario_test.go +++ b/integration/scenario_test.go @@ -44,7 +44,6 @@ func TestHeadscale(t *testing.T) { if err != nil { t.Errorf("headscale failed to become ready: %s", err) } - }) t.Run("create-namespace", func(t *testing.T) { @@ -129,7 +128,6 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) { if err != nil { t.Errorf("headscale failed to become ready: %s", err) } - }) t.Run("create-namespace", func(t *testing.T) { diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 2dfd852c..ef89b229 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -16,11 +16,15 @@ import ( "tailscale.com/ipn/ipnstate" ) -const tsicHashLength = 6 -const dockerContextPath = "../." +const ( + tsicHashLength = 6 + dockerContextPath = "../." +) -var errTailscalePingFailed = errors.New("ping failed") -var errTailscaleNotLoggedIn = errors.New("tailscale not logged in") +var ( + errTailscalePingFailed = errors.New("ping failed") + errTailscaleNotLoggedIn = errors.New("tailscale not logged in") +) type TailscaleInContainer struct { version string @@ -34,7 +38,8 @@ type TailscaleInContainer struct { func New( pool *dockertest.Pool, version string, - network *dockertest.Network) (*TailscaleInContainer, error) { + network *dockertest.Network, +) (*TailscaleInContainer, error) { hash, err := headscale.GenerateRandomStringDNSSafe(tsicHashLength) if err != nil { return nil, err @@ -130,7 +135,7 @@ func (t *TailscaleInContainer) Up( return nil } -// TODO(kradalby): Make cached/lazy +// TODO(kradalby): Make cached/lazy. func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) { ips := make([]netip.Addr, 0) @@ -213,7 +218,7 @@ func (t *TailscaleInContainer) WaitForPeers(expected int) error { }) } -// TODO(kradalby): Make multiping, go routine magic +// TODO(kradalby): Make multiping, go routine magic. func (t *TailscaleInContainer) Ping(ip netip.Addr) error { return t.pool.Retry(func() error { command := []string{ @@ -245,7 +250,6 @@ func (t *TailscaleInContainer) Ping(ip netip.Addr) error { return nil }) - } func createTailscaleBuildOptions(version string) *dockertest.BuildOptions { From 8502a0acda2c429073f8593a0f20e8daf6d46bd9 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 12:09:57 +0200 Subject: [PATCH 20/23] dont request tty Signed-off-by: Kristoffer Dalby --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index de890d20..72925347 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ test_integration_oidc: test_integration_v2_general: docker run \ - -it --rm \ + -t --rm \ -v ~/.cache/hs-integration-go:/go \ --name headscale-test-suite \ -v $$PWD:$$PWD -w $$PWD \ From 12ee9bc02dccbbfe1c8088546441f0ca98b9afe1 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 12:19:43 +0200 Subject: [PATCH 21/23] Fix golangcilint Signed-off-by: Kristoffer Dalby --- integration/general_test.go | 2 +- integration/hsic/hsic.go | 2 +- integration/scenario.go | 49 ++++++++++++++++++++----------------- integration/tsic/tsic.go | 12 ++++----- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/integration/general_test.go b/integration/general_test.go index 0b8db521..2e7689ac 100644 --- a/integration/general_test.go +++ b/integration/general_test.go @@ -51,7 +51,7 @@ func TestPingAll(t *testing.T) { allClients = append(allClients, clients...) } - scenario.WaitForTailscaleSync() + err = scenario.WaitForTailscaleSync() if err != nil { t.Errorf("failed wait for tailscale clients to be in sync: %s", err) } diff --git a/integration/hsic/hsic.go b/integration/hsic/hsic.go index afe9b62c..1790a0a2 100644 --- a/integration/hsic/hsic.go +++ b/integration/hsic/hsic.go @@ -135,7 +135,7 @@ func (t *HeadscaleInContainer) WaitForReady() error { log.Printf("waiting for headscale to be ready at %s", url) return t.pool.Retry(func() error { - resp, err := http.Get(url) + resp, err := http.Get(url) //nolint if err != nil { return fmt.Errorf("headscale is not ready: %w", err) } diff --git a/integration/scenario.go b/integration/scenario.go index 36c8a430..0b8d2022 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -18,6 +18,8 @@ import ( ) const scenarioHashLength = 6 +const maxWait = 60 * time.Second +const headscalePort = 8080 var ( errNoHeadscaleAvailable = errors.New("no headscale available") @@ -75,7 +77,7 @@ func NewScenario() (*Scenario, error) { return nil, fmt.Errorf("could not connect to docker: %w", err) } - pool.MaxWait = 60 * time.Second + pool.MaxWait = maxWait networkName := fmt.Sprintf("hs-%s", hash) if overrideNetworkName := os.Getenv("HEADSCALE_TEST_NETWORK_NAME"); overrideNetworkName != "" { @@ -139,7 +141,7 @@ func (s *Scenario) Shutdown() error { // TODO(kradalby): make port and headscale configurable, multiple instances support? func (s *Scenario) StartHeadscale() error { - headscale, err := hsic.New(s.pool, 8080, s.network) + headscale, err := hsic.New(s.pool, headscalePort, s.network) if err != nil { return fmt.Errorf("failed to create headscale container: %w", err) } @@ -150,6 +152,7 @@ func (s *Scenario) StartHeadscale() error { } func (s *Scenario) Headscale() *hsic.HeadscaleInContainer { + //nolint return s.controlServers["headscale"].(*hsic.HeadscaleInContainer) } @@ -186,33 +189,33 @@ func (s *Scenario) CreateNamespace(namespace string) error { /// Client related stuff func (s *Scenario) CreateTailscaleNodesInNamespace( - namespace string, + namespaceStr string, requestedVersion string, count int, ) error { - if ns, ok := s.namespaces[namespace]; ok { + if namespace, ok := s.namespaces[namespaceStr]; ok { for i := 0; i < count; i++ { version := requestedVersion if requestedVersion == "all" { version = TailscaleVersions[i%len(TailscaleVersions)] } - ns.createWaitGroup.Add(1) + namespace.createWaitGroup.Add(1) go func() { - defer ns.createWaitGroup.Done() + defer namespace.createWaitGroup.Done() // TODO(kradalby): error handle this - ts, err := tsic.New(s.pool, version, s.network) + tsClient, err := tsic.New(s.pool, version, s.network) if err != nil { // return fmt.Errorf("failed to add tailscale node: %w", err) - fmt.Printf("failed to add tailscale node: %s", err) + log.Printf("failed to add tailscale node: %s", err) } - ns.Clients[ts.Hostname] = ts + namespace.Clients[tsClient.Hostname] = tsClient }() } - ns.createWaitGroup.Wait() + namespace.createWaitGroup.Wait() return nil } @@ -221,20 +224,20 @@ func (s *Scenario) CreateTailscaleNodesInNamespace( } func (s *Scenario) RunTailscaleUp( - namespace, loginServer, authKey string, + namespaceStr, loginServer, authKey string, ) error { - if ns, ok := s.namespaces[namespace]; ok { - for _, client := range ns.Clients { - ns.joinWaitGroup.Add(1) + if namespace, ok := s.namespaces[namespaceStr]; ok { + for _, client := range namespace.Clients { + namespace.joinWaitGroup.Add(1) go func(c *tsic.TailscaleInContainer) { - defer ns.joinWaitGroup.Done() + defer namespace.joinWaitGroup.Done() // TODO(kradalby): error handle this _ = c.Up(loginServer, authKey) }(client) } - ns.joinWaitGroup.Wait() + namespace.joinWaitGroup.Wait() return nil } @@ -245,8 +248,8 @@ func (s *Scenario) RunTailscaleUp( func (s *Scenario) CountTailscale() int { count := 0 - for _, ns := range s.namespaces { - count += len(ns.Clients) + for _, namespace := range s.namespaces { + count += len(namespace.Clients) } return count @@ -255,18 +258,18 @@ func (s *Scenario) CountTailscale() int { func (s *Scenario) WaitForTailscaleSync() error { tsCount := s.CountTailscale() - for _, ns := range s.namespaces { - for _, client := range ns.Clients { - ns.syncWaitGroup.Add(1) + for _, namespace := range s.namespaces { + for _, client := range namespace.Clients { + namespace.syncWaitGroup.Add(1) go func(c *tsic.TailscaleInContainer) { - defer ns.syncWaitGroup.Done() + defer namespace.syncWaitGroup.Done() // TODO(kradalby): error handle this _ = c.WaitForPeers(tsCount) }(client) } - ns.syncWaitGroup.Wait() + namespace.syncWaitGroup.Wait() } return nil diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index ef89b229..f3188135 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -22,8 +22,9 @@ const ( ) var ( - errTailscalePingFailed = errors.New("ping failed") - errTailscaleNotLoggedIn = errors.New("tailscale not logged in") + errTailscalePingFailed = errors.New("ping failed") + errTailscaleNotLoggedIn = errors.New("tailscale not logged in") + errTailscaleWrongPeerCount = errors.New("wrong peer count") ) type TailscaleInContainer struct { @@ -207,11 +208,7 @@ func (t *TailscaleInContainer) WaitForPeers(expected int) error { } if peers := status.Peers(); len(peers) != expected { - return fmt.Errorf( - "tailscale client does not have the expected clients: %d out of %d", - len(peers), - expected, - ) + return errTailscaleWrongPeerCount } return nil @@ -241,6 +238,7 @@ func (t *TailscaleInContainer) Ping(ip netip.Addr) error { ip.String(), err, ) + return err } From 6d8c18d4de57247895449e364f693b406660625a Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 12:21:38 +0200 Subject: [PATCH 22/23] Fix golangcilint Signed-off-by: Kristoffer Dalby --- integration/scenario.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/integration/scenario.go b/integration/scenario.go index 0b8d2022..ebe3aff2 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -17,9 +17,11 @@ import ( "github.com/ory/dockertest/v3" ) -const scenarioHashLength = 6 -const maxWait = 60 * time.Second -const headscalePort = 8080 +const ( + scenarioHashLength = 6 + maxWait = 60 * time.Second + headscalePort = 8080 +) var ( errNoHeadscaleAvailable = errors.New("no headscale available") From b2bca2ac815ddf1002d8078f364dab82d733249a Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 18 Oct 2022 16:00:24 +0200 Subject: [PATCH 23/23] Only run integration tests from dir in new tests Signed-off-by: Kristoffer Dalby --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 72925347..431e1076 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ test_integration_v2_general: -t --rm \ -v ~/.cache/hs-integration-go:/go \ --name headscale-test-suite \ - -v $$PWD:$$PWD -w $$PWD \ + -v $$PWD:$$PWD -w $$PWD/integration \ -v /var/run/docker.sock:/var/run/docker.sock \ golang:1 \ go test ./... -timeout 15m -v