mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-21 17:56:39 +00:00
Compare commits
13 Commits
fix/proxy_
...
synology-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cf1644bc4 | ||
|
|
5a1f8f13a2 | ||
|
|
e71059d245 | ||
|
|
91fa2e20a0 | ||
|
|
61034aaf4d | ||
|
|
b8717b8956 | ||
|
|
50201d63c2 | ||
|
|
d11b39282b | ||
|
|
bd58eea8ea | ||
|
|
a5811a2d7d | ||
|
|
a680f80ed9 | ||
|
|
10fbdc2c4a | ||
|
|
1444fbe104 |
2
.github/workflows/golang-test-linux.yml
vendored
2
.github/workflows/golang-test-linux.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
arch: [ '386','amd64' ]
|
arch: [ '386','amd64' ]
|
||||||
store: [ 'jsonfile', 'sqlite' ]
|
store: [ 'jsonfile', 'sqlite', 'postgres']
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
"github.com/netbirdio/management-integrations/integrations"
|
"github.com/netbirdio/management-integrations/integrations"
|
||||||
|
|
||||||
clientProto "github.com/netbirdio/netbird/client/proto"
|
clientProto "github.com/netbirdio/netbird/client/proto"
|
||||||
client "github.com/netbirdio/netbird/client/server"
|
client "github.com/netbirdio/netbird/client/server"
|
||||||
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
||||||
@@ -69,10 +70,11 @@ func startManagement(t *testing.T, config *mgmt.Config) (*grpc.Server, net.Liste
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
s := grpc.NewServer()
|
s := grpc.NewServer()
|
||||||
store, err := mgmt.NewStoreFromJson(config.Datadir, nil)
|
store, cleanUp, err := mgmt.NewTestStoreFromJson(config.Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
peersUpdateManager := mgmt.NewPeersUpdateManager(nil)
|
peersUpdateManager := mgmt.NewPeersUpdateManager(nil)
|
||||||
eventStore := &activity.InMemoryEventStore{}
|
eventStore := &activity.InMemoryEventStore{}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -91,6 +92,9 @@ func (c *ConnectClient) RunOniOS(
|
|||||||
networkChangeListener listener.NetworkChangeListener,
|
networkChangeListener listener.NetworkChangeListener,
|
||||||
dnsManager dns.IosDnsManager,
|
dnsManager dns.IosDnsManager,
|
||||||
) error {
|
) error {
|
||||||
|
// Set GC percent to 5% to reduce memory usage as iOS only allows 50MB of memory for the extension.
|
||||||
|
debug.SetGCPercent(5)
|
||||||
|
|
||||||
mobileDependency := MobileDependency{
|
mobileDependency := MobileDependency{
|
||||||
FileDescriptor: fileDescriptor,
|
FileDescriptor: fileDescriptor,
|
||||||
NetworkChangeListener: networkChangeListener,
|
NetworkChangeListener: networkChangeListener,
|
||||||
@@ -327,6 +331,15 @@ func createEngineConfig(key wgtypes.Key, config *Config, peerConfig *mgmProto.Pe
|
|||||||
engineConf.PreSharedKey = &preSharedKey
|
engineConf.PreSharedKey = &preSharedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port, err := freePort(config.WgPort)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if port != config.WgPort {
|
||||||
|
log.Infof("using %d as wireguard port: %d is in use", port, config.WgPort)
|
||||||
|
}
|
||||||
|
engineConf.WgPort = port
|
||||||
|
|
||||||
return engineConf, nil
|
return engineConf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,3 +389,20 @@ func statusRecorderToSignalConnStateNotifier(statusRecorder *peer.Status) signal
|
|||||||
notifier, _ := sri.(signal.ConnStateNotifier)
|
notifier, _ := sri.(signal.ConnStateNotifier)
|
||||||
return notifier
|
return notifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func freePort(start int) (int, error) {
|
||||||
|
addr := net.UDPAddr{}
|
||||||
|
if start == 0 {
|
||||||
|
start = iface.DefaultWgPort
|
||||||
|
}
|
||||||
|
for x := start; x <= 65535; x++ {
|
||||||
|
addr.Port = x
|
||||||
|
conn, err := net.ListenUDP("udp", &addr)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("no free ports")
|
||||||
|
}
|
||||||
|
|||||||
57
client/internal/connect_test.go
Normal file
57
client/internal/connect_test.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_freePort(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
port int
|
||||||
|
want int
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "available",
|
||||||
|
port: 51820,
|
||||||
|
want: 51820,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "notavailable",
|
||||||
|
port: 51830,
|
||||||
|
want: 51831,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "noports",
|
||||||
|
port: 65535,
|
||||||
|
want: 0,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
|
||||||
|
c1, err := net.ListenUDP("udp", &net.UDPAddr{Port: 51830})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("freePort error = %v", err)
|
||||||
|
}
|
||||||
|
c2, err := net.ListenUDP("udp", &net.UDPAddr{Port: 65535})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("freePort error = %v", err)
|
||||||
|
}
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := freePort(tt.port)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("freePort() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("freePort() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
c1.Close()
|
||||||
|
c2.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -260,13 +259,10 @@ func (u *upstreamResolverBase) disable(err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo test the deactivation logic, it seems to affect the client
|
log.Warnf("Upstream resolving is Disabled for %v", reactivatePeriod)
|
||||||
if runtime.GOOS != "ios" {
|
u.deactivate(err)
|
||||||
log.Warnf("Upstream resolving is Disabled for %v", reactivatePeriod)
|
u.disabled = true
|
||||||
u.deactivate(err)
|
go u.waitUntilResponse()
|
||||||
u.disabled = true
|
|
||||||
go u.waitUntilResponse()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *upstreamResolverBase) testNameserver(server string) error {
|
func (u *upstreamResolverBase) testNameserver(server string) error {
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ type Engine struct {
|
|||||||
// networkSerial is the latest CurrentSerial (state ID) of the network sent by the Management service
|
// networkSerial is the latest CurrentSerial (state ID) of the network sent by the Management service
|
||||||
networkSerial uint64
|
networkSerial uint64
|
||||||
|
|
||||||
networkWatcher *networkmonitor.NetworkWatcher
|
networkMonitor *networkmonitor.NetworkMonitor
|
||||||
|
|
||||||
sshServerFunc func(hostKeyPEM []byte, addr string) (nbssh.Server, error)
|
sshServerFunc func(hostKeyPEM []byte, addr string) (nbssh.Server, error)
|
||||||
sshServer nbssh.Server
|
sshServer nbssh.Server
|
||||||
@@ -150,6 +150,8 @@ type Engine struct {
|
|||||||
signalProbe *Probe
|
signalProbe *Probe
|
||||||
relayProbe *Probe
|
relayProbe *Probe
|
||||||
wgProbe *Probe
|
wgProbe *Probe
|
||||||
|
|
||||||
|
wgConnWorker sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer is an instance of the Connection Peer
|
// Peer is an instance of the Connection Peer
|
||||||
@@ -212,7 +214,6 @@ func NewEngineWithProbes(
|
|||||||
networkSerial: 0,
|
networkSerial: 0,
|
||||||
sshServerFunc: nbssh.DefaultSSHServer,
|
sshServerFunc: nbssh.DefaultSSHServer,
|
||||||
statusRecorder: statusRecorder,
|
statusRecorder: statusRecorder,
|
||||||
networkWatcher: networkmonitor.New(),
|
|
||||||
mgmProbe: mgmProbe,
|
mgmProbe: mgmProbe,
|
||||||
signalProbe: signalProbe,
|
signalProbe: signalProbe,
|
||||||
relayProbe: relayProbe,
|
relayProbe: relayProbe,
|
||||||
@@ -229,7 +230,10 @@ func (e *Engine) Stop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// stopping network monitor first to avoid starting the engine again
|
// stopping network monitor first to avoid starting the engine again
|
||||||
e.networkWatcher.Stop()
|
if e.networkMonitor != nil {
|
||||||
|
e.networkMonitor.Stop()
|
||||||
|
}
|
||||||
|
log.Info("Network monitor: stopped")
|
||||||
|
|
||||||
err := e.removeAllPeers()
|
err := e.removeAllPeers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -243,6 +247,7 @@ func (e *Engine) Stop() error {
|
|||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
|
||||||
e.close()
|
e.close()
|
||||||
|
e.wgConnWorker.Wait()
|
||||||
log.Infof("stopped Netbird Engine")
|
log.Infof("stopped Netbird Engine")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -259,7 +264,7 @@ func (e *Engine) Start() error {
|
|||||||
}
|
}
|
||||||
e.ctx, e.cancel = context.WithCancel(e.clientCtx)
|
e.ctx, e.cancel = context.WithCancel(e.clientCtx)
|
||||||
|
|
||||||
e.wgProxyFactory = wgproxy.NewFactory(e.clientCtx, e.config.WgPort)
|
e.wgProxyFactory = wgproxy.NewFactory(e.ctx, e.config.WgPort)
|
||||||
|
|
||||||
wgIface, err := e.newWgIface()
|
wgIface, err := e.newWgIface()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -344,20 +349,8 @@ func (e *Engine) Start() error {
|
|||||||
e.receiveManagementEvents()
|
e.receiveManagementEvents()
|
||||||
e.receiveProbeEvents()
|
e.receiveProbeEvents()
|
||||||
|
|
||||||
if e.config.NetworkMonitor {
|
// starting network monitor at the very last to avoid disruptions
|
||||||
// starting network monitor at the very last to avoid disruptions
|
e.startNetworkMonitor()
|
||||||
go e.networkWatcher.Start(e.ctx, func() {
|
|
||||||
log.Infof("Network monitor detected network change, restarting engine")
|
|
||||||
if err := e.Stop(); err != nil {
|
|
||||||
log.Errorf("Failed to stop engine: %v", err)
|
|
||||||
}
|
|
||||||
if err := e.Start(); err != nil {
|
|
||||||
log.Errorf("Failed to start engine: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
log.Infof("Network monitor is disabled, not starting")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -879,18 +872,25 @@ func (e *Engine) addNewPeer(peerConfig *mgmProto.RemotePeerConfig) error {
|
|||||||
log.Warnf("error adding peer %s to status recorder, got error: %v", peerKey, err)
|
log.Warnf("error adding peer %s to status recorder, got error: %v", peerKey, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.wgConnWorker.Add(1)
|
||||||
go e.connWorker(conn, peerKey)
|
go e.connWorker(conn, peerKey)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) connWorker(conn *peer.Conn, peerKey string) {
|
func (e *Engine) connWorker(conn *peer.Conn, peerKey string) {
|
||||||
|
defer e.wgConnWorker.Done()
|
||||||
for {
|
for {
|
||||||
|
|
||||||
// randomize starting time a bit
|
// randomize starting time a bit
|
||||||
min := 500
|
min := 500
|
||||||
max := 2000
|
max := 2000
|
||||||
time.Sleep(time.Duration(rand.Intn(max-min)+min) * time.Millisecond)
|
duration := time.Duration(rand.Intn(max-min)+min) * time.Millisecond
|
||||||
|
select {
|
||||||
|
case <-e.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-time.After(duration):
|
||||||
|
}
|
||||||
|
|
||||||
// if peer has been removed -> give up
|
// if peer has been removed -> give up
|
||||||
if !e.peerExists(peerKey) {
|
if !e.peerExists(peerKey) {
|
||||||
@@ -1399,3 +1399,26 @@ func (e *Engine) probeSTUNs() []relay.ProbeResult {
|
|||||||
func (e *Engine) probeTURNs() []relay.ProbeResult {
|
func (e *Engine) probeTURNs() []relay.ProbeResult {
|
||||||
return relay.ProbeAll(e.ctx, relay.ProbeTURN, e.TURNs)
|
return relay.ProbeAll(e.ctx, relay.ProbeTURN, e.TURNs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Engine) startNetworkMonitor() {
|
||||||
|
if !e.config.NetworkMonitor {
|
||||||
|
log.Infof("Network monitor is disabled, not starting")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.networkMonitor = networkmonitor.New()
|
||||||
|
go func() {
|
||||||
|
err := e.networkMonitor.Start(e.ctx, func() {
|
||||||
|
log.Infof("Network monitor detected network change, restarting engine")
|
||||||
|
if err := e.Stop(); err != nil {
|
||||||
|
log.Errorf("Failed to stop engine: %v", err)
|
||||||
|
}
|
||||||
|
if err := e.Start(); err != nil {
|
||||||
|
log.Errorf("Failed to start engine: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if err != nil && !errors.Is(err, networkmonitor.ErrStopped) {
|
||||||
|
log.Errorf("Network monitor: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ func TestEngine_UpdateNetworkMap(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
engine.udpMux = bind.NewUniversalUDPMuxDefault(bind.UniversalUDPMuxParams{UDPConn: conn})
|
engine.udpMux = bind.NewUniversalUDPMuxDefault(bind.UniversalUDPMuxParams{UDPConn: conn})
|
||||||
|
engine.ctx = ctx
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
@@ -408,6 +409,7 @@ func TestEngine_Sync(t *testing.T) {
|
|||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
||||||
|
engine.ctx = ctx
|
||||||
|
|
||||||
engine.dnsServer = &dns.MockServer{
|
engine.dnsServer = &dns.MockServer{
|
||||||
UpdateDNSServerFunc: func(serial uint64, update nbdns.Config) error { return nil },
|
UpdateDNSServerFunc: func(serial uint64, update nbdns.Config) error { return nil },
|
||||||
@@ -566,6 +568,7 @@ func TestEngine_UpdateNetworkMapWithRoutes(t *testing.T) {
|
|||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
||||||
|
engine.ctx = ctx
|
||||||
newNet, err := stdnet.NewNet()
|
newNet, err := stdnet.NewNet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -735,6 +738,8 @@ func TestEngine_UpdateNetworkMapWithDNSUpdate(t *testing.T) {
|
|||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
WgPort: 33100,
|
WgPort: 33100,
|
||||||
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
|
||||||
|
engine.ctx = ctx
|
||||||
|
|
||||||
newNet, err := stdnet.NewNet()
|
newNet, err := stdnet.NewNet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -1003,7 +1008,9 @@ func createEngine(ctx context.Context, cancel context.CancelFunc, setupKey strin
|
|||||||
WgPort: wgPort,
|
WgPort: wgPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewEngine(ctx, cancel, signalClient, mgmtClient, conf, MobileDependency{}, peer.NewRecorder("https://mgm")), nil
|
e, err := NewEngine(ctx, cancel, signalClient, mgmtClient, conf, MobileDependency{}, peer.NewRecorder("https://mgm")), nil
|
||||||
|
e.ctx = ctx
|
||||||
|
return e, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func startSignal() (*grpc.Server, string, error) {
|
func startSignal() (*grpc.Server, string, error) {
|
||||||
@@ -1042,7 +1049,7 @@ func startManagement(dataDir string) (*grpc.Server, string, error) {
|
|||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
s := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp))
|
s := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp))
|
||||||
store, err := server.NewStoreFromJson(config.Datadir, nil)
|
store, _, err := server.NewTestStoreFromJson(config.Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,20 @@ package networkmonitor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NetworkWatcher watches for changes in network configuration.
|
var ErrStopped = errors.New("monitor has been stopped")
|
||||||
type NetworkWatcher struct {
|
|
||||||
|
// NetworkMonitor watches for changes in network configuration.
|
||||||
|
type NetworkMonitor struct {
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
wg sync.WaitGroup
|
||||||
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new network monitor.
|
// New creates a new network monitor.
|
||||||
func New() *NetworkWatcher {
|
func New() *NetworkMonitor {
|
||||||
return &NetworkWatcher{}
|
return &NetworkMonitor{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func checkChange(ctx context.Context, nexthopv4 netip.Addr, intfv4 *net.Interfac
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ErrStopped
|
||||||
default:
|
default:
|
||||||
buf := make([]byte, 2048)
|
buf := make([]byte, 2048)
|
||||||
n, err := unix.Read(fd, buf)
|
n, err := unix.Read(fd, buf)
|
||||||
@@ -63,7 +63,7 @@ func checkChange(ctx context.Context, nexthopv4 netip.Addr, intfv4 *net.Interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Network monitor: monitored interface (%s) is down.", ifinfo.Name)
|
log.Infof("Network monitor: monitored interface (%s) is down.", ifinfo.Name)
|
||||||
callback()
|
go callback()
|
||||||
|
|
||||||
// handle route changes
|
// handle route changes
|
||||||
case unix.RTM_ADD, syscall.RTM_DELETE:
|
case unix.RTM_ADD, syscall.RTM_DELETE:
|
||||||
@@ -84,11 +84,11 @@ func checkChange(ctx context.Context, nexthopv4 netip.Addr, intfv4 *net.Interfac
|
|||||||
switch msg.Type {
|
switch msg.Type {
|
||||||
case unix.RTM_ADD:
|
case unix.RTM_ADD:
|
||||||
log.Infof("Network monitor: default route changed: via %s, interface %s", route.Gw, intf)
|
log.Infof("Network monitor: default route changed: via %s, interface %s", route.Gw, intf)
|
||||||
callback()
|
go callback()
|
||||||
case unix.RTM_DELETE:
|
case unix.RTM_DELETE:
|
||||||
if intfv4 != nil && route.Gw.Compare(nexthopv4) == 0 || intfv6 != nil && route.Gw.Compare(nexthopv6) == 0 {
|
if intfv4 != nil && route.Gw.Compare(nexthopv4) == 0 || intfv6 != nil && route.Gw.Compare(nexthopv6) == 0 {
|
||||||
log.Infof("Network monitor: default route removed: via %s, interface %s", route.Gw, intf)
|
log.Infof("Network monitor: default route removed: via %s, interface %s", route.Gw, intf)
|
||||||
callback()
|
go callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package networkmonitor
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
@@ -15,20 +16,18 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/internal/routemanager"
|
"github.com/netbirdio/netbird/client/internal/routemanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Start begins watching for network changes and calls the callback function and stops when a change is detected.
|
// Start begins monitoring network changes. When a change is detected, it calls the callback asynchronously and returns.
|
||||||
func (nw *NetworkWatcher) Start(ctx context.Context, callback func()) {
|
func (nw *NetworkMonitor) Start(ctx context.Context, callback func()) (err error) {
|
||||||
if nw.cancel != nil {
|
|
||||||
log.Warn("Network monitor: already running, stopping previous watcher")
|
|
||||||
nw.Stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
log.Info("Network monitor: not starting, context is already cancelled")
|
return ctx.Err()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nw.mu.Lock()
|
||||||
ctx, nw.cancel = context.WithCancel(ctx)
|
ctx, nw.cancel = context.WithCancel(ctx)
|
||||||
defer nw.Stop()
|
nw.mu.Unlock()
|
||||||
|
|
||||||
|
nw.wg.Add(1)
|
||||||
|
defer nw.wg.Done()
|
||||||
|
|
||||||
var nexthop4, nexthop6 netip.Addr
|
var nexthop4, nexthop6 netip.Addr
|
||||||
var intf4, intf6 *net.Interface
|
var intf4, intf6 *net.Interface
|
||||||
@@ -56,27 +55,30 @@ func (nw *NetworkWatcher) Start(ctx context.Context, callback func()) {
|
|||||||
expBackOff := backoff.WithContext(backoff.NewExponentialBackOff(), ctx)
|
expBackOff := backoff.WithContext(backoff.NewExponentialBackOff(), ctx)
|
||||||
|
|
||||||
if err := backoff.Retry(operation, expBackOff); err != nil {
|
if err := backoff.Retry(operation, expBackOff); err != nil {
|
||||||
log.Errorf("Network monitor: failed to get default next hops: %v", err)
|
return fmt.Errorf("failed to get default next hops: %w", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// recover in case sys ops panic
|
// recover in case sys ops panic
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
log.Errorf("Network monitor: panic occurred: %v, stack trace: %s", r, string(debug.Stack()))
|
err = fmt.Errorf("panic occurred: %v, stack trace: %s", r, string(debug.Stack()))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := checkChange(ctx, nexthop4, intf4, nexthop6, intf6, callback); err != nil && !errors.Is(err, context.Canceled) {
|
if err := checkChange(ctx, nexthop4, intf4, nexthop6, intf6, callback); err != nil {
|
||||||
log.Errorf("Network monitor: failed to start: %v", err)
|
return fmt.Errorf("check change: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the network monitor.
|
// Stop stops the network monitor.
|
||||||
func (nw *NetworkWatcher) Stop() {
|
func (nw *NetworkMonitor) Stop() {
|
||||||
|
nw.mu.Lock()
|
||||||
|
defer nw.mu.Unlock()
|
||||||
|
|
||||||
if nw.cancel != nil {
|
if nw.cancel != nil {
|
||||||
nw.cancel()
|
nw.cancel()
|
||||||
nw.cancel = nil
|
nw.wg.Wait()
|
||||||
log.Info("Network monitor: stopped")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func checkChange(ctx context.Context, nexthopv4 netip.Addr, intfv4 *net.Interfac
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ErrStopped
|
||||||
|
|
||||||
// handle interface state changes
|
// handle interface state changes
|
||||||
case update := <-linkChan:
|
case update := <-linkChan:
|
||||||
@@ -47,12 +47,12 @@ func checkChange(ctx context.Context, nexthopv4 netip.Addr, intfv4 *net.Interfac
|
|||||||
switch update.Header.Type {
|
switch update.Header.Type {
|
||||||
case syscall.RTM_DELLINK:
|
case syscall.RTM_DELLINK:
|
||||||
log.Infof("Network monitor: monitored interface (%s) is gone", update.Link.Attrs().Name)
|
log.Infof("Network monitor: monitored interface (%s) is gone", update.Link.Attrs().Name)
|
||||||
callback()
|
go callback()
|
||||||
return nil
|
return nil
|
||||||
case syscall.RTM_NEWLINK:
|
case syscall.RTM_NEWLINK:
|
||||||
if (update.IfInfomsg.Flags&syscall.IFF_RUNNING) == 0 && update.Link.Attrs().OperState == netlink.OperDown {
|
if (update.IfInfomsg.Flags&syscall.IFF_RUNNING) == 0 && update.Link.Attrs().OperState == netlink.OperDown {
|
||||||
log.Infof("Network monitor: monitored interface (%s) is down.", update.Link.Attrs().Name)
|
log.Infof("Network monitor: monitored interface (%s) is down.", update.Link.Attrs().Name)
|
||||||
callback()
|
go callback()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,12 +67,12 @@ func checkChange(ctx context.Context, nexthopv4 netip.Addr, intfv4 *net.Interfac
|
|||||||
// triggered on added/replaced routes
|
// triggered on added/replaced routes
|
||||||
case syscall.RTM_NEWROUTE:
|
case syscall.RTM_NEWROUTE:
|
||||||
log.Infof("Network monitor: default route changed: via %s, interface %d", route.Gw, route.LinkIndex)
|
log.Infof("Network monitor: default route changed: via %s, interface %d", route.Gw, route.LinkIndex)
|
||||||
callback()
|
go callback()
|
||||||
return nil
|
return nil
|
||||||
case syscall.RTM_DELROUTE:
|
case syscall.RTM_DELROUTE:
|
||||||
if intfv4 != nil && route.Gw.Equal(nexthopv4.AsSlice()) || intfv6 != nil && route.Gw.Equal(nexthop6.AsSlice()) {
|
if intfv4 != nil && route.Gw.Equal(nexthopv4.AsSlice()) || intfv6 != nil && route.Gw.Equal(nexthop6.AsSlice()) {
|
||||||
log.Infof("Network monitor: default route removed: via %s, interface %d", route.Gw, route.LinkIndex)
|
log.Infof("Network monitor: default route removed: via %s, interface %d", route.Gw, route.LinkIndex)
|
||||||
callback()
|
go callback()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ package networkmonitor
|
|||||||
|
|
||||||
import "context"
|
import "context"
|
||||||
|
|
||||||
func (nw *NetworkWatcher) Start(context.Context, func()) {
|
func (nw *NetworkMonitor) Start(context.Context, func()) error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nw *NetworkWatcher) Stop() {
|
func (nw *NetworkMonitor) Stop() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ func checkChange(ctx context.Context, nexthopv4 netip.Addr, intfv4 *net.Interfac
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ErrStopped
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if changed(nexthopv4, intfv4, neighborv4, nexthopv6, intfv6, neighborv6) {
|
if changed(nexthopv4, intfv4, neighborv4, nexthopv6, intfv6, neighborv6) {
|
||||||
callback()
|
go callback()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -487,6 +487,10 @@ func (conn *Conn) configureConnection(remoteConn net.Conn, remoteWgPort int, rem
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "ios" {
|
||||||
|
runtime.GC()
|
||||||
|
}
|
||||||
|
|
||||||
if conn.onConnected != nil {
|
if conn.onConnected != nil {
|
||||||
conn.onConnected(conn.config.Key, remoteRosenpassPubKey, ipNet.IP.String(), remoteRosenpassAddr)
|
conn.onConnected(conn.config.Key, remoteRosenpassPubKey, ipNet.IP.String(), remoteRosenpassAddr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,11 +43,6 @@ func routeCmd(action string, prefix netip.Prefix, nexthop netip.Addr, intf *net.
|
|||||||
}
|
}
|
||||||
if prefix.Addr().Is6() {
|
if prefix.Addr().Is6() {
|
||||||
inet = "-inet6"
|
inet = "-inet6"
|
||||||
// Special case for IPv6 split default route, pointing to the wg interface fails
|
|
||||||
// TODO: Remove once we have IPv6 support on the interface
|
|
||||||
if prefix.Bits() == 1 {
|
|
||||||
intf = &net.Interface{Name: "lo0"}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := []string{"-n", action, inet, network}
|
args := []string{"-n", action, inet, network}
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ func (p *WGEBPFProxy) AddTurnConn(turnConn net.Conn) (net.Addr, error) {
|
|||||||
|
|
||||||
// CloseConn doing nothing because this type of proxy implementation does not store the connection
|
// CloseConn doing nothing because this type of proxy implementation does not store the connection
|
||||||
func (p *WGEBPFProxy) CloseConn() error {
|
func (p *WGEBPFProxy) CloseConn() error {
|
||||||
p.cancel()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,10 +106,11 @@ func startManagement(t *testing.T, signalAddr string, counter *int) (*grpc.Serve
|
|||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
s := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp))
|
s := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp))
|
||||||
store, err := server.NewStoreFromJson(config.Datadir, nil)
|
store, cleanUp, err := server.NewTestStoreFromJson(config.Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
peersUpdateManager := server.NewPeersUpdateManager(nil)
|
peersUpdateManager := server.NewPeersUpdateManager(nil)
|
||||||
eventStore := &activity.InMemoryEventStore{}
|
eventStore := &activity.InMemoryEventStore{}
|
||||||
|
|||||||
@@ -399,6 +399,7 @@ func (s *serviceClient) updateStatus() error {
|
|||||||
status, err := conn.Status(s.ctx, &proto.StatusRequest{})
|
status, err := conn.Status(s.ctx, &proto.StatusRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("get service status: %v", err)
|
log.Errorf("get service status: %v", err)
|
||||||
|
s.setDisconnectedStatus()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,17 +427,7 @@ func (s *serviceClient) updateStatus() error {
|
|||||||
s.mRoutes.Enable()
|
s.mRoutes.Enable()
|
||||||
systrayIconState = true
|
systrayIconState = true
|
||||||
} else if status.Status != string(internal.StatusConnected) && s.mUp.Disabled() {
|
} else if status.Status != string(internal.StatusConnected) && s.mUp.Disabled() {
|
||||||
s.connected = false
|
s.setDisconnectedStatus()
|
||||||
if s.isUpdateIconActive {
|
|
||||||
systray.SetIcon(s.icUpdateDisconnected)
|
|
||||||
} else {
|
|
||||||
systray.SetIcon(s.icDisconnected)
|
|
||||||
}
|
|
||||||
systray.SetTooltip("NetBird (Disconnected)")
|
|
||||||
s.mStatus.SetTitle("Disconnected")
|
|
||||||
s.mDown.Disable()
|
|
||||||
s.mUp.Enable()
|
|
||||||
s.mRoutes.Disable()
|
|
||||||
systrayIconState = false
|
systrayIconState = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,6 +472,20 @@ func (s *serviceClient) updateStatus() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) setDisconnectedStatus() {
|
||||||
|
s.connected = false
|
||||||
|
if s.isUpdateIconActive {
|
||||||
|
systray.SetIcon(s.icUpdateDisconnected)
|
||||||
|
} else {
|
||||||
|
systray.SetIcon(s.icDisconnected)
|
||||||
|
}
|
||||||
|
systray.SetTooltip("NetBird (Disconnected)")
|
||||||
|
s.mStatus.SetTitle("Disconnected")
|
||||||
|
s.mDown.Disable()
|
||||||
|
s.mUp.Enable()
|
||||||
|
s.mRoutes.Disable()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *serviceClient) onTrayReady() {
|
func (s *serviceClient) onTrayReady() {
|
||||||
systray.SetIcon(s.icDisconnected)
|
systray.SetIcon(s.icDisconnected)
|
||||||
systray.SetTooltip("NetBird")
|
systray.SetTooltip("NetBird")
|
||||||
|
|||||||
36
go.mod
36
go.mod
@@ -6,7 +6,7 @@ toolchain go1.21.0
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
cunicu.li/go-rosenpass v0.4.0
|
cunicu.li/go-rosenpass v0.4.0
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3
|
github.com/cenkalti/backoff/v4 v4.2.0
|
||||||
github.com/cloudflare/circl v1.3.3 // indirect
|
github.com/cloudflare/circl v1.3.3 // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
github.com/golang/protobuf v1.5.3
|
github.com/golang/protobuf v1.5.3
|
||||||
@@ -54,7 +54,7 @@ require (
|
|||||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2
|
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2
|
||||||
github.com/hashicorp/go-version v1.6.0
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/libp2p/go-netroute v0.2.1
|
github.com/libp2p/go-netroute v0.2.1
|
||||||
github.com/magiconair/properties v1.8.5
|
github.com/magiconair/properties v1.8.7
|
||||||
github.com/mattn/go-sqlite3 v1.14.19
|
github.com/mattn/go-sqlite3 v1.14.19
|
||||||
github.com/mdlayher/socket v0.4.1
|
github.com/mdlayher/socket v0.4.1
|
||||||
github.com/miekg/dns v1.1.43
|
github.com/miekg/dns v1.1.43
|
||||||
@@ -72,6 +72,8 @@ require (
|
|||||||
github.com/rs/xid v1.3.0
|
github.com/rs/xid v1.3.0
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
|
github.com/testcontainers/testcontainers-go v0.20.0
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/postgres v0.20.0
|
||||||
github.com/things-go/go-socks5 v0.0.4
|
github.com/things-go/go-socks5 v0.0.4
|
||||||
github.com/yusufpapurcu/wmi v1.2.3
|
github.com/yusufpapurcu/wmi v1.2.3
|
||||||
github.com/zcalusic/sysinfo v1.0.2
|
github.com/zcalusic/sysinfo v1.0.2
|
||||||
@@ -88,22 +90,31 @@ require (
|
|||||||
golang.org/x/term v0.18.0
|
golang.org/x/term v0.18.0
|
||||||
google.golang.org/api v0.126.0
|
google.golang.org/api v0.126.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
gorm.io/driver/postgres v1.5.7
|
||||||
gorm.io/driver/sqlite v1.5.3
|
gorm.io/driver/sqlite v1.5.3
|
||||||
gorm.io/gorm v1.25.4
|
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute v1.19.3 // indirect
|
cloud.google.com/go/compute v1.19.3 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||||
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/XiaoMi/pegasus-go-client v0.0.0-20210427083443-f3b6b08bc4c2 // indirect
|
github.com/XiaoMi/pegasus-go-client v0.0.0-20210427083443-f3b6b08bc4c2 // indirect
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/containerd/containerd v1.6.19 // indirect
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/docker/distribution v2.8.1+incompatible // indirect
|
||||||
|
github.com/docker/docker v23.0.5+incompatible // indirect
|
||||||
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 // indirect
|
github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 // indirect
|
||||||
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect
|
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect
|
||||||
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect
|
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect
|
||||||
@@ -118,29 +129,43 @@ require (
|
|||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
github.com/go-stack/stack v1.8.0 // indirect
|
github.com/go-stack/stack v1.8.0 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect
|
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/btree v1.0.1 // indirect
|
github.com/google/btree v1.0.1 // indirect
|
||||||
github.com/google/s2a-go v0.1.4 // indirect
|
github.com/google/s2a-go v0.1.4 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.10.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.10.0 // indirect
|
||||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||||
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||||
|
github.com/klauspost/compress v1.15.9 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||||
|
github.com/moby/patternmatcher v0.5.0 // indirect
|
||||||
|
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||||
|
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f // indirect
|
||||||
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/nxadm/tail v1.4.8 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
|
||||||
|
github.com/opencontainers/runc v1.1.5 // indirect
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
|
||||||
github.com/pegasus-kv/thrift v0.13.0 // indirect
|
github.com/pegasus-kv/thrift v0.13.0 // indirect
|
||||||
github.com/pion/dtls/v2 v2.2.10 // indirect
|
github.com/pion/dtls/v2 v2.2.10 // indirect
|
||||||
github.com/pion/mdns v0.0.12 // indirect
|
github.com/pion/mdns v0.0.12 // indirect
|
||||||
github.com/pion/randutil v0.1.0 // indirect
|
github.com/pion/randutil v0.1.0 // indirect
|
||||||
github.com/pion/transport/v2 v2.2.4 // indirect
|
github.com/pion/transport/v2 v2.2.4 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
github.com/prometheus/common v0.37.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
@@ -154,12 +179,13 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk v1.11.1 // indirect
|
go.opentelemetry.io/otel/sdk v1.11.1 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.11.1 // indirect
|
go.opentelemetry.io/otel/trace v1.11.1 // indirect
|
||||||
golang.org/x/image v0.10.0 // indirect
|
golang.org/x/image v0.10.0 // indirect
|
||||||
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
|
golang.org/x/tools v0.13.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect
|
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect
|
||||||
|
|||||||
105
go.sum
105
go.sum
@@ -40,12 +40,18 @@ cunicu.li/go-rosenpass v0.4.0/go.mod h1:MPbjH9nxV4l3vEagKVdFNwHOketqgS5/To1VYJpl
|
|||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
fyne.io/fyne/v2 v2.1.4 h1:bt1+28++kAzRzPB0GM2EuSV4cnl8rXNX4cjfd8G06Rc=
|
fyne.io/fyne/v2 v2.1.4 h1:bt1+28++kAzRzPB0GM2EuSV4cnl8rXNX4cjfd8G06Rc=
|
||||||
fyne.io/fyne/v2 v2.1.4/go.mod h1:p+E/Dh+wPW8JwR2DVcsZ9iXgR9ZKde80+Y+40Is54AQ=
|
fyne.io/fyne/v2 v2.1.4/go.mod h1:p+E/Dh+wPW8JwR2DVcsZ9iXgR9ZKde80+Y+40Is54AQ=
|
||||||
|
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.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
|
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
|
||||||
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
|
github.com/Microsoft/hcsshim v0.9.7 h1:mKNHW/Xvv1aFH87Jb6ERDzXTJTLPlmzfZ28VBFD/bfg=
|
||||||
|
github.com/Microsoft/hcsshim v0.9.7/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
@@ -73,16 +79,18 @@ github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQ
|
|||||||
github.com/c-robinson/iplib v1.0.3 h1:NG0UF0GoEsrC1/vyfX1Lx2Ss7CySWl3KqqXh3q4DdPU=
|
github.com/c-robinson/iplib v1.0.3 h1:NG0UF0GoEsrC1/vyfX1Lx2Ss7CySWl3KqqXh3q4DdPU=
|
||||||
github.com/c-robinson/iplib v1.0.3/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
|
github.com/c-robinson/iplib v1.0.3/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
|
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||||
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
|
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
|
||||||
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
|
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
@@ -92,16 +100,25 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
|
|||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||||
|
github.com/containerd/containerd v1.6.19 h1:F0qgQPrG0P2JPgwpxWxYavrVeXAG0ezUIB9Z/4FTUAU=
|
||||||
|
github.com/containerd/containerd v1.6.19/go.mod h1:HZCDMn4v/Xl2579/MvtOC2M206i+JJ6VxFWU/NetrGY=
|
||||||
|
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
|
||||||
|
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
||||||
github.com/coocood/freecache v1.2.1 h1:/v1CqMq45NFH9mp/Pt142reundeBM0dVUD3osQBeu/U=
|
github.com/coocood/freecache v1.2.1 h1:/v1CqMq45NFH9mp/Pt142reundeBM0dVUD3osQBeu/U=
|
||||||
github.com/coocood/freecache v1.2.1/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk=
|
github.com/coocood/freecache v1.2.1/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk=
|
||||||
github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8=
|
github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8=
|
||||||
github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
github.com/cunicu/circl v0.0.0-20230801113412-fec58fc7b5f6 h1:/DS5cDX3FJdl+XaN2D7XAwFpuanTxnp52DBLZAaJKx0=
|
github.com/cunicu/circl v0.0.0-20230801113412-fec58fc7b5f6 h1:/DS5cDX3FJdl+XaN2D7XAwFpuanTxnp52DBLZAaJKx0=
|
||||||
github.com/cunicu/circl v0.0.0-20230801113412-fec58fc7b5f6/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw=
|
github.com/cunicu/circl v0.0.0-20230801113412-fec58fc7b5f6/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@@ -111,6 +128,15 @@ github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkz
|
|||||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||||
|
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
github.com/docker/docker v23.0.5+incompatible h1:DaxtlTJjFSnLOXVNUBU1+6kXGz2lpDoEAH6QoxaSg8k=
|
||||||
|
github.com/docker/docker v23.0.5+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/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/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
@@ -127,6 +153,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
|
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||||
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
|
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
|
||||||
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA=
|
github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA=
|
||||||
@@ -188,10 +215,13 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
|||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=
|
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=
|
||||||
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
|
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
@@ -290,8 +320,9 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
|
|||||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.2-0.20240212192251-757544f21357 h1:Fkzd8ktnpOR9h47SXHe2AYPwelXLH2GjGsjlAloiWfo=
|
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.2-0.20240212192251-757544f21357 h1:Fkzd8ktnpOR9h47SXHe2AYPwelXLH2GjGsjlAloiWfo=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.2-0.20240212192251-757544f21357/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4=
|
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.2-0.20240212192251-757544f21357/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 h1:ET4pqyjiGmY09R5y+rSd70J2w45CtbWDNvGqWp/R3Ng=
|
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 h1:ET4pqyjiGmY09R5y+rSd70J2w45CtbWDNvGqWp/R3Ng=
|
||||||
@@ -305,8 +336,16 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
|||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
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/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
|
||||||
|
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
|
||||||
github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
|
github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
@@ -332,7 +371,10 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
|
|||||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||||
|
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
@@ -345,11 +387,13 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
|
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
|
||||||
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
|
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
|
||||||
github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
|
github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
|
||||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
|
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
|
||||||
@@ -369,12 +413,22 @@ github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE9
|
|||||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||||
|
github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
|
||||||
|
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||||
|
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
||||||
|
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||||
|
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||||
|
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f h1:J/7hjLaHLD7epG0m6TBMGmp4NQ+ibBYLfeyJWdAIFLA=
|
||||||
|
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f/go.mod h1:15ce4BGCFxt7I5NQKT+HV0yEDxmf6fSysfEDiVo3zFM=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
|
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
@@ -414,6 +468,14 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
||||||
|
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||||
|
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
|
||||||
|
github.com/opencontainers/runc v1.1.5/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/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||||
@@ -422,6 +484,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
|
|||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/pegasus-kv/thrift v0.13.0 h1:4ESwaNoHImfbHa9RUGJiJZ4hrxorihZHk5aarYwY8d4=
|
github.com/pegasus-kv/thrift v0.13.0 h1:4ESwaNoHImfbHa9RUGJiJZ4hrxorihZHk5aarYwY8d4=
|
||||||
github.com/pegasus-kv/thrift v0.13.0/go.mod h1:Gl9NT/WHG6ABm6NsrbfE8LiJN0sAyneCrvB4qN4NPqQ=
|
github.com/pegasus-kv/thrift v0.13.0/go.mod h1:Gl9NT/WHG6ABm6NsrbfE8LiJN0sAyneCrvB4qN4NPqQ=
|
||||||
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
|
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||||
@@ -485,10 +548,12 @@ github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
|||||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
|
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 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
||||||
@@ -526,13 +591,21 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
|||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
|
github.com/testcontainers/testcontainers-go v0.20.0 h1:ASrcJee7vcWNw43yUgL2n8KA5IOywrF031GawlrkVkE=
|
||||||
|
github.com/testcontainers/testcontainers-go v0.20.0/go.mod h1:zb+NOlCQBkZ7RQp4QI+YMIHyO2CQ/qsXzNF5eLJ24SY=
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/postgres v0.20.0 h1:skGd0Tv6USw6c9aJwea+Mb2WonLqf6N5npbS5WxbGQ0=
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/postgres v0.20.0/go.mod h1:wtdaiIzG+DlZ/0DbNvrJ89TT7RUer8ZnRcv4y+xHcU8=
|
||||||
github.com/things-go/go-socks5 v0.0.4 h1:jMQjIc+qhD4z9cITOMnBiwo9dDmpGuXmBlkRFrl/qD0=
|
github.com/things-go/go-socks5 v0.0.4 h1:jMQjIc+qhD4z9cITOMnBiwo9dDmpGuXmBlkRFrl/qD0=
|
||||||
github.com/things-go/go-socks5 v0.0.4/go.mod h1:sh4K6WHrmHZpjxLTCHyYtXYH8OUuD+yZun41NomR1IQ=
|
github.com/things-go/go-socks5 v0.0.4/go.mod h1:sh4K6WHrmHZpjxLTCHyYtXYH8OUuD+yZun41NomR1IQ=
|
||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 h1:8mhqcHPqTMhSPoslhGYihEgSfc77+7La1P6kiB6+9So=
|
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 h1:8mhqcHPqTMhSPoslhGYihEgSfc77+7La1P6kiB6+9So=
|
||||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
@@ -623,6 +696,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||||
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -658,6 +733,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
|
|||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
@@ -709,6 +785,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -718,6 +795,8 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -752,6 +831,9 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -834,14 +916,18 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||||
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -944,6 +1030,7 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
@@ -982,10 +1069,14 @@ 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-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
||||||
|
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
|
||||||
gorm.io/driver/sqlite v1.5.3 h1:7/0dUgX28KAcopdfbRWWl68Rflh6osa4rDh+m51KL2g=
|
gorm.io/driver/sqlite v1.5.3 h1:7/0dUgX28KAcopdfbRWWl68Rflh6osa4rDh+m51KL2g=
|
||||||
gorm.io/driver/sqlite v1.5.3/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
|
gorm.io/driver/sqlite v1.5.3/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
|
||||||
gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
|
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde h1:9DShaph9qhkIYw7QF91I/ynrr4cOO2PZra2PFD7Mfeg=
|
||||||
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
|
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||||
|
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
||||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package iface
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -79,8 +80,19 @@ func TestWGIface_UpdateAddr(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, addr, addrs[0].String())
|
var found bool
|
||||||
|
for _, a := range addrs {
|
||||||
|
prefix, err := netip.ParsePrefix(a.String())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if prefix.Addr().Is4() {
|
||||||
|
found = true
|
||||||
|
assert.Equal(t, addr, prefix.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
t.Fatal("v4 address not found")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIfaceAddrs(ifaceName string) ([]net.Addr, error) {
|
func getIfaceAddrs(ifaceName string) ([]net.Addr, error) {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
//go:build !ios
|
//go:build !ios
|
||||||
// +build !ios
|
|
||||||
|
|
||||||
package iface
|
package iface
|
||||||
|
|
||||||
@@ -121,13 +120,19 @@ func (t *tunDevice) Wrapper() *DeviceWrapper {
|
|||||||
func (t *tunDevice) assignAddr() error {
|
func (t *tunDevice) assignAddr() error {
|
||||||
cmd := exec.Command("ifconfig", t.name, "inet", t.address.IP.String(), t.address.IP.String())
|
cmd := exec.Command("ifconfig", t.name, "inet", t.address.IP.String(), t.address.IP.String())
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
log.Infof(`adding address command "%v" failed with output %s and error: `, cmd.String(), out)
|
log.Errorf("adding address command '%v' failed with output: %s", cmd.String(), out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dummy ipv6 so routing works
|
||||||
|
cmd = exec.Command("ifconfig", t.name, "inet6", "fe80::/64")
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
log.Debugf("adding address command '%v' failed with output: %s", cmd.String(), out)
|
||||||
|
}
|
||||||
|
|
||||||
routeCmd := exec.Command("route", "add", "-net", t.address.Network.String(), "-interface", t.name)
|
routeCmd := exec.Command("route", "add", "-net", t.address.Network.String(), "-interface", t.name)
|
||||||
if out, err := routeCmd.CombinedOutput(); err != nil {
|
if out, err := routeCmd.CombinedOutput(); err != nil {
|
||||||
log.Printf(`adding route command "%v" failed with output %s and error: `, routeCmd.String(), out)
|
log.Errorf("adding route command '%v' failed with output: %s", routeCmd.String(), out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -62,10 +62,11 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
s := grpc.NewServer()
|
s := grpc.NewServer()
|
||||||
store, err := mgmt.NewStoreFromJson(config.Datadir, nil)
|
store, cleanUp, err := mgmt.NewTestStoreFromJson(config.Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
peersUpdateManager := mgmt.NewPeersUpdateManager(nil)
|
peersUpdateManager := mgmt.NewPeersUpdateManager(nil)
|
||||||
eventStore := &activity.InMemoryEventStore{}
|
eventStore := &activity.InMemoryEventStore{}
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
|
||||||
"github.com/netbirdio/netbird/util"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server"
|
||||||
|
"github.com/netbirdio/netbird/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var shortDown = "Rollback SQLite store to JSON file store. Please make a backup of the SQLite file before running this command."
|
var shortDown = "Rollback SQLite store to JSON file store. Please make a backup of the SQLite file before running this command."
|
||||||
@@ -39,16 +40,16 @@ var downCmd = &cobra.Command{
|
|||||||
return fmt.Errorf("%s already exists, couldn't continue the operation", fileStorePath)
|
return fmt.Errorf("%s already exists, couldn't continue the operation", fileStorePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlstore, err := server.NewSqliteStore(mgmtDataDir, nil)
|
sqlStore, err := server.NewSqliteStore(mgmtDataDir, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed creating file store: %s: %v", mgmtDataDir, err)
|
return fmt.Errorf("failed creating file store: %s: %v", mgmtDataDir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sqliteStoreAccounts := len(sqlstore.GetAllAccounts())
|
sqliteStoreAccounts := len(sqlStore.GetAllAccounts())
|
||||||
log.Infof("%d account will be migrated from sqlite store %s to file store %s",
|
log.Infof("%d account will be migrated from sqlite store %s to file store %s",
|
||||||
sqliteStoreAccounts, sqliteStorePath, fileStorePath)
|
sqliteStoreAccounts, sqliteStorePath, fileStorePath)
|
||||||
|
|
||||||
store, err := server.NewFilestoreFromSqliteStore(sqlstore, mgmtDataDir, nil)
|
store, err := server.NewFilestoreFromSqliteStore(sqlStore, mgmtDataDir, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed creating file store: %s: %v", mgmtDataDir, err)
|
return fmt.Errorf("failed creating file store: %s: %v", mgmtDataDir, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1294,6 +1294,7 @@ func TestAccountManager_DeletePeer(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := "account_creator"
|
userID := "account_creator"
|
||||||
account, err := createAccount(manager, "test_account", userID, "netbird.cloud")
|
account, err := createAccount(manager, "test_account", userID, "netbird.cloud")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1655,6 +1656,7 @@ func TestDefaultAccountManager_DefaultAccountSettings(t *testing.T) {
|
|||||||
func TestDefaultAccountManager_UpdatePeer_PeerLoginExpiration(t *testing.T) {
|
func TestDefaultAccountManager_UpdatePeer_PeerLoginExpiration(t *testing.T) {
|
||||||
manager, err := createManager(t)
|
manager, err := createManager(t)
|
||||||
require.NoError(t, err, "unable to create account manager")
|
require.NoError(t, err, "unable to create account manager")
|
||||||
|
|
||||||
_, err = manager.GetAccountByUserOrAccountID(userID, "", "")
|
_, err = manager.GetAccountByUserOrAccountID(userID, "", "")
|
||||||
require.NoError(t, err, "unable to create an account")
|
require.NoError(t, err, "unable to create an account")
|
||||||
|
|
||||||
@@ -1707,6 +1709,7 @@ func TestDefaultAccountManager_UpdatePeer_PeerLoginExpiration(t *testing.T) {
|
|||||||
func TestDefaultAccountManager_MarkPeerConnected_PeerLoginExpiration(t *testing.T) {
|
func TestDefaultAccountManager_MarkPeerConnected_PeerLoginExpiration(t *testing.T) {
|
||||||
manager, err := createManager(t)
|
manager, err := createManager(t)
|
||||||
require.NoError(t, err, "unable to create account manager")
|
require.NoError(t, err, "unable to create account manager")
|
||||||
|
|
||||||
account, err := manager.GetAccountByUserOrAccountID(userID, "", "")
|
account, err := manager.GetAccountByUserOrAccountID(userID, "", "")
|
||||||
require.NoError(t, err, "unable to create an account")
|
require.NoError(t, err, "unable to create an account")
|
||||||
|
|
||||||
@@ -1750,6 +1753,7 @@ func TestDefaultAccountManager_MarkPeerConnected_PeerLoginExpiration(t *testing.
|
|||||||
func TestDefaultAccountManager_UpdateAccountSettings_PeerLoginExpiration(t *testing.T) {
|
func TestDefaultAccountManager_UpdateAccountSettings_PeerLoginExpiration(t *testing.T) {
|
||||||
manager, err := createManager(t)
|
manager, err := createManager(t)
|
||||||
require.NoError(t, err, "unable to create account manager")
|
require.NoError(t, err, "unable to create account manager")
|
||||||
|
|
||||||
_, err = manager.GetAccountByUserOrAccountID(userID, "", "")
|
_, err = manager.GetAccountByUserOrAccountID(userID, "", "")
|
||||||
require.NoError(t, err, "unable to create an account")
|
require.NoError(t, err, "unable to create an account")
|
||||||
|
|
||||||
@@ -2267,21 +2271,29 @@ func TestAccount_UserGroupsRemoveFromPeers(t *testing.T) {
|
|||||||
|
|
||||||
func createManager(t *testing.T) (*DefaultAccountManager, error) {
|
func createManager(t *testing.T) (*DefaultAccountManager, error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
store, err := createStore(t)
|
store, err := createStore(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
eventStore := &activity.InMemoryEventStore{}
|
eventStore := &activity.InMemoryEventStore{}
|
||||||
return BuildManager(store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{})
|
|
||||||
|
manager, err := BuildManager(store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return manager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createStore(t *testing.T) (Store, error) {
|
func createStore(t *testing.T) (Store, error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
dataDir := t.TempDir()
|
dataDir := t.TempDir()
|
||||||
store, err := NewStoreFromJson(dataDir, nil)
|
store, cleanUp, err := NewTestStoreFromJson(dataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
return store, nil
|
return store, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func TestGetDNSSettings(t *testing.T) {
|
|||||||
|
|
||||||
account, err := initTestDNSAccount(t, am)
|
account, err := initTestDNSAccount(t, am)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed to init testing account")
|
t.Fatal("failed to init testing account")
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsSettings, err := am.GetDNSSettings(account.Id, dnsAdminUserID)
|
dnsSettings, err := am.GetDNSSettings(account.Id, dnsAdminUserID)
|
||||||
@@ -200,10 +200,11 @@ func createDNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
func createDNSStore(t *testing.T) (Store, error) {
|
func createDNSStore(t *testing.T) (Store, error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
dataDir := t.TempDir()
|
dataDir := t.TempDir()
|
||||||
store, err := NewStoreFromJson(dataDir, nil)
|
store, cleanUp, err := NewTestStoreFromJson(dataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
return store, nil
|
return store, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,18 +57,18 @@ func NewFileStore(dataDir string, metrics telemetry.AppMetrics) (*FileStore, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewFilestoreFromSqliteStore restores a store from Sqlite and stores to Filestore json in the file located in datadir
|
// NewFilestoreFromSqliteStore restores a store from Sqlite and stores to Filestore json in the file located in datadir
|
||||||
func NewFilestoreFromSqliteStore(sqlitestore *SqliteStore, dataDir string, metrics telemetry.AppMetrics) (*FileStore, error) {
|
func NewFilestoreFromSqliteStore(sqlStore *SqlStore, dataDir string, metrics telemetry.AppMetrics) (*FileStore, error) {
|
||||||
store, err := NewFileStore(dataDir, metrics)
|
store, err := NewFileStore(dataDir, metrics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.SaveInstallationID(sqlitestore.GetInstallationID())
|
err = store.SaveInstallationID(sqlStore.GetInstallationID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, account := range sqlitestore.GetAllAccounts() {
|
for _, account := range sqlStore.GetAllAccounts() {
|
||||||
store.Accounts[account.Id] = account
|
store.Accounts[account.Id] = account
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ func TestStalePeerIndices(t *testing.T) {
|
|||||||
|
|
||||||
func TestNewStore(t *testing.T) {
|
func TestNewStore(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
|
|
||||||
if store.Accounts == nil || len(store.Accounts) != 0 {
|
if store.Accounts == nil || len(store.Accounts) != 0 {
|
||||||
t.Errorf("expected to create a new empty Accounts map when creating a new FileStore")
|
t.Errorf("expected to create a new empty Accounts map when creating a new FileStore")
|
||||||
@@ -87,6 +88,7 @@ func TestNewStore(t *testing.T) {
|
|||||||
|
|
||||||
func TestSaveAccount(t *testing.T) {
|
func TestSaveAccount(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
|
|
||||||
account := newAccountWithId("account_id", "testuser", "")
|
account := newAccountWithId("account_id", "testuser", "")
|
||||||
setupKey := GenerateDefaultSetupKey()
|
setupKey := GenerateDefaultSetupKey()
|
||||||
@@ -135,6 +137,8 @@ func TestDeleteAccount(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer store.Close()
|
||||||
|
|
||||||
var account *Account
|
var account *Account
|
||||||
for _, a := range store.Accounts {
|
for _, a := range store.Accounts {
|
||||||
account = a
|
account = a
|
||||||
@@ -179,6 +183,7 @@ func TestDeleteAccount(t *testing.T) {
|
|||||||
|
|
||||||
func TestStore(t *testing.T) {
|
func TestStore(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
|
|
||||||
account := newAccountWithId("account_id", "testuser", "")
|
account := newAccountWithId("account_id", "testuser", "")
|
||||||
account.Peers["testpeer"] = &nbpeer.Peer{
|
account.Peers["testpeer"] = &nbpeer.Peer{
|
||||||
@@ -436,6 +441,7 @@ func TestFileStore_GetTokenIDByHashedToken(t *testing.T) {
|
|||||||
|
|
||||||
func TestFileStore_DeleteHashedPAT2TokenIDIndex(t *testing.T) {
|
func TestFileStore_DeleteHashedPAT2TokenIDIndex(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
store.HashedPAT2TokenID["someHashedToken"] = "someTokenId"
|
store.HashedPAT2TokenID["someHashedToken"] = "someTokenId"
|
||||||
|
|
||||||
err := store.DeleteHashedPAT2TokenIDIndex("someHashedToken")
|
err := store.DeleteHashedPAT2TokenIDIndex("someHashedToken")
|
||||||
|
|||||||
@@ -405,10 +405,12 @@ func startManagement(t *testing.T, config *Config) (*grpc.Server, string, error)
|
|||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
s := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp))
|
s := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp))
|
||||||
store, err := NewStoreFromJson(config.Datadir, nil)
|
store, cleanUp, err := NewTestStoreFromJson(config.Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
peersUpdateManager := NewPeersUpdateManager(nil)
|
peersUpdateManager := NewPeersUpdateManager(nil)
|
||||||
eventStore := &activity.InMemoryEventStore{}
|
eventStore := &activity.InMemoryEventStore{}
|
||||||
accountManager, err := BuildManager(store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
accountManager, err := BuildManager(store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
||||||
|
|||||||
@@ -532,10 +532,11 @@ func startServer(config *server.Config) (*grpc.Server, net.Listener) {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
s := grpc.NewServer()
|
s := grpc.NewServer()
|
||||||
|
|
||||||
store, err := server.NewStoreFromJson(config.Datadir, nil)
|
store, _, err := server.NewTestStoreFromJson(config.Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed creating a store: %s: %v", config.Datadir, err)
|
log.Fatalf("failed creating a store: %s: %v", config.Datadir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
peersUpdateManager := server.NewPeersUpdateManager(nil)
|
peersUpdateManager := server.NewPeersUpdateManager(nil)
|
||||||
eventStore := &activity.InMemoryEventStore{}
|
eventStore := &activity.InMemoryEventStore{}
|
||||||
accountManager, err := server.BuildManager(store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
accountManager, err := server.BuildManager(store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
||||||
|
|||||||
@@ -766,10 +766,11 @@ func createNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
func createNSStore(t *testing.T) (Store, error) {
|
func createNSStore(t *testing.T) (Store, error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
dataDir := t.TempDir()
|
dataDir := t.TempDir()
|
||||||
store, err := NewStoreFromJson(dataDir, nil)
|
store, cleanUp, err := NewTestStoreFromJson(dataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
return store, nil
|
return store, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,7 +216,9 @@ func (p *Peer) FQDN(dnsDomain string) string {
|
|||||||
|
|
||||||
// EventMeta returns activity event meta related to the peer
|
// EventMeta returns activity event meta related to the peer
|
||||||
func (p *Peer) EventMeta(dnsDomain string) map[string]any {
|
func (p *Peer) EventMeta(dnsDomain string) map[string]any {
|
||||||
return map[string]any{"name": p.Name, "fqdn": p.FQDN(dnsDomain), "ip": p.IP, "created_at": p.CreatedAt}
|
return map[string]any{"name": p.Name, "fqdn": p.FQDN(dnsDomain), "ip": p.IP, "created_at": p.CreatedAt,
|
||||||
|
"location_city_name": p.Location.CityName, "location_country_code": p.Location.CountryCode,
|
||||||
|
"location_geo_name_id": p.Location.GeoNameID, "location_connection_ip": p.Location.ConnectionIP}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy PeerStatus
|
// Copy PeerStatus
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ type Policy struct {
|
|||||||
Enabled bool
|
Enabled bool
|
||||||
|
|
||||||
// Rules of the policy
|
// Rules of the policy
|
||||||
Rules []*PolicyRule `gorm:"foreignKey:PolicyID;references:id"`
|
Rules []*PolicyRule `gorm:"foreignKey:PolicyID;references:id;constraint:OnDelete:CASCADE;"`
|
||||||
|
|
||||||
// SourcePostureChecks are ID references to Posture checks for policy source groups
|
// SourcePostureChecks are ID references to Posture checks for policy source groups
|
||||||
SourcePostureChecks []string `gorm:"serializer:json"`
|
SourcePostureChecks []string `gorm:"serializer:json"`
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package server
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/posture"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -1021,10 +1021,11 @@ func createRouterManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
func createRouterStore(t *testing.T) (Store, error) {
|
func createRouterStore(t *testing.T) (Store, error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
dataDir := t.TempDir()
|
dataDir := t.TempDir()
|
||||||
store, err := NewStoreFromJson(dataDir, nil)
|
store, cleanUp, err := NewTestStoreFromJson(dataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
return store, nil
|
return store, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package server
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/netip"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -12,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
@@ -20,7 +19,6 @@ import (
|
|||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/server/account"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
nbgroup "github.com/netbirdio/netbird/management/server/group"
|
||||||
"github.com/netbirdio/netbird/management/server/migration"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/posture"
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
@@ -28,14 +26,14 @@ import (
|
|||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SqliteStore represents an account storage backed by a Sqlite DB persisted to disk
|
// SqlStore represents an account storage backed by a Sql DB persisted to disk
|
||||||
type SqliteStore struct {
|
type SqlStore struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
storeFile string
|
|
||||||
accountLocks sync.Map
|
accountLocks sync.Map
|
||||||
globalAccountLock sync.Mutex
|
globalAccountLock sync.Mutex
|
||||||
metrics telemetry.AppMetrics
|
metrics telemetry.AppMetrics
|
||||||
installationPK int
|
installationPK int
|
||||||
|
storeEngine StoreEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
type installation struct {
|
type installation struct {
|
||||||
@@ -45,24 +43,8 @@ type installation struct {
|
|||||||
|
|
||||||
type migrationFunc func(*gorm.DB) error
|
type migrationFunc func(*gorm.DB) error
|
||||||
|
|
||||||
// NewSqliteStore restores a store from the file located in the datadir
|
// NewSqlStore creates a new SqlStore instance.
|
||||||
func NewSqliteStore(dataDir string, metrics telemetry.AppMetrics) (*SqliteStore, error) {
|
func NewSqlStore(db *gorm.DB, storeEngine StoreEngine, metrics telemetry.AppMetrics) (*SqlStore, error) {
|
||||||
storeStr := "store.db?cache=shared"
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// Vo avoid `The process cannot access the file because it is being used by another process` on Windows
|
|
||||||
storeStr = "store.db"
|
|
||||||
}
|
|
||||||
|
|
||||||
file := filepath.Join(dataDir, storeStr)
|
|
||||||
db, err := gorm.Open(sqlite.Open(file), &gorm.Config{
|
|
||||||
Logger: logger.Default.LogMode(logger.Silent),
|
|
||||||
CreateBatchSize: 400,
|
|
||||||
PrepareStmt: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sql, err := db.DB()
|
sql, err := db.DB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -82,33 +64,11 @@ func NewSqliteStore(dataDir string, metrics telemetry.AppMetrics) (*SqliteStore,
|
|||||||
return nil, fmt.Errorf("auto migrate: %w", err)
|
return nil, fmt.Errorf("auto migrate: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SqliteStore{db: db, storeFile: file, metrics: metrics, installationPK: 1}, nil
|
return &SqlStore{db: db, storeEngine: storeEngine, metrics: metrics, installationPK: 1}, nil
|
||||||
}
|
|
||||||
|
|
||||||
// NewSqliteStoreFromFileStore restores a store from FileStore and stores SQLite DB in the file located in datadir
|
|
||||||
func NewSqliteStoreFromFileStore(filestore *FileStore, dataDir string, metrics telemetry.AppMetrics) (*SqliteStore, error) {
|
|
||||||
store, err := NewSqliteStore(dataDir, metrics)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = store.SaveInstallationID(filestore.InstallationID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, account := range filestore.GetAllAccounts() {
|
|
||||||
err := store.SaveAccount(account)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return store, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AcquireGlobalLock acquires global lock across all the accounts and returns a function that releases the lock
|
// AcquireGlobalLock acquires global lock across all the accounts and returns a function that releases the lock
|
||||||
func (s *SqliteStore) AcquireGlobalLock() (unlock func()) {
|
func (s *SqlStore) AcquireGlobalLock() (unlock func()) {
|
||||||
log.Tracef("acquiring global lock")
|
log.Tracef("acquiring global lock")
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
s.globalAccountLock.Lock()
|
s.globalAccountLock.Lock()
|
||||||
@@ -127,7 +87,7 @@ func (s *SqliteStore) AcquireGlobalLock() (unlock func()) {
|
|||||||
return unlock
|
return unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) AcquireAccountWriteLock(accountID string) (unlock func()) {
|
func (s *SqlStore) AcquireAccountWriteLock(accountID string) (unlock func()) {
|
||||||
log.Tracef("acquiring write lock for account %s", accountID)
|
log.Tracef("acquiring write lock for account %s", accountID)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
@@ -143,7 +103,7 @@ func (s *SqliteStore) AcquireAccountWriteLock(accountID string) (unlock func())
|
|||||||
return unlock
|
return unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) AcquireAccountReadLock(accountID string) (unlock func()) {
|
func (s *SqlStore) AcquireAccountReadLock(accountID string) (unlock func()) {
|
||||||
log.Tracef("acquiring read lock for account %s", accountID)
|
log.Tracef("acquiring read lock for account %s", accountID)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
@@ -159,7 +119,7 @@ func (s *SqliteStore) AcquireAccountReadLock(accountID string) (unlock func()) {
|
|||||||
return unlock
|
return unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) SaveAccount(account *Account) error {
|
func (s *SqlStore) SaveAccount(account *Account) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
for _, key := range account.SetupKeys {
|
for _, key := range account.SetupKeys {
|
||||||
@@ -225,12 +185,12 @@ func (s *SqliteStore) SaveAccount(account *Account) error {
|
|||||||
if s.metrics != nil {
|
if s.metrics != nil {
|
||||||
s.metrics.StoreMetrics().CountPersistenceDuration(took)
|
s.metrics.StoreMetrics().CountPersistenceDuration(took)
|
||||||
}
|
}
|
||||||
log.Debugf("took %d ms to persist an account to the SQLite", took.Milliseconds())
|
log.Debugf("took %d ms to persist an account to the store", took.Milliseconds())
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) DeleteAccount(account *Account) error {
|
func (s *SqlStore) DeleteAccount(account *Account) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
err := s.db.Transaction(func(tx *gorm.DB) error {
|
err := s.db.Transaction(func(tx *gorm.DB) error {
|
||||||
@@ -256,19 +216,19 @@ func (s *SqliteStore) DeleteAccount(account *Account) error {
|
|||||||
if s.metrics != nil {
|
if s.metrics != nil {
|
||||||
s.metrics.StoreMetrics().CountPersistenceDuration(took)
|
s.metrics.StoreMetrics().CountPersistenceDuration(took)
|
||||||
}
|
}
|
||||||
log.Debugf("took %d ms to delete an account to the SQLite", took.Milliseconds())
|
log.Debugf("took %d ms to delete an account to the store", took.Milliseconds())
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) SaveInstallationID(ID string) error {
|
func (s *SqlStore) SaveInstallationID(ID string) error {
|
||||||
installation := installation{InstallationIDValue: ID}
|
installation := installation{InstallationIDValue: ID}
|
||||||
installation.ID = uint(s.installationPK)
|
installation.ID = uint(s.installationPK)
|
||||||
|
|
||||||
return s.db.Clauses(clause.OnConflict{UpdateAll: true}).Create(&installation).Error
|
return s.db.Clauses(clause.OnConflict{UpdateAll: true}).Create(&installation).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetInstallationID() string {
|
func (s *SqlStore) GetInstallationID() string {
|
||||||
var installation installation
|
var installation installation
|
||||||
|
|
||||||
if result := s.db.First(&installation, "id = ?", s.installationPK); result.Error != nil {
|
if result := s.db.First(&installation, "id = ?", s.installationPK); result.Error != nil {
|
||||||
@@ -278,7 +238,7 @@ func (s *SqliteStore) GetInstallationID() string {
|
|||||||
return installation.InstallationIDValue
|
return installation.InstallationIDValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) SavePeerStatus(accountID, peerID string, peerStatus nbpeer.PeerStatus) error {
|
func (s *SqlStore) SavePeerStatus(accountID, peerID string, peerStatus nbpeer.PeerStatus) error {
|
||||||
var peerCopy nbpeer.Peer
|
var peerCopy nbpeer.Peer
|
||||||
peerCopy.Status = &peerStatus
|
peerCopy.Status = &peerStatus
|
||||||
result := s.db.Model(&nbpeer.Peer{}).
|
result := s.db.Model(&nbpeer.Peer{}).
|
||||||
@@ -296,7 +256,7 @@ func (s *SqliteStore) SavePeerStatus(accountID, peerID string, peerStatus nbpeer
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) SavePeerLocation(accountID string, peerWithLocation *nbpeer.Peer) error {
|
func (s *SqlStore) SavePeerLocation(accountID string, peerWithLocation *nbpeer.Peer) error {
|
||||||
// To maintain data integrity, we create a copy of the peer's location to prevent unintended updates to other fields.
|
// To maintain data integrity, we create a copy of the peer's location to prevent unintended updates to other fields.
|
||||||
var peerCopy nbpeer.Peer
|
var peerCopy nbpeer.Peer
|
||||||
// Since the location field has been migrated to JSON serialization,
|
// Since the location field has been migrated to JSON serialization,
|
||||||
@@ -318,17 +278,17 @@ func (s *SqliteStore) SavePeerLocation(accountID string, peerWithLocation *nbpee
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteHashedPAT2TokenIDIndex is noop in Sqlite
|
// DeleteHashedPAT2TokenIDIndex is noop in SqlStore
|
||||||
func (s *SqliteStore) DeleteHashedPAT2TokenIDIndex(hashedToken string) error {
|
func (s *SqlStore) DeleteHashedPAT2TokenIDIndex(hashedToken string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteTokenID2UserIDIndex is noop in Sqlite
|
// DeleteTokenID2UserIDIndex is noop in SqlStore
|
||||||
func (s *SqliteStore) DeleteTokenID2UserIDIndex(tokenID string) error {
|
func (s *SqlStore) DeleteTokenID2UserIDIndex(tokenID string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAccountByPrivateDomain(domain string) (*Account, error) {
|
func (s *SqlStore) GetAccountByPrivateDomain(domain string) (*Account, error) {
|
||||||
var account Account
|
var account Account
|
||||||
|
|
||||||
result := s.db.First(&account, "domain = ? and is_domain_primary_account = ? and domain_category = ?",
|
result := s.db.First(&account, "domain = ? and is_domain_primary_account = ? and domain_category = ?",
|
||||||
@@ -345,7 +305,7 @@ func (s *SqliteStore) GetAccountByPrivateDomain(domain string) (*Account, error)
|
|||||||
return s.GetAccount(account.Id)
|
return s.GetAccount(account.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAccountBySetupKey(setupKey string) (*Account, error) {
|
func (s *SqlStore) GetAccountBySetupKey(setupKey string) (*Account, error) {
|
||||||
var key SetupKey
|
var key SetupKey
|
||||||
result := s.db.Select("account_id").First(&key, "key = ?", strings.ToUpper(setupKey))
|
result := s.db.Select("account_id").First(&key, "key = ?", strings.ToUpper(setupKey))
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
@@ -363,7 +323,7 @@ func (s *SqliteStore) GetAccountBySetupKey(setupKey string) (*Account, error) {
|
|||||||
return s.GetAccount(key.AccountID)
|
return s.GetAccount(key.AccountID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetTokenIDByHashedToken(hashedToken string) (string, error) {
|
func (s *SqlStore) GetTokenIDByHashedToken(hashedToken string) (string, error) {
|
||||||
var token PersonalAccessToken
|
var token PersonalAccessToken
|
||||||
result := s.db.First(&token, "hashed_token = ?", hashedToken)
|
result := s.db.First(&token, "hashed_token = ?", hashedToken)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
@@ -377,7 +337,7 @@ func (s *SqliteStore) GetTokenIDByHashedToken(hashedToken string) (string, error
|
|||||||
return token.ID, nil
|
return token.ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetUserByTokenID(tokenID string) (*User, error) {
|
func (s *SqlStore) GetUserByTokenID(tokenID string) (*User, error) {
|
||||||
var token PersonalAccessToken
|
var token PersonalAccessToken
|
||||||
result := s.db.First(&token, "id = ?", tokenID)
|
result := s.db.First(&token, "id = ?", tokenID)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
@@ -406,7 +366,7 @@ func (s *SqliteStore) GetUserByTokenID(tokenID string) (*User, error) {
|
|||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAllAccounts() (all []*Account) {
|
func (s *SqlStore) GetAllAccounts() (all []*Account) {
|
||||||
var accounts []Account
|
var accounts []Account
|
||||||
result := s.db.Find(&accounts)
|
result := s.db.Find(&accounts)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
@@ -422,7 +382,7 @@ func (s *SqliteStore) GetAllAccounts() (all []*Account) {
|
|||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAccount(accountID string) (*Account, error) {
|
func (s *SqlStore) GetAccount(accountID string) (*Account, error) {
|
||||||
|
|
||||||
var account Account
|
var account Account
|
||||||
result := s.db.Model(&account).
|
result := s.db.Model(&account).
|
||||||
@@ -490,7 +450,7 @@ func (s *SqliteStore) GetAccount(accountID string) (*Account, error) {
|
|||||||
return &account, nil
|
return &account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAccountByUser(userID string) (*Account, error) {
|
func (s *SqlStore) GetAccountByUser(userID string) (*Account, error) {
|
||||||
var user User
|
var user User
|
||||||
result := s.db.Select("account_id").First(&user, "id = ?", userID)
|
result := s.db.Select("account_id").First(&user, "id = ?", userID)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
@@ -508,7 +468,7 @@ func (s *SqliteStore) GetAccountByUser(userID string) (*Account, error) {
|
|||||||
return s.GetAccount(user.AccountID)
|
return s.GetAccount(user.AccountID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAccountByPeerID(peerID string) (*Account, error) {
|
func (s *SqlStore) GetAccountByPeerID(peerID string) (*Account, error) {
|
||||||
var peer nbpeer.Peer
|
var peer nbpeer.Peer
|
||||||
result := s.db.Select("account_id").First(&peer, "id = ?", peerID)
|
result := s.db.Select("account_id").First(&peer, "id = ?", peerID)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
@@ -526,7 +486,7 @@ func (s *SqliteStore) GetAccountByPeerID(peerID string) (*Account, error) {
|
|||||||
return s.GetAccount(peer.AccountID)
|
return s.GetAccount(peer.AccountID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAccountByPeerPubKey(peerKey string) (*Account, error) {
|
func (s *SqlStore) GetAccountByPeerPubKey(peerKey string) (*Account, error) {
|
||||||
var peer nbpeer.Peer
|
var peer nbpeer.Peer
|
||||||
|
|
||||||
result := s.db.Select("account_id").First(&peer, "key = ?", peerKey)
|
result := s.db.Select("account_id").First(&peer, "key = ?", peerKey)
|
||||||
@@ -545,7 +505,7 @@ func (s *SqliteStore) GetAccountByPeerPubKey(peerKey string) (*Account, error) {
|
|||||||
return s.GetAccount(peer.AccountID)
|
return s.GetAccount(peer.AccountID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqliteStore) GetAccountIDByPeerPubKey(peerKey string) (string, error) {
|
func (s *SqlStore) GetAccountIDByPeerPubKey(peerKey string) (string, error) {
|
||||||
var peer nbpeer.Peer
|
var peer nbpeer.Peer
|
||||||
var accountID string
|
var accountID string
|
||||||
result := s.db.Model(&peer).Select("account_id").Where("key = ?", peerKey).First(&accountID)
|
result := s.db.Model(&peer).Select("account_id").Where("key = ?", peerKey).First(&accountID)
|
||||||
@@ -561,7 +521,7 @@ func (s *SqliteStore) GetAccountIDByPeerPubKey(peerKey string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SaveUserLastLogin stores the last login time for a user in DB.
|
// SaveUserLastLogin stores the last login time for a user in DB.
|
||||||
func (s *SqliteStore) SaveUserLastLogin(accountID, userID string, lastLogin time.Time) error {
|
func (s *SqlStore) SaveUserLastLogin(accountID, userID string, lastLogin time.Time) error {
|
||||||
var user User
|
var user User
|
||||||
|
|
||||||
result := s.db.First(&user, "account_id = ? and id = ?", accountID, userID)
|
result := s.db.First(&user, "account_id = ? and id = ?", accountID, userID)
|
||||||
@@ -579,7 +539,7 @@ func (s *SqliteStore) SaveUserLastLogin(accountID, userID string, lastLogin time
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the underlying DB connection
|
// Close closes the underlying DB connection
|
||||||
func (s *SqliteStore) Close() error {
|
func (s *SqlStore) Close() error {
|
||||||
sql, err := s.db.DB()
|
sql, err := s.db.DB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get db: %w", err)
|
return fmt.Errorf("get db: %w", err)
|
||||||
@@ -587,40 +547,85 @@ func (s *SqliteStore) Close() error {
|
|||||||
return sql.Close()
|
return sql.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStoreEngine returns SqliteStoreEngine
|
// GetStoreEngine returns underlying store engine
|
||||||
func (s *SqliteStore) GetStoreEngine() StoreEngine {
|
func (s *SqlStore) GetStoreEngine() StoreEngine {
|
||||||
return SqliteStoreEngine
|
return s.storeEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
// migrate migrates the SQLite database to the latest schema
|
// NewSqliteStore creates a new SQLite store.
|
||||||
func migrate(db *gorm.DB) error {
|
func NewSqliteStore(dataDir string, metrics telemetry.AppMetrics) (*SqlStore, error) {
|
||||||
migrations := getMigrations()
|
storeStr := "store.db?cache=shared"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// Vo avoid `The process cannot access the file because it is being used by another process` on Windows
|
||||||
|
storeStr = "store.db"
|
||||||
|
}
|
||||||
|
|
||||||
for _, m := range migrations {
|
file := filepath.Join(dataDir, storeStr)
|
||||||
if err := m(db); err != nil {
|
db, err := gorm.Open(sqlite.Open(file), &gorm.Config{
|
||||||
return err
|
Logger: logger.Default.LogMode(logger.Silent),
|
||||||
|
CreateBatchSize: 400,
|
||||||
|
PrepareStmt: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewSqlStore(db, SqliteStoreEngine, metrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPostgresqlStore creates a new Postgres store.
|
||||||
|
func NewPostgresqlStore(dsn string, metrics telemetry.AppMetrics) (*SqlStore, error) {
|
||||||
|
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||||
|
Logger: logger.Default.LogMode(logger.Silent),
|
||||||
|
PrepareStmt: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewSqlStore(db, PostgresStoreEngine, metrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSqliteStoreFromFileStore restores a store from FileStore and stores SQLite DB in the file located in datadir.
|
||||||
|
func NewSqliteStoreFromFileStore(fileStore *FileStore, dataDir string, metrics telemetry.AppMetrics) (*SqlStore, error) {
|
||||||
|
store, err := NewSqliteStore(dataDir, metrics)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.SaveInstallationID(fileStore.InstallationID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, account := range fileStore.GetAllAccounts() {
|
||||||
|
err := store.SaveAccount(account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return store, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMigrations() []migrationFunc {
|
// NewPostgresqlStoreFromFileStore restores a store from FileStore and stores Postgres DB.
|
||||||
return []migrationFunc{
|
func NewPostgresqlStoreFromFileStore(fileStore *FileStore, dsn string, metrics telemetry.AppMetrics) (*SqlStore, error) {
|
||||||
func(db *gorm.DB) error {
|
store, err := NewPostgresqlStore(dsn, metrics)
|
||||||
return migration.MigrateFieldFromGobToJSON[Account, net.IPNet](db, "network_net")
|
if err != nil {
|
||||||
},
|
return nil, err
|
||||||
func(db *gorm.DB) error {
|
|
||||||
return migration.MigrateFieldFromGobToJSON[route.Route, netip.Prefix](db, "network")
|
|
||||||
},
|
|
||||||
func(db *gorm.DB) error {
|
|
||||||
return migration.MigrateFieldFromGobToJSON[route.Route, []string](db, "peer_groups")
|
|
||||||
},
|
|
||||||
func(db *gorm.DB) error {
|
|
||||||
return migration.MigrateNetIPFieldFromBlobToJSON[nbpeer.Peer](db, "location_connection_ip", "")
|
|
||||||
},
|
|
||||||
func(db *gorm.DB) error {
|
|
||||||
return migration.MigrateNetIPFieldFromBlobToJSON[nbpeer.Peer](db, "ip", "idx_peers_account_id_ip")
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = store.SaveInstallationID(fileStore.InstallationID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, account := range fileStore.GetAllAccounts() {
|
||||||
|
err := store.SaveAccount(account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return store, nil
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -569,7 +570,7 @@ func TestMigrate(t *testing.T) {
|
|||||||
require.NoError(t, err, "Migration should not fail on migrated db")
|
require.NoError(t, err, "Migration should not fail on migrated db")
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSqliteStore(t *testing.T) *SqliteStore {
|
func newSqliteStore(t *testing.T) *SqlStore {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
store, err := NewSqliteStore(t.TempDir(), nil)
|
store, err := NewSqliteStore(t.TempDir(), nil)
|
||||||
@@ -579,7 +580,7 @@ func newSqliteStore(t *testing.T) *SqliteStore {
|
|||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSqliteStoreFromFile(t *testing.T, filename string) *SqliteStore {
|
func newSqliteStoreFromFile(t *testing.T, filename string) *SqlStore {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
storeDir := t.TempDir()
|
storeDir := t.TempDir()
|
||||||
@@ -613,3 +614,298 @@ func newAccount(store Store, id int) error {
|
|||||||
|
|
||||||
return store.SaveAccount(account)
|
return store.SaveAccount(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newPostgresqlStore(t *testing.T) *SqlStore {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
cleanUp, err := createPGDB()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
|
postgresDsn, ok := os.LookupEnv(postgresDsnEnv)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("could not initialize postgresql store: %s is not set", postgresDsnEnv)
|
||||||
|
}
|
||||||
|
|
||||||
|
store, err := NewPostgresqlStore(postgresDsn, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not initialize postgresql store: %s", err)
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, store)
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPostgresqlStoreFromFile(t *testing.T, filename string) *SqlStore {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
storeDir := t.TempDir()
|
||||||
|
err := util.CopyFileContents(filename, filepath.Join(storeDir, "store.json"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fStore, err := NewFileStore(storeDir, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cleanUp, err := createPGDB()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Cleanup(cleanUp)
|
||||||
|
|
||||||
|
postgresDsn, ok := os.LookupEnv(postgresDsnEnv)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("could not initialize postgresql store: %s is not set", postgresDsnEnv)
|
||||||
|
}
|
||||||
|
|
||||||
|
store, err := NewPostgresqlStoreFromFileStore(fStore, postgresDsn, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, store)
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostgresql_NewStore(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("The PostgreSQL store is not properly supported by %s yet", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
store := newPostgresqlStore(t)
|
||||||
|
|
||||||
|
if len(store.GetAllAccounts()) != 0 {
|
||||||
|
t.Errorf("expected to create a new empty Accounts map when creating a new FileStore")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostgresql_SaveAccount(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("The PostgreSQL store is not properly supported by %s yet", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
store := newPostgresqlStore(t)
|
||||||
|
|
||||||
|
account := newAccountWithId("account_id", "testuser", "")
|
||||||
|
setupKey := GenerateDefaultSetupKey()
|
||||||
|
account.SetupKeys[setupKey.Key] = setupKey
|
||||||
|
account.Peers["testpeer"] = &nbpeer.Peer{
|
||||||
|
Key: "peerkey",
|
||||||
|
SetupKey: "peerkeysetupkey",
|
||||||
|
IP: net.IP{127, 0, 0, 1},
|
||||||
|
Meta: nbpeer.PeerSystemMeta{},
|
||||||
|
Name: "peer name",
|
||||||
|
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := store.SaveAccount(account)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
account2 := newAccountWithId("account_id2", "testuser2", "")
|
||||||
|
setupKey = GenerateDefaultSetupKey()
|
||||||
|
account2.SetupKeys[setupKey.Key] = setupKey
|
||||||
|
account2.Peers["testpeer2"] = &nbpeer.Peer{
|
||||||
|
Key: "peerkey2",
|
||||||
|
SetupKey: "peerkeysetupkey2",
|
||||||
|
IP: net.IP{127, 0, 0, 2},
|
||||||
|
Meta: nbpeer.PeerSystemMeta{},
|
||||||
|
Name: "peer name 2",
|
||||||
|
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.SaveAccount(account2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(store.GetAllAccounts()) != 2 {
|
||||||
|
t.Errorf("expecting 2 Accounts to be stored after SaveAccount()")
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := store.GetAccount(account.Id)
|
||||||
|
if a == nil {
|
||||||
|
t.Errorf("expecting Account to be stored after SaveAccount(): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a != nil && len(a.Policies) != 1 {
|
||||||
|
t.Errorf("expecting Account to have one policy stored after SaveAccount(), got %d", len(a.Policies))
|
||||||
|
}
|
||||||
|
|
||||||
|
if a != nil && len(a.Policies[0].Rules) != 1 {
|
||||||
|
t.Errorf("expecting Account to have one policy rule stored after SaveAccount(), got %d", len(a.Policies[0].Rules))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if a, err := store.GetAccountByPeerPubKey("peerkey"); a == nil {
|
||||||
|
t.Errorf("expecting PeerKeyID2AccountID index updated after SaveAccount(): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a, err := store.GetAccountByUser("testuser"); a == nil {
|
||||||
|
t.Errorf("expecting UserID2AccountID index updated after SaveAccount(): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a, err := store.GetAccountByPeerID("testpeer"); a == nil {
|
||||||
|
t.Errorf("expecting PeerID2AccountID index updated after SaveAccount(): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a, err := store.GetAccountBySetupKey(setupKey.Key); a == nil {
|
||||||
|
t.Errorf("expecting SetupKeyID2AccountID index updated after SaveAccount(): %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostgresql_DeleteAccount(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("The PostgreSQL store is not properly supported by %s yet", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
store := newPostgresqlStore(t)
|
||||||
|
|
||||||
|
testUserID := "testuser"
|
||||||
|
user := NewAdminUser(testUserID)
|
||||||
|
user.PATs = map[string]*PersonalAccessToken{"testtoken": {
|
||||||
|
ID: "testtoken",
|
||||||
|
Name: "test token",
|
||||||
|
}}
|
||||||
|
|
||||||
|
account := newAccountWithId("account_id", testUserID, "")
|
||||||
|
setupKey := GenerateDefaultSetupKey()
|
||||||
|
account.SetupKeys[setupKey.Key] = setupKey
|
||||||
|
account.Peers["testpeer"] = &nbpeer.Peer{
|
||||||
|
Key: "peerkey",
|
||||||
|
SetupKey: "peerkeysetupkey",
|
||||||
|
IP: net.IP{127, 0, 0, 1},
|
||||||
|
Meta: nbpeer.PeerSystemMeta{},
|
||||||
|
Name: "peer name",
|
||||||
|
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()},
|
||||||
|
}
|
||||||
|
account.Users[testUserID] = user
|
||||||
|
|
||||||
|
err := store.SaveAccount(account)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(store.GetAllAccounts()) != 1 {
|
||||||
|
t.Errorf("expecting 1 Accounts to be stored after SaveAccount()")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.DeleteAccount(account)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(store.GetAllAccounts()) != 0 {
|
||||||
|
t.Errorf("expecting 0 Accounts to be stored after DeleteAccount()")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = store.GetAccountByPeerPubKey("peerkey")
|
||||||
|
require.Error(t, err, "expecting error after removing DeleteAccount when getting account by peer public key")
|
||||||
|
|
||||||
|
_, err = store.GetAccountByUser("testuser")
|
||||||
|
require.Error(t, err, "expecting error after removing DeleteAccount when getting account by user")
|
||||||
|
|
||||||
|
_, err = store.GetAccountByPeerID("testpeer")
|
||||||
|
require.Error(t, err, "expecting error after removing DeleteAccount when getting account by peer id")
|
||||||
|
|
||||||
|
_, err = store.GetAccountBySetupKey(setupKey.Key)
|
||||||
|
require.Error(t, err, "expecting error after removing DeleteAccount when getting account by setup key")
|
||||||
|
|
||||||
|
_, err = store.GetAccount(account.Id)
|
||||||
|
require.Error(t, err, "expecting error after removing DeleteAccount when getting account by id")
|
||||||
|
|
||||||
|
for _, policy := range account.Policies {
|
||||||
|
var rules []*PolicyRule
|
||||||
|
err = store.db.Model(&PolicyRule{}).Find(&rules, "policy_id = ?", policy.ID).Error
|
||||||
|
require.NoError(t, err, "expecting no error after removing DeleteAccount when searching for policy rules")
|
||||||
|
require.Len(t, rules, 0, "expecting no policy rules to be found after removing DeleteAccount")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, accountUser := range account.Users {
|
||||||
|
var pats []*PersonalAccessToken
|
||||||
|
err = store.db.Model(&PersonalAccessToken{}).Find(&pats, "user_id = ?", accountUser.Id).Error
|
||||||
|
require.NoError(t, err, "expecting no error after removing DeleteAccount when searching for personal access token")
|
||||||
|
require.Len(t, pats, 0, "expecting no personal access token to be found after removing DeleteAccount")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostgresql_SavePeerStatus(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("The PostgreSQL store is not properly supported by %s yet", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
store := newPostgresqlStoreFromFile(t, "testdata/store.json")
|
||||||
|
|
||||||
|
account, err := store.GetAccount("bf1c8084-ba50-4ce7-9439-34653001fc3b")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// save status of non-existing peer
|
||||||
|
newStatus := nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()}
|
||||||
|
err = store.SavePeerStatus(account.Id, "non-existing-peer", newStatus)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
// save new status of existing peer
|
||||||
|
account.Peers["testpeer"] = &nbpeer.Peer{
|
||||||
|
Key: "peerkey",
|
||||||
|
ID: "testpeer",
|
||||||
|
SetupKey: "peerkeysetupkey",
|
||||||
|
IP: net.IP{127, 0, 0, 1},
|
||||||
|
Meta: nbpeer.PeerSystemMeta{},
|
||||||
|
Name: "peer name",
|
||||||
|
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now().UTC()},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.SaveAccount(account)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = store.SavePeerStatus(account.Id, "testpeer", newStatus)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
account, err = store.GetAccount(account.Id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
actual := account.Peers["testpeer"].Status
|
||||||
|
assert.Equal(t, newStatus.Connected, actual.Connected)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostgresql_TestGetAccountByPrivateDomain(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("The PostgreSQL store is not properly supported by %s yet", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
store := newPostgresqlStoreFromFile(t, "testdata/store.json")
|
||||||
|
|
||||||
|
existingDomain := "test.com"
|
||||||
|
|
||||||
|
account, err := store.GetAccountByPrivateDomain(existingDomain)
|
||||||
|
require.NoError(t, err, "should found account")
|
||||||
|
require.Equal(t, existingDomain, account.Domain, "domains should match")
|
||||||
|
|
||||||
|
_, err = store.GetAccountByPrivateDomain("missing-domain.com")
|
||||||
|
require.Error(t, err, "should return error on domain lookup")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostgresql_GetTokenIDByHashedToken(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("The PostgreSQL store is not properly supported by %s yet", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
store := newPostgresqlStoreFromFile(t, "testdata/store.json")
|
||||||
|
|
||||||
|
hashed := "SoMeHaShEdToKeN"
|
||||||
|
id := "9dj38s35-63fb-11ec-90d6-0242ac120003"
|
||||||
|
|
||||||
|
token, err := store.GetTokenIDByHashedToken(hashed)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, id, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostgresql_GetUserByTokenID(t *testing.T) {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
t.Skipf("The PostgreSQL store is not properly supported by %s yet", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
store := newPostgresqlStoreFromFile(t, "testdata/store.json")
|
||||||
|
|
||||||
|
id := "9dj38s35-63fb-11ec-90d6-0242ac120003"
|
||||||
|
|
||||||
|
user, err := store.GetUserByTokenID(id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, id, user.PATs[id].ID)
|
||||||
|
}
|
||||||
@@ -1,16 +1,25 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/testcontainers/testcontainers-go"
|
||||||
|
"github.com/testcontainers/testcontainers-go/modules/postgres"
|
||||||
|
"github.com/testcontainers/testcontainers-go/wait"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/migration"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Store interface {
|
type Store interface {
|
||||||
@@ -49,8 +58,11 @@ type Store interface {
|
|||||||
type StoreEngine string
|
type StoreEngine string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FileStoreEngine StoreEngine = "jsonfile"
|
FileStoreEngine StoreEngine = "jsonfile"
|
||||||
SqliteStoreEngine StoreEngine = "sqlite"
|
SqliteStoreEngine StoreEngine = "sqlite"
|
||||||
|
PostgresStoreEngine StoreEngine = "postgres"
|
||||||
|
|
||||||
|
postgresDsnEnv = "NETBIRD_STORE_ENGINE_POSTGRES_DSN"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getStoreEngineFromEnv() StoreEngine {
|
func getStoreEngineFromEnv() StoreEngine {
|
||||||
@@ -61,8 +73,7 @@ func getStoreEngineFromEnv() StoreEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
value := StoreEngine(strings.ToLower(kind))
|
value := StoreEngine(strings.ToLower(kind))
|
||||||
|
if value == FileStoreEngine || value == SqliteStoreEngine || value == PostgresStoreEngine {
|
||||||
if value == FileStoreEngine || value == SqliteStoreEngine {
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,18 +105,60 @@ func NewStore(kind StoreEngine, dataDir string, metrics telemetry.AppMetrics) (S
|
|||||||
case SqliteStoreEngine:
|
case SqliteStoreEngine:
|
||||||
log.Info("using SQLite store engine")
|
log.Info("using SQLite store engine")
|
||||||
return NewSqliteStore(dataDir, metrics)
|
return NewSqliteStore(dataDir, metrics)
|
||||||
|
case PostgresStoreEngine:
|
||||||
|
log.Info("using Postgres store engine")
|
||||||
|
dsn, ok := os.LookupEnv(postgresDsnEnv)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%s is not set", postgresDsnEnv)
|
||||||
|
}
|
||||||
|
return NewPostgresqlStore(dsn, metrics)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported kind of store %s", kind)
|
return nil, fmt.Errorf("unsupported kind of store %s", kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStoreFromJson is only used in tests
|
// migrate migrates the SQLite database to the latest schema
|
||||||
func NewStoreFromJson(dataDir string, metrics telemetry.AppMetrics) (Store, error) {
|
func migrate(db *gorm.DB) error {
|
||||||
|
migrations := getMigrations()
|
||||||
|
|
||||||
|
for _, m := range migrations {
|
||||||
|
if err := m(db); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMigrations() []migrationFunc {
|
||||||
|
return []migrationFunc{
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.MigrateFieldFromGobToJSON[Account, net.IPNet](db, "network_net")
|
||||||
|
},
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.MigrateFieldFromGobToJSON[route.Route, netip.Prefix](db, "network")
|
||||||
|
},
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.MigrateFieldFromGobToJSON[route.Route, []string](db, "peer_groups")
|
||||||
|
},
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.MigrateNetIPFieldFromBlobToJSON[nbpeer.Peer](db, "location_connection_ip", "")
|
||||||
|
},
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.MigrateNetIPFieldFromBlobToJSON[nbpeer.Peer](db, "ip", "idx_peers_account_id_ip")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTestStoreFromJson is only used in tests
|
||||||
|
func NewTestStoreFromJson(dataDir string) (Store, func(), error) {
|
||||||
fstore, err := NewFileStore(dataDir, nil)
|
fstore, err := NewFileStore(dataDir, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanUp := func() {}
|
||||||
|
|
||||||
// if store engine is not set in the config we first try to evaluate NETBIRD_STORE_ENGINE
|
// if store engine is not set in the config we first try to evaluate NETBIRD_STORE_ENGINE
|
||||||
kind := getStoreEngineFromEnv()
|
kind := getStoreEngineFromEnv()
|
||||||
if kind == "" {
|
if kind == "" {
|
||||||
@@ -115,10 +168,64 @@ func NewStoreFromJson(dataDir string, metrics telemetry.AppMetrics) (Store, erro
|
|||||||
|
|
||||||
switch kind {
|
switch kind {
|
||||||
case FileStoreEngine:
|
case FileStoreEngine:
|
||||||
return fstore, nil
|
return fstore, cleanUp, nil
|
||||||
case SqliteStoreEngine:
|
case SqliteStoreEngine:
|
||||||
return NewSqliteStoreFromFileStore(fstore, dataDir, metrics)
|
store, err := NewSqliteStoreFromFileStore(fstore, dataDir, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return store, cleanUp, nil
|
||||||
|
case PostgresStoreEngine:
|
||||||
|
cleanUp, err = createPGDB()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dsn, ok := os.LookupEnv(postgresDsnEnv)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("%s is not set", postgresDsnEnv)
|
||||||
|
}
|
||||||
|
|
||||||
|
store, err := NewPostgresqlStoreFromFileStore(fstore, dsn, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return store, cleanUp, nil
|
||||||
default:
|
default:
|
||||||
return NewSqliteStoreFromFileStore(fstore, dataDir, metrics)
|
store, err := NewSqliteStoreFromFileStore(fstore, dataDir, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return store, cleanUp, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createPGDB() (func(), error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
c, err := postgres.RunContainer(ctx,
|
||||||
|
testcontainers.WithImage("postgres:alpine"),
|
||||||
|
postgres.WithDatabase("test"),
|
||||||
|
postgres.WithUsername("postgres"),
|
||||||
|
postgres.WithPassword("postgres"),
|
||||||
|
testcontainers.WithWaitStrategy(
|
||||||
|
wait.ForLog("database system is ready to accept connections").
|
||||||
|
WithOccurrence(2).WithStartupTimeout(15*time.Second)),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup := func() {
|
||||||
|
timeout := 10 * time.Second
|
||||||
|
err = c.Stop(ctx, &timeout)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("failed to stop container: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
talksConn, err := c.ConnectionString(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return cleanup, err
|
||||||
|
}
|
||||||
|
return cleanup, os.Setenv("NETBIRD_STORE_ENGINE_POSTGRES_DSN", talksConn)
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ const (
|
|||||||
|
|
||||||
func TestUser_CreatePAT_ForSameUser(t *testing.T) {
|
func TestUser_CreatePAT_ForSameUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -76,6 +77,7 @@ func TestUser_CreatePAT_ForSameUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_CreatePAT_ForDifferentUser(t *testing.T) {
|
func TestUser_CreatePAT_ForDifferentUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users[mockTargetUserId] = &User{
|
account.Users[mockTargetUserId] = &User{
|
||||||
Id: mockTargetUserId,
|
Id: mockTargetUserId,
|
||||||
@@ -97,6 +99,7 @@ func TestUser_CreatePAT_ForDifferentUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_CreatePAT_ForServiceUser(t *testing.T) {
|
func TestUser_CreatePAT_ForServiceUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users[mockTargetUserId] = &User{
|
account.Users[mockTargetUserId] = &User{
|
||||||
Id: mockTargetUserId,
|
Id: mockTargetUserId,
|
||||||
@@ -122,6 +125,7 @@ func TestUser_CreatePAT_ForServiceUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_CreatePAT_WithWrongExpiration(t *testing.T) {
|
func TestUser_CreatePAT_WithWrongExpiration(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -140,6 +144,7 @@ func TestUser_CreatePAT_WithWrongExpiration(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_CreatePAT_WithEmptyName(t *testing.T) {
|
func TestUser_CreatePAT_WithEmptyName(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -158,6 +163,7 @@ func TestUser_CreatePAT_WithEmptyName(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_DeletePAT(t *testing.T) {
|
func TestUser_DeletePAT(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users[mockUserID] = &User{
|
account.Users[mockUserID] = &User{
|
||||||
Id: mockUserID,
|
Id: mockUserID,
|
||||||
@@ -190,6 +196,7 @@ func TestUser_DeletePAT(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_GetPAT(t *testing.T) {
|
func TestUser_GetPAT(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users[mockUserID] = &User{
|
account.Users[mockUserID] = &User{
|
||||||
Id: mockUserID,
|
Id: mockUserID,
|
||||||
@@ -221,6 +228,7 @@ func TestUser_GetPAT(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_GetAllPATs(t *testing.T) {
|
func TestUser_GetAllPATs(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users[mockUserID] = &User{
|
account.Users[mockUserID] = &User{
|
||||||
Id: mockUserID,
|
Id: mockUserID,
|
||||||
@@ -322,6 +330,7 @@ func validateStruct(s interface{}) (err error) {
|
|||||||
|
|
||||||
func TestUser_CreateServiceUser(t *testing.T) {
|
func TestUser_CreateServiceUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -359,6 +368,7 @@ func TestUser_CreateServiceUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_CreateUser_ServiceUser(t *testing.T) {
|
func TestUser_CreateUser_ServiceUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -397,6 +407,7 @@ func TestUser_CreateUser_ServiceUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_CreateUser_RegularUser(t *testing.T) {
|
func TestUser_CreateUser_RegularUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -421,6 +432,7 @@ func TestUser_CreateUser_RegularUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_InviteNewUser(t *testing.T) {
|
func TestUser_InviteNewUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -549,6 +561,7 @@ func TestUser_DeleteUser_ServiceUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_DeleteUser_SelfDelete(t *testing.T) {
|
func TestUser_DeleteUser_SelfDelete(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -569,6 +582,7 @@ func TestUser_DeleteUser_SelfDelete(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_DeleteUser_regularUser(t *testing.T) {
|
func TestUser_DeleteUser_regularUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
targetId := "user2"
|
targetId := "user2"
|
||||||
@@ -650,6 +664,7 @@ func TestUser_DeleteUser_regularUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestDefaultAccountManager_GetUser(t *testing.T) {
|
func TestDefaultAccountManager_GetUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
|
|
||||||
err := store.SaveAccount(account)
|
err := store.SaveAccount(account)
|
||||||
@@ -678,6 +693,7 @@ func TestDefaultAccountManager_GetUser(t *testing.T) {
|
|||||||
|
|
||||||
func TestDefaultAccountManager_ListUsers(t *testing.T) {
|
func TestDefaultAccountManager_ListUsers(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users["normal_user1"] = NewRegularUser("normal_user1")
|
account.Users["normal_user1"] = NewRegularUser("normal_user1")
|
||||||
account.Users["normal_user2"] = NewRegularUser("normal_user2")
|
account.Users["normal_user2"] = NewRegularUser("normal_user2")
|
||||||
@@ -790,6 +806,7 @@ func TestDefaultAccountManager_ListUsers_DashboardPermissions(t *testing.T) {
|
|||||||
|
|
||||||
func TestDefaultAccountManager_ExternalCache(t *testing.T) {
|
func TestDefaultAccountManager_ExternalCache(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
externalUser := &User{
|
externalUser := &User{
|
||||||
Id: "externalUser",
|
Id: "externalUser",
|
||||||
@@ -853,6 +870,7 @@ func TestUser_IsAdmin(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) {
|
func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users[mockServiceUserID] = &User{
|
account.Users[mockServiceUserID] = &User{
|
||||||
Id: mockServiceUserID,
|
Id: mockServiceUserID,
|
||||||
@@ -880,6 +898,8 @@ func TestUser_GetUsersFromAccount_ForAdmin(t *testing.T) {
|
|||||||
|
|
||||||
func TestUser_GetUsersFromAccount_ForUser(t *testing.T) {
|
func TestUser_GetUsersFromAccount_ForUser(t *testing.T) {
|
||||||
store := newStore(t)
|
store := newStore(t)
|
||||||
|
defer store.Close()
|
||||||
|
|
||||||
account := newAccountWithId(mockAccountID, mockUserID, "")
|
account := newAccountWithId(mockAccountID, mockUserID, "")
|
||||||
account.Users[mockServiceUserID] = &User{
|
account.Users[mockServiceUserID] = &User{
|
||||||
Id: mockServiceUserID,
|
Id: mockServiceUserID,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ ARCH="$(uname -m)"
|
|||||||
PACKAGE_MANAGER="bin"
|
PACKAGE_MANAGER="bin"
|
||||||
INSTALL_DIR=""
|
INSTALL_DIR=""
|
||||||
SUDO=""
|
SUDO=""
|
||||||
|
IS_SYNOLOGY="false"
|
||||||
|
|
||||||
|
|
||||||
if command -v sudo > /dev/null && [ "$(id -u)" -ne 0 ]; then
|
if command -v sudo > /dev/null && [ "$(id -u)" -ne 0 ]; then
|
||||||
@@ -174,6 +175,15 @@ install_native_binaries() {
|
|||||||
if ! $SKIP_UI_APP; then
|
if ! $SKIP_UI_APP; then
|
||||||
download_release_binary "$UI_APP"
|
download_release_binary "$UI_APP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if "x-$IS_SYNOLOGY" = "x-true"; then
|
||||||
|
${SUDO} mkdir -p /etc/sysconfig
|
||||||
|
if ${SUDO} grep NB_WG_KERNEL_DISABLED /etc/sysconfig/netbird > /dev/null 2>&1; then
|
||||||
|
echo "NB_WG_KERNEL_DISABLED already set"
|
||||||
|
else
|
||||||
|
echo 'NB_WG_KERNEL_DISABLED=true' | ${SUDO} tee -a /etc/sysconfig/netbird
|
||||||
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_use_bin_variable() {
|
check_use_bin_variable() {
|
||||||
@@ -349,39 +359,56 @@ fi
|
|||||||
if type uname >/dev/null 2>&1; then
|
if type uname >/dev/null 2>&1; then
|
||||||
case "$(uname)" in
|
case "$(uname)" in
|
||||||
Linux)
|
Linux)
|
||||||
OS_NAME="$(. /etc/os-release && echo "$ID")"
|
OS_TYPE="linux"
|
||||||
OS_TYPE="linux"
|
UNAME_OUTPUT="$(uname -a)"
|
||||||
INSTALL_DIR="/usr/bin"
|
if echo "$UNAME_OUTPUT" | grep -qi "synology"; then
|
||||||
|
OS_NAME="synology"
|
||||||
|
INSTALL_DIR="/usr/local/bin"
|
||||||
|
PACKAGE_MANAGER="bin"
|
||||||
|
SKIP_UI_APP=true
|
||||||
|
IS_SYNOLOGY="true"
|
||||||
|
else
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
OS_NAME="$(. /etc/os-release && echo "$ID")"
|
||||||
|
INSTALL_DIR="/usr/bin"
|
||||||
|
|
||||||
# Allow netbird UI installation for x64 arch only
|
# Allow netbird UI installation for x64 arch only
|
||||||
if [ "$ARCH" != "amd64" ] && [ "$ARCH" != "arm64" ] \
|
if [ "$ARCH" != "amd64" ] && [ "$ARCH" != "arm64" ] \
|
||||||
&& [ "$ARCH" != "x86_64" ];then
|
&& [ "$ARCH" != "x86_64" ];then
|
||||||
SKIP_UI_APP=true
|
SKIP_UI_APP=true
|
||||||
echo "NetBird UI installation will be omitted as $ARCH is not a compatible architecture"
|
echo "NetBird UI installation will be omitted as $ARCH is not a compatible architecture"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Allow netbird UI installation for linux running desktop environment
|
# Allow netbird UI installation for linux running desktop environment
|
||||||
if [ -z "$XDG_CURRENT_DESKTOP" ];then
|
if [ -z "$XDG_CURRENT_DESKTOP" ];then
|
||||||
SKIP_UI_APP=true
|
SKIP_UI_APP=true
|
||||||
echo "NetBird UI installation will be omitted as Linux does not run desktop environment"
|
echo "NetBird UI installation will be omitted as Linux does not run desktop environment"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check the availability of a compatible package manager
|
# Check the availability of a compatible package manager
|
||||||
if check_use_bin_variable; then
|
if check_use_bin_variable; then
|
||||||
PACKAGE_MANAGER="bin"
|
PACKAGE_MANAGER="bin"
|
||||||
elif [ -x "$(command -v apt)" ]; then
|
elif [ -x "$(command -v apt-get)" ]; then
|
||||||
PACKAGE_MANAGER="apt"
|
PACKAGE_MANAGER="apt"
|
||||||
echo "The installation will be performed using apt package manager"
|
echo "The installation will be performed using apt package manager"
|
||||||
elif [ -x "$(command -v dnf)" ]; then
|
elif [ -x "$(command -v dnf)" ]; then
|
||||||
PACKAGE_MANAGER="dnf"
|
PACKAGE_MANAGER="dnf"
|
||||||
echo "The installation will be performed using dnf package manager"
|
echo "The installation will be performed using dnf package manager"
|
||||||
elif [ -x "$(command -v yum)" ]; then
|
elif [ -x "$(command -v yum)" ]; then
|
||||||
PACKAGE_MANAGER="yum"
|
PACKAGE_MANAGER="yum"
|
||||||
echo "The installation will be performed using yum package manager"
|
echo "The installation will be performed using yum package manager"
|
||||||
elif [ -x "$(command -v pacman)" ]; then
|
elif [ -x "$(command -v pacman)" ]; then
|
||||||
PACKAGE_MANAGER="pacman"
|
PACKAGE_MANAGER="pacman"
|
||||||
echo "The installation will be performed using pacman package manager"
|
echo "The installation will be performed using pacman package manager"
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "Unable to determine OS type from /etc/os-release"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
Darwin)
|
Darwin)
|
||||||
OS_NAME="macos"
|
OS_NAME="macos"
|
||||||
|
|||||||
Reference in New Issue
Block a user