diff --git a/cmd/gluetun/main.go b/cmd/gluetun/main.go index 28f80c1d..7baa1a51 100644 --- a/cmd/gluetun/main.go +++ b/cmd/gluetun/main.go @@ -126,8 +126,8 @@ var ( //nolint:gocognit,gocyclo,maintidx func _main(ctx context.Context, buildInfo models.BuildInformation, args []string, logger log.LoggerInterface, source sources.Source, - tun tun.Interface, netLinker netlink.NetLinker, cmder command.RunStarter, - cli cli.CLIer) error { + tun Tun, netLinker netLinker, cmder command.RunStarter, + cli clier) error { if len(args) > 1 { // cli operation switch args[1] { case "healthcheck": @@ -390,7 +390,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, "vpn", goroutine.OptionTimeout(time.Second)) go vpnLooper.Run(vpnCtx, vpnDone) - updaterLooper := updater.NewLooper(allSettings.Updater, + updaterLooper := updater.NewLoop(allSettings.Updater, providers, storage, httpClient, updaterLogger) updaterHandler, updaterCtx, updaterDone := goshutdown.NewGoRoutineHandler( "updater", goroutine.OptionTimeout(defaultShutdownTimeout)) @@ -411,7 +411,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, go httpProxyLooper.Run(httpProxyCtx, httpProxyDone) otherGroupHandler.Add(httpProxyHandler) - shadowsocksLooper := shadowsocks.NewLooper(allSettings.Shadowsocks, + shadowsocksLooper := shadowsocks.NewLoop(allSettings.Shadowsocks, logger.New(log.SetComponent("shadowsocks"))) shadowsocksHandler, shadowsocksCtx, shadowsocksDone := goshutdown.NewGoRoutineHandler( "shadowsocks proxy", goroutine.OptionTimeout(defaultShutdownTimeout)) @@ -480,3 +480,38 @@ func printVersions(ctx context.Context, logger infoer, return nil } + +type netLinker interface { + AddrList(link netlink.Link, family int) ( + addresses []netlink.Addr, err error) + AddrAdd(link netlink.Link, addr *netlink.Addr) error + IsWireguardSupported() (ok bool, err error) + RouteList(link netlink.Link, family int) ( + routes []netlink.Route, err error) + RouteAdd(route *netlink.Route) error + RouteDel(route *netlink.Route) error + RouteReplace(route *netlink.Route) error + RuleList(family int) (rules []netlink.Rule, err error) + RuleAdd(rule *netlink.Rule) error + RuleDel(rule *netlink.Rule) error + LinkList() (links []netlink.Link, err error) + LinkByName(name string) (link netlink.Link, err error) + LinkByIndex(index int) (link netlink.Link, err error) + LinkAdd(link netlink.Link) (err error) + LinkDel(link netlink.Link) (err error) + LinkSetUp(link netlink.Link) (err error) + LinkSetDown(link netlink.Link) (err error) +} + +type clier interface { + ClientKey(args []string) error + FormatServers(args []string) error + OpenvpnConfig(logger cli.OpenvpnConfigLogger, source sources.Source) error + HealthCheck(ctx context.Context, source sources.Source, warner cli.Warner) error + Update(ctx context.Context, args []string, logger cli.UpdaterLogger) error +} + +type Tun interface { + Check(tunDevice string) error + Create(tunDevice string) error +} diff --git a/internal/alpine/alpine.go b/internal/alpine/alpine.go index afd599fb..9bacd5a6 100644 --- a/internal/alpine/alpine.go +++ b/internal/alpine/alpine.go @@ -5,13 +5,6 @@ import ( "os/user" ) -var _ Alpiner = (*Alpine)(nil) - -type Alpiner interface { - UserCreater - VersionGetter -} - type Alpine struct { alpineReleasePath string passwdPath string diff --git a/internal/alpine/users.go b/internal/alpine/users.go index bda922ca..3e267075 100644 --- a/internal/alpine/users.go +++ b/internal/alpine/users.go @@ -12,10 +12,6 @@ var ( ErrUserAlreadyExists = errors.New("user already exists") ) -type UserCreater interface { - CreateUser(username string, uid int) (createdUsername string, err error) -} - // CreateUser creates a user in Alpine with the given UID. func (a *Alpine) CreateUser(username string, uid int) (createdUsername string, err error) { UIDStr := strconv.Itoa(uid) diff --git a/internal/alpine/version.go b/internal/alpine/version.go index 972d386c..6d17bad6 100644 --- a/internal/alpine/version.go +++ b/internal/alpine/version.go @@ -7,10 +7,6 @@ import ( "strings" ) -type VersionGetter interface { - Version(ctx context.Context) (version string, err error) -} - func (a *Alpine) Version(ctx context.Context) (version string, err error) { file, err := os.OpenFile(a.alpineReleasePath, os.O_RDONLY, 0) if err != nil { diff --git a/internal/cli/cli.go b/internal/cli/cli.go index ebc47bf9..a6de4c7b 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -1,16 +1,6 @@ // Package cli defines an interface CLI to run command line operations. package cli -var _ CLIer = (*CLI)(nil) - -type CLIer interface { - ClientKeyFormatter - HealthChecker - OpenvpnConfigMaker - Updater - ServersFormatter -} - type CLI struct { repoServersPath string } diff --git a/internal/cli/clientkey.go b/internal/cli/clientkey.go index d95c242d..6a4204ba 100644 --- a/internal/cli/clientkey.go +++ b/internal/cli/clientkey.go @@ -10,10 +10,6 @@ import ( "github.com/qdm12/gluetun/internal/configuration/sources/files" ) -type ClientKeyFormatter interface { - ClientKey(args []string) error -} - func (c *CLI) ClientKey(args []string) error { flagSet := flag.NewFlagSet("clientkey", flag.ExitOnError) filepath := flagSet.String("path", files.OpenVPNClientKeyPath, "file path to the client.key file") diff --git a/internal/cli/formatservers.go b/internal/cli/formatservers.go index f0aad72c..d0ad62df 100644 --- a/internal/cli/formatservers.go +++ b/internal/cli/formatservers.go @@ -15,10 +15,6 @@ import ( "golang.org/x/text/language" ) -type ServersFormatter interface { - FormatServers(args []string) error -} - var ( ErrFormatNotRecognized = errors.New("format is not recognized") ErrProviderUnspecified = errors.New("VPN provider to format was not specified") diff --git a/internal/cli/healthcheck.go b/internal/cli/healthcheck.go index 2dcf8e17..90c13e3d 100644 --- a/internal/cli/healthcheck.go +++ b/internal/cli/healthcheck.go @@ -10,10 +10,6 @@ import ( "github.com/qdm12/gluetun/internal/healthcheck" ) -type HealthChecker interface { - HealthCheck(ctx context.Context, source sources.Source, warner Warner) error -} - func (c *CLI) HealthCheck(ctx context.Context, source sources.Source, warner Warner) error { // Extract the health server port from the configuration. config, err := source.ReadHealth() diff --git a/internal/cli/openvpnconfig.go b/internal/cli/openvpnconfig.go index e8f0298f..a07d96e0 100644 --- a/internal/cli/openvpnconfig.go +++ b/internal/cli/openvpnconfig.go @@ -1,6 +1,7 @@ package cli import ( + "context" "fmt" "net/http" "strings" @@ -10,18 +11,18 @@ import ( "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/provider" "github.com/qdm12/gluetun/internal/storage" - "github.com/qdm12/gluetun/internal/updater/unzip" ) -type OpenvpnConfigMaker interface { - OpenvpnConfig(logger OpenvpnConfigLogger, source sources.Source) error -} - type OpenvpnConfigLogger interface { Info(s string) Warn(s string) } +type Unzipper interface { + FetchAndExtract(ctx context.Context, url string) ( + contents map[string][]byte, err error) +} + func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, source sources.Source) error { storage, err := storage.New(logger, constants.ServersData) if err != nil { @@ -38,7 +39,7 @@ func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, source sources.Source) e } // Unused by this CLI command - unzipper := (unzip.Unzipper)(nil) + unzipper := (Unzipper)(nil) client := (*http.Client)(nil) warner := (Warner)(nil) diff --git a/internal/cli/update.go b/internal/cli/update.go index d65b45b1..3256dded 100644 --- a/internal/cli/update.go +++ b/internal/cli/update.go @@ -25,10 +25,6 @@ var ( ErrNoProviderSpecified = errors.New("no provider was specified") ) -type Updater interface { - Update(ctx context.Context, args []string, logger UpdaterLogger) error -} - type UpdaterLogger interface { Info(s string) Warn(s string) diff --git a/internal/dns/interfaces.go b/internal/dns/interfaces.go new file mode 100644 index 00000000..a6308272 --- /dev/null +++ b/internal/dns/interfaces.go @@ -0,0 +1,29 @@ +package dns + +import ( + "context" + + "github.com/qdm12/dns/pkg/unbound" + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/models" +) + +type Configurator interface { + SetupFiles(ctx context.Context) error + MakeUnboundConf(settings unbound.Settings) (err error) + Start(ctx context.Context, verbosityDetailsLevel uint8) ( + stdoutLines, stderrLines chan string, waitError chan error, err error) + Version(ctx context.Context) (version string, err error) +} + +type statusManager interface { + GetStatus() (status models.LoopStatus) + SetStatus(status models.LoopStatus) + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} + +type stateManager interface { + GetSettings() (settings settings.DNS) + SetSettings(ctx context.Context, settings settings.DNS) (outcome string) +} diff --git a/internal/dns/loop.go b/internal/dns/loop.go index 8206ed75..44d76ace 100644 --- a/internal/dns/loop.go +++ b/internal/dns/loop.go @@ -7,7 +7,6 @@ import ( "time" "github.com/qdm12/dns/pkg/blacklist" - "github.com/qdm12/dns/pkg/unbound" "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/dns/state" @@ -15,20 +14,10 @@ import ( "github.com/qdm12/gluetun/internal/models" ) -var _ Looper = (*Loop)(nil) - -type Looper interface { - Runner - RestartTickerRunner - loopstate.Applier - loopstate.Getter - SettingsGetSetter -} - type Loop struct { - statusManager loopstate.Manager - state state.Manager - conf unbound.Configurator + statusManager statusManager + state stateManager + conf Configurator resolvConf string blockBuilder blacklist.Builder client *http.Client @@ -46,7 +35,7 @@ type Loop struct { const defaultBackoffTime = 10 * time.Second -func NewLoop(conf unbound.Configurator, settings settings.DNS, +func NewLoop(conf Configurator, settings settings.DNS, client *http.Client, logger Logger) *Loop { start := make(chan struct{}) running := make(chan models.LoopStatus) diff --git a/internal/dns/run.go b/internal/dns/run.go index dcf1a1c4..4a8ea264 100644 --- a/internal/dns/run.go +++ b/internal/dns/run.go @@ -7,10 +7,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type Runner interface { - Run(ctx context.Context, done chan<- struct{}) -} - func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) diff --git a/internal/dns/settings.go b/internal/dns/settings.go index ba975ac7..71744c95 100644 --- a/internal/dns/settings.go +++ b/internal/dns/settings.go @@ -6,22 +6,8 @@ import ( "github.com/qdm12/gluetun/internal/configuration/settings" ) -type SettingsGetSetter interface { - SettingsGetter - SettingsSetter -} - -type SettingsGetter interface { - GetSettings() (settings settings.DNS) -} - func (l *Loop) GetSettings() (settings settings.DNS) { return l.state.GetSettings() } -type SettingsSetter interface { - SetSettings(ctx context.Context, settings settings.DNS) ( - outcome string) -} - func (l *Loop) SetSettings(ctx context.Context, settings settings.DNS) ( outcome string) { return l.state.SetSettings(ctx, settings) diff --git a/internal/dns/state/settings.go b/internal/dns/state/settings.go index d90f5984..432a42aa 100644 --- a/internal/dns/state/settings.go +++ b/internal/dns/state/settings.go @@ -8,12 +8,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type SettingsGetSetter interface { - GetSettings() (settings settings.DNS) - SetSettings(ctx context.Context, - settings settings.DNS) (outcome string) -} - func (s *State) GetSettings() (settings settings.DNS) { s.settingsMu.RLock() defer s.settingsMu.RUnlock() diff --git a/internal/dns/state/state.go b/internal/dns/state/state.go index a0edda22..b3419559 100644 --- a/internal/dns/state/state.go +++ b/internal/dns/state/state.go @@ -1,19 +1,14 @@ package state import ( + "context" "sync" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/loopstate" + "github.com/qdm12/gluetun/internal/models" ) -var _ Manager = (*State)(nil) - -type Manager interface { - SettingsGetSetter -} - -func New(statusApplier loopstate.Applier, +func New(statusApplier StatusApplier, settings settings.DNS, updateTicker chan<- struct{}) *State { return &State{ @@ -24,10 +19,15 @@ func New(statusApplier loopstate.Applier, } type State struct { - statusApplier loopstate.Applier + statusApplier StatusApplier settings settings.DNS settingsMu sync.RWMutex updateTicker chan<- struct{} } + +type StatusApplier interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} diff --git a/internal/dns/ticker.go b/internal/dns/ticker.go index e5c1d551..7076092e 100644 --- a/internal/dns/ticker.go +++ b/internal/dns/ticker.go @@ -7,10 +7,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type RestartTickerRunner interface { - RunRestartTicker(ctx context.Context, done chan<- struct{}) -} - func (l *Loop) RunRestartTicker(ctx context.Context, done chan<- struct{}) { defer close(done) // Timer that acts as a ticker diff --git a/internal/firewall/enable.go b/internal/firewall/enable.go index bf8b20ca..37487174 100644 --- a/internal/firewall/enable.go +++ b/internal/firewall/enable.go @@ -5,10 +5,6 @@ import ( "fmt" ) -type Enabler interface { - SetEnabled(ctx context.Context, enabled bool) (err error) -} - func (c *Config) SetEnabled(ctx context.Context, enabled bool) (err error) { c.stateMutex.Lock() defer c.stateMutex.Unlock() diff --git a/internal/firewall/firewall.go b/internal/firewall/firewall.go index e829b6e7..6d52c17f 100644 --- a/internal/firewall/firewall.go +++ b/internal/firewall/firewall.go @@ -12,16 +12,6 @@ import ( "github.com/qdm12/golibs/command" ) -var _ Configurator = (*Config)(nil) - -// Configurator allows to change firewall rules and modify network routes. -type Configurator interface { - Enabler - VPNConnectionSetter - PortAllower - OutboundSubnetsSetter -} - type Config struct { //nolint:maligned runner command.Runner logger Logger diff --git a/internal/firewall/outboundsubnets.go b/internal/firewall/outboundsubnets.go index c5291f73..92cb7de6 100644 --- a/internal/firewall/outboundsubnets.go +++ b/internal/firewall/outboundsubnets.go @@ -8,10 +8,6 @@ import ( "github.com/qdm12/gluetun/internal/subnet" ) -type OutboundSubnetsSetter interface { - SetOutboundSubnets(ctx context.Context, subnets []net.IPNet) (err error) -} - func (c *Config) SetOutboundSubnets(ctx context.Context, subnets []net.IPNet) (err error) { c.stateMutex.Lock() defer c.stateMutex.Unlock() diff --git a/internal/firewall/ports.go b/internal/firewall/ports.go index efed4552..4db955e6 100644 --- a/internal/firewall/ports.go +++ b/internal/firewall/ports.go @@ -6,11 +6,6 @@ import ( "strconv" ) -type PortAllower interface { - SetAllowedPort(ctx context.Context, port uint16, intf string) (err error) - RemoveAllowedPort(ctx context.Context, port uint16) (err error) -} - func (c *Config) SetAllowedPort(ctx context.Context, port uint16, intf string) (err error) { c.stateMutex.Lock() defer c.stateMutex.Unlock() diff --git a/internal/firewall/vpn.go b/internal/firewall/vpn.go index 9c48fc35..7b228c89 100644 --- a/internal/firewall/vpn.go +++ b/internal/firewall/vpn.go @@ -7,11 +7,6 @@ import ( "github.com/qdm12/gluetun/internal/models" ) -type VPNConnectionSetter interface { - SetVPNConnection(ctx context.Context, - connection models.Connection, vpnIntf string) error -} - func (c *Config) SetVPNConnection(ctx context.Context, connection models.Connection, vpnIntf string) (err error) { c.stateMutex.Lock() diff --git a/internal/healthcheck/client.go b/internal/healthcheck/client.go index 8535a552..f8991483 100644 --- a/internal/healthcheck/client.go +++ b/internal/healthcheck/client.go @@ -12,12 +12,6 @@ var ( ErrHTTPStatusNotOK = errors.New("HTTP response status is not OK") ) -var _ Checker = (*Client)(nil) - -type Checker interface { - Check(ctx context.Context, url string) error -} - type Client struct { httpClient *http.Client } diff --git a/internal/healthcheck/openvpn.go b/internal/healthcheck/openvpn.go index e3c8d7b2..a234a062 100644 --- a/internal/healthcheck/openvpn.go +++ b/internal/healthcheck/openvpn.go @@ -5,11 +5,10 @@ import ( "time" "github.com/qdm12/gluetun/internal/constants" - "github.com/qdm12/gluetun/internal/vpn" ) type vpnHealth struct { - looper vpn.Looper + loop StatusApplier healthyWait time.Duration healthyTimer *time.Timer } @@ -17,8 +16,8 @@ type vpnHealth struct { func (s *Server) onUnhealthyVPN(ctx context.Context) { s.logger.Info("program has been unhealthy for " + s.vpn.healthyWait.String() + ": restarting VPN") - _, _ = s.vpn.looper.ApplyStatus(ctx, constants.Stopped) - _, _ = s.vpn.looper.ApplyStatus(ctx, constants.Running) + _, _ = s.vpn.loop.ApplyStatus(ctx, constants.Stopped) + _, _ = s.vpn.loop.ApplyStatus(ctx, constants.Running) s.vpn.healthyWait += *s.config.VPN.Addition s.vpn.healthyTimer = time.NewTimer(s.vpn.healthyWait) } diff --git a/internal/healthcheck/server.go b/internal/healthcheck/server.go index 1c45f705..6402f518 100644 --- a/internal/healthcheck/server.go +++ b/internal/healthcheck/server.go @@ -5,15 +5,9 @@ import ( "net" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/vpn" + "github.com/qdm12/gluetun/internal/models" ) -var _ ServerRunner = (*Server)(nil) - -type ServerRunner interface { - Run(ctx context.Context, done chan<- struct{}) -} - type Server struct { logger Logger handler *handler @@ -23,15 +17,20 @@ type Server struct { } func NewServer(config settings.Health, - logger Logger, vpnLooper vpn.Looper) *Server { + logger Logger, vpnLoop StatusApplier) *Server { return &Server{ logger: logger, handler: newHandler(), dialer: &net.Dialer{}, config: config, vpn: vpnHealth{ - looper: vpnLooper, + loop: vpnLoop, healthyWait: *config.VPN.Initial, }, } } + +type StatusApplier interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} diff --git a/internal/httpproxy/loop.go b/internal/httpproxy/loop.go index 0c357272..c87f9c61 100644 --- a/internal/httpproxy/loop.go +++ b/internal/httpproxy/loop.go @@ -12,18 +12,9 @@ import ( "github.com/qdm12/gluetun/internal/models" ) -var _ Looper = (*Loop)(nil) - -type Looper interface { - Runner - loopstate.Getter - loopstate.Applier - SettingsGetSetter -} - type Loop struct { - statusManager loopstate.Manager - state state.Manager + statusManager statusManager + state StateManager // Other objects logger Logger // Internal channels and locks @@ -34,6 +25,18 @@ type Loop struct { backoffTime time.Duration } +type statusManager interface { + GetStatus() (status models.LoopStatus) + SetStatus(status models.LoopStatus) + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} + +type StateManager interface { + GetSettings() settings.HTTPProxy + SetSettings(ctx context.Context, settings settings.HTTPProxy) (outcome string) +} + const defaultBackoffTime = 10 * time.Second func NewLoop(logger Logger, settings settings.HTTPProxy) *Loop { diff --git a/internal/httpproxy/run.go b/internal/httpproxy/run.go index 66f37f6d..4248c9c8 100644 --- a/internal/httpproxy/run.go +++ b/internal/httpproxy/run.go @@ -6,10 +6,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type Runner interface { - Run(ctx context.Context, done chan<- struct{}) -} - func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) diff --git a/internal/httpproxy/settings.go b/internal/httpproxy/settings.go index 3fc5f904..48cef59c 100644 --- a/internal/httpproxy/settings.go +++ b/internal/httpproxy/settings.go @@ -4,11 +4,8 @@ import ( "context" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/httpproxy/state" ) -type SettingsGetSetter = state.SettingsGetSetter - func (l *Loop) GetSettings() (settings settings.HTTPProxy) { return l.state.GetSettings() } diff --git a/internal/httpproxy/state/settings.go b/internal/httpproxy/state/settings.go index 58846c4f..7829ffe1 100644 --- a/internal/httpproxy/state/settings.go +++ b/internal/httpproxy/state/settings.go @@ -8,26 +8,12 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type SettingsGetSetter interface { - SettingsGetter - SettingsSetter -} - -type SettingsGetter interface { - GetSettings() (settings settings.HTTPProxy) -} - func (s *State) GetSettings() (settings settings.HTTPProxy) { s.settingsMu.RLock() defer s.settingsMu.RUnlock() return s.settings } -type SettingsSetter interface { - SetSettings(ctx context.Context, - settings settings.HTTPProxy) (outcome string) -} - func (s *State) SetSettings(ctx context.Context, settings settings.HTTPProxy) (outcome string) { s.settingsMu.Lock() diff --git a/internal/httpproxy/state/state.go b/internal/httpproxy/state/state.go index 930cfd8a..e611ad85 100644 --- a/internal/httpproxy/state/state.go +++ b/internal/httpproxy/state/state.go @@ -1,19 +1,14 @@ package state import ( + "context" "sync" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/loopstate" + "github.com/qdm12/gluetun/internal/models" ) -var _ Manager = (*State)(nil) - -type Manager interface { - SettingsGetSetter -} - -func New(statusApplier loopstate.Applier, +func New(statusApplier StatusApplier, settings settings.HTTPProxy) *State { return &State{ statusApplier: statusApplier, @@ -22,7 +17,12 @@ func New(statusApplier loopstate.Applier, } type State struct { - statusApplier loopstate.Applier + statusApplier StatusApplier settings settings.HTTPProxy settingsMu sync.RWMutex } + +type StatusApplier interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} diff --git a/internal/httpserver/server.go b/internal/httpserver/server.go index 3c2562f0..3cf1b296 100644 --- a/internal/httpserver/server.go +++ b/internal/httpserver/server.go @@ -2,30 +2,11 @@ package httpserver import ( - "context" "fmt" "net/http" "time" ) -var _ Interface = (*Server)(nil) - -// Interface is the HTTP server composite interface. -type Interface interface { - Runner - AddressGetter -} - -// Runner is the interface for an HTTP server with a Run method. -type Runner interface { - Run(ctx context.Context, ready chan<- struct{}, done chan<- struct{}) -} - -// AddressGetter obtains the address the HTTP server is listening on. -type AddressGetter interface { - GetAddress() (address string) -} - // Server is an HTTP server implementation, which uses // the HTTP handler provided. type Server struct { diff --git a/internal/loopstate/apply.go b/internal/loopstate/apply.go index d48eda6c..8903364c 100644 --- a/internal/loopstate/apply.go +++ b/internal/loopstate/apply.go @@ -9,11 +9,6 @@ import ( "github.com/qdm12/gluetun/internal/models" ) -type Applier interface { - ApplyStatus(ctx context.Context, status models.LoopStatus) ( - outcome string, err error) -} - var ErrInvalidStatus = errors.New("invalid status") // ApplyStatus sends signals to the running loop depending on the diff --git a/internal/loopstate/get.go b/internal/loopstate/get.go index fb675dfa..225fd1c6 100644 --- a/internal/loopstate/get.go +++ b/internal/loopstate/get.go @@ -2,10 +2,6 @@ package loopstate import "github.com/qdm12/gluetun/internal/models" -type Getter interface { - GetStatus() (status models.LoopStatus) -} - // GetStatus gets the status thread safely. func (s *State) GetStatus() (status models.LoopStatus) { s.statusMu.RLock() diff --git a/internal/loopstate/lock.go b/internal/loopstate/lock.go index 3907fef4..fde03799 100644 --- a/internal/loopstate/lock.go +++ b/internal/loopstate/lock.go @@ -1,9 +1,4 @@ package loopstate -type Locker interface { - Lock() - Unlock() -} - func (s *State) Lock() { s.loopMu.Lock() } func (s *State) Unlock() { s.loopMu.Unlock() } diff --git a/internal/loopstate/set.go b/internal/loopstate/set.go index 69f52b00..098a7355 100644 --- a/internal/loopstate/set.go +++ b/internal/loopstate/set.go @@ -2,10 +2,6 @@ package loopstate import "github.com/qdm12/gluetun/internal/models" -type Setter interface { - SetStatus(status models.LoopStatus) -} - // SetStatus sets the status thread safely. // It should only be called by the loop internal code since // it does not interact with the loop code directly. diff --git a/internal/loopstate/state.go b/internal/loopstate/state.go index a19d413c..bbbe9335 100644 --- a/internal/loopstate/state.go +++ b/internal/loopstate/state.go @@ -6,15 +6,6 @@ import ( "github.com/qdm12/gluetun/internal/models" ) -var _ Manager = (*State)(nil) - -type Manager interface { - Locker - Getter - Setter - Applier -} - func New(status models.LoopStatus, start chan<- struct{}, running <-chan models.LoopStatus, stop chan<- struct{}, stopped <-chan struct{}) *State { diff --git a/internal/netlink/address.go b/internal/netlink/address.go index 6b28b02d..245c2f58 100644 --- a/internal/netlink/address.go +++ b/internal/netlink/address.go @@ -4,14 +4,6 @@ import "github.com/vishvananda/netlink" type Addr = netlink.Addr -var _ Addresser = (*NetLink)(nil) - -type Addresser interface { - AddrList(link netlink.Link, family int) ( - addresses []netlink.Addr, err error) - AddrAdd(link netlink.Link, addr *netlink.Addr) error -} - func (n *NetLink) AddrList(link Link, family int) ( addresses []Addr, err error) { return netlink.AddrList(link, family) diff --git a/internal/netlink/family.go b/internal/netlink/family.go index 6745b67c..922e6777 100644 --- a/internal/netlink/family.go +++ b/internal/netlink/family.go @@ -13,10 +13,6 @@ const ( FAMILY_V6 = netlink.FAMILY_V6 ) -type WireguardChecker interface { - IsWireguardSupported() (ok bool, err error) -} - func (n *NetLink) IsWireguardSupported() (ok bool, err error) { families, err := netlink.GenlFamilyList() if err != nil { diff --git a/internal/netlink/interface.go b/internal/netlink/interface.go deleted file mode 100644 index 8cb56254..00000000 --- a/internal/netlink/interface.go +++ /dev/null @@ -1,13 +0,0 @@ -package netlink - -//go:generate mockgen -destination=mock_$GOPACKAGE/$GOFILE . NetLinker - -var _ NetLinker = (*NetLink)(nil) - -type NetLinker interface { - Addresser - Linker - Router - Ruler - WireguardChecker -} diff --git a/internal/netlink/link.go b/internal/netlink/link.go index 84d886b5..13ff28f3 100644 --- a/internal/netlink/link.go +++ b/internal/netlink/link.go @@ -8,18 +8,6 @@ type ( Wireguard = netlink.Wireguard ) -var _ Linker = (*NetLink)(nil) - -type Linker interface { - LinkList() (links []netlink.Link, err error) - LinkByName(name string) (link netlink.Link, err error) - LinkByIndex(index int) (link netlink.Link, err error) - LinkAdd(link netlink.Link) (err error) - LinkDel(link netlink.Link) (err error) - LinkSetUp(link netlink.Link) (err error) - LinkSetDown(link netlink.Link) (err error) -} - func (n *NetLink) LinkList() (links []Link, err error) { return netlink.LinkList() } diff --git a/internal/netlink/route.go b/internal/netlink/route.go index 1e6e7c9c..171a6d1a 100644 --- a/internal/netlink/route.go +++ b/internal/netlink/route.go @@ -4,16 +4,6 @@ import "github.com/vishvananda/netlink" type Route = netlink.Route -var _ Router = (*NetLink)(nil) - -type Router interface { - RouteList(link netlink.Link, family int) ( - routes []netlink.Route, err error) - RouteAdd(route *netlink.Route) error - RouteDel(route *netlink.Route) error - RouteReplace(route *netlink.Route) error -} - func (n *NetLink) RouteList(link Link, family int) ( routes []Route, err error) { return netlink.RouteList(link, family) diff --git a/internal/netlink/rule.go b/internal/netlink/rule.go index ca8642cb..8fcdd38b 100644 --- a/internal/netlink/rule.go +++ b/internal/netlink/rule.go @@ -8,14 +8,6 @@ func NewRule() *Rule { return netlink.NewRule() } -var _ Ruler = (*NetLink)(nil) - -type Ruler interface { - RuleList(family int) (rules []netlink.Rule, err error) - RuleAdd(rule *netlink.Rule) error - RuleDel(rule *netlink.Rule) error -} - func (n *NetLink) RuleList(family int) (rules []Rule, err error) { return netlink.RuleList(family) } diff --git a/internal/openvpn/auth.go b/internal/openvpn/auth.go index 885995bd..b47fe06a 100644 --- a/internal/openvpn/auth.go +++ b/internal/openvpn/auth.go @@ -6,10 +6,6 @@ import ( "strings" ) -type AuthWriter interface { - WriteAuthFile(user, password string) error -} - // WriteAuthFile writes the OpenVPN auth file to disk with the right permissions. func (c *Configurator) WriteAuthFile(user, password string) error { file, err := os.Open(c.authFilePath) diff --git a/internal/openvpn/config.go b/internal/openvpn/config.go index 77a7006a..07e2c8fb 100644 --- a/internal/openvpn/config.go +++ b/internal/openvpn/config.go @@ -5,10 +5,6 @@ import ( "strings" ) -type Writer interface { - WriteConfig(lines []string) error -} - func (c *Configurator) WriteConfig(lines []string) error { file, err := os.OpenFile(c.configPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) if err != nil { diff --git a/internal/openvpn/extract/extractor.go b/internal/openvpn/extract/extractor.go index a40614aa..6f59f92e 100644 --- a/internal/openvpn/extract/extractor.go +++ b/internal/openvpn/extract/extractor.go @@ -1,16 +1,5 @@ package extract -import ( - "github.com/qdm12/gluetun/internal/models" -) - -var _ Interface = (*Extractor)(nil) - -type Interface interface { - Data(filepath string) (lines []string, - connection models.Connection, err error) -} - type Extractor struct{} func New() *Extractor { diff --git a/internal/openvpn/openvpn.go b/internal/openvpn/openvpn.go index 62b16a1b..e8fdb4cb 100644 --- a/internal/openvpn/openvpn.go +++ b/internal/openvpn/openvpn.go @@ -5,14 +5,6 @@ import ( "github.com/qdm12/golibs/command" ) -var _ Interface = (*Configurator)(nil) - -type Interface interface { - VersionGetter - AuthWriter - Writer -} - type Configurator struct { logger Infoer cmder command.RunStarter diff --git a/internal/openvpn/version.go b/internal/openvpn/version.go index 65bd2c55..19df6605 100644 --- a/internal/openvpn/version.go +++ b/internal/openvpn/version.go @@ -8,11 +8,6 @@ import ( "strings" ) -type VersionGetter interface { - Version24(ctx context.Context) (version string, err error) - Version25(ctx context.Context) (version string, err error) -} - func (c *Configurator) Version24(ctx context.Context) (version string, err error) { return c.version(ctx, binOpenvpn24) } diff --git a/internal/portforward/get.go b/internal/portforward/get.go index 90722df6..4078ec56 100644 --- a/internal/portforward/get.go +++ b/internal/portforward/get.go @@ -1,9 +1,5 @@ package portforward -import "github.com/qdm12/gluetun/internal/portforward/state" - -type Getter = state.PortForwardedGetter - func (l *Loop) GetPortForwarded() (port uint16) { return l.state.GetPortForwarded() } diff --git a/internal/portforward/interfaces.go b/internal/portforward/interfaces.go new file mode 100644 index 00000000..428b1333 --- /dev/null +++ b/internal/portforward/interfaces.go @@ -0,0 +1,30 @@ +package portforward + +import ( + "context" + + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/models" +) + +type PortAllower interface { + SetAllowedPort(ctx context.Context, port uint16, intf string) (err error) + RemoveAllowedPort(ctx context.Context, port uint16) (err error) +} + +type statusManager interface { + GetStatus() (status models.LoopStatus) + SetStatus(status models.LoopStatus) + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} + +type StateManager interface { + GetSettings() (settings settings.PortForwarding) + SetSettings(ctx context.Context, + settings settings.PortForwarding) (outcome string) + GetPortForwarded() (port uint16) + SetPortForwarded(port uint16) + GetStartData() (startData StartData) + SetStartData(startData StartData) +} diff --git a/internal/portforward/loop.go b/internal/portforward/loop.go index 84a118af..b3f8e24b 100644 --- a/internal/portforward/loop.go +++ b/internal/portforward/loop.go @@ -7,28 +7,17 @@ import ( "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" - "github.com/qdm12/gluetun/internal/firewall" "github.com/qdm12/gluetun/internal/loopstate" "github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/portforward/state" ) -var _ Looper = (*Loop)(nil) - -type Looper interface { - Runner - loopstate.Getter - StartStopper - SettingsGetSetter - Getter -} - type Loop struct { - statusManager loopstate.Manager - state state.Manager + statusManager statusManager + state StateManager // Objects client *http.Client - portAllower firewall.PortAllower + portAllower PortAllower logger Logger // Internal channels and locks start chan struct{} @@ -43,7 +32,7 @@ type Loop struct { const defaultBackoffTime = 5 * time.Second func NewLoop(settings settings.PortForwarding, - client *http.Client, portAllower firewall.PortAllower, + client *http.Client, portAllower PortAllower, logger Logger) *Loop { start := make(chan struct{}) running := make(chan models.LoopStatus) diff --git a/internal/portforward/run.go b/internal/portforward/run.go index f4411972..1e1e9d51 100644 --- a/internal/portforward/run.go +++ b/internal/portforward/run.go @@ -7,10 +7,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type Runner interface { - Run(ctx context.Context, done chan<- struct{}) -} - func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) diff --git a/internal/portforward/settings.go b/internal/portforward/settings.go index db77b23f..a72d8a17 100644 --- a/internal/portforward/settings.go +++ b/internal/portforward/settings.go @@ -4,11 +4,8 @@ import ( "context" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/portforward/state" ) -type SettingsGetSetter = state.SettingsGetSetter - func (l *Loop) GetSettings() (settings settings.PortForwarding) { return l.state.GetSettings() } diff --git a/internal/portforward/state/portforwarded.go b/internal/portforward/state/portforwarded.go index ebb87f81..f11b0aae 100644 --- a/internal/portforward/state/portforwarded.go +++ b/internal/portforward/state/portforwarded.go @@ -1,14 +1,5 @@ package state -type PortForwardedGetterSetter interface { - PortForwardedGetter - SetPortForwarded(port uint16) -} - -type PortForwardedGetter interface { - GetPortForwarded() (port uint16) -} - // GetPortForwarded is used by the control HTTP server // to obtain the port currently forwarded. func (s *State) GetPortForwarded() (port uint16) { diff --git a/internal/portforward/state/settings.go b/internal/portforward/state/settings.go index 06e624c6..fe6d629e 100644 --- a/internal/portforward/state/settings.go +++ b/internal/portforward/state/settings.go @@ -9,12 +9,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type SettingsGetSetter interface { - GetSettings() (settings settings.PortForwarding) - SetSettings(ctx context.Context, - settings settings.PortForwarding) (outcome string) -} - func (s *State) GetSettings() (settings settings.PortForwarding) { s.settingsMu.RLock() defer s.settingsMu.RUnlock() diff --git a/internal/portforward/state/startdata.go b/internal/portforward/state/startdata.go index b912557b..e7511362 100644 --- a/internal/portforward/state/startdata.go +++ b/internal/portforward/state/startdata.go @@ -13,25 +13,12 @@ type StartData struct { Interface string // tun0 for example } -type StartDataGetterSetter interface { - StartDataGetter - StartDataSetter -} - -type StartDataGetter interface { - GetStartData() (startData StartData) -} - func (s *State) GetStartData() (startData StartData) { s.startDataMu.RLock() defer s.startDataMu.RUnlock() return s.startData } -type StartDataSetter interface { - SetStartData(startData StartData) -} - func (s *State) SetStartData(startData StartData) { s.startDataMu.Lock() defer s.startDataMu.Unlock() diff --git a/internal/portforward/state/state.go b/internal/portforward/state/state.go index 55ce95a8..7ec3bd30 100644 --- a/internal/portforward/state/state.go +++ b/internal/portforward/state/state.go @@ -1,21 +1,14 @@ package state import ( + "context" "sync" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/loopstate" + "github.com/qdm12/gluetun/internal/models" ) -var _ Manager = (*State)(nil) - -type Manager interface { - SettingsGetSetter - PortForwardedGetterSetter - StartDataGetterSetter -} - -func New(statusApplier loopstate.Applier, +func New(statusApplier StatusApplier, settings settings.PortForwarding) *State { return &State{ statusApplier: statusApplier, @@ -24,7 +17,7 @@ func New(statusApplier loopstate.Applier, } type State struct { - statusApplier loopstate.Applier + statusApplier StatusApplier settings settings.PortForwarding settingsMu sync.RWMutex @@ -35,3 +28,8 @@ type State struct { startData StartData startDataMu sync.RWMutex } + +type StatusApplier interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} diff --git a/internal/portforward/status.go b/internal/portforward/status.go index 60017843..76c5136d 100644 --- a/internal/portforward/status.go +++ b/internal/portforward/status.go @@ -14,12 +14,6 @@ func (l *Loop) GetStatus() (status models.LoopStatus) { type StartData = state.StartData -type StartStopper interface { - Start(ctx context.Context, data StartData) ( - outcome string, err error) - Stop(ctx context.Context) (outcome string, err error) -} - func (l *Loop) Start(ctx context.Context, data StartData) ( outcome string, err error) { l.startMu.Lock() diff --git a/internal/provider/common/mocks.go b/internal/provider/common/mocks.go index 3fd6119a..3c19b295 100644 --- a/internal/provider/common/mocks.go +++ b/internal/provider/common/mocks.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/qdm12/gluetun/internal/provider/common (interfaces: ParallelResolver,Storage) +// Source: github.com/qdm12/gluetun/internal/provider/common (interfaces: ParallelResolver,Storage,Unzipper) // Package common is a generated GoMock package. package common @@ -105,3 +105,41 @@ func (mr *MockStorageMockRecorder) GetServerByName(arg0, arg1 interface{}) *gomo mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServerByName", reflect.TypeOf((*MockStorage)(nil).GetServerByName), arg0, arg1) } + +// MockUnzipper is a mock of Unzipper interface. +type MockUnzipper struct { + ctrl *gomock.Controller + recorder *MockUnzipperMockRecorder +} + +// MockUnzipperMockRecorder is the mock recorder for MockUnzipper. +type MockUnzipperMockRecorder struct { + mock *MockUnzipper +} + +// NewMockUnzipper creates a new mock instance. +func NewMockUnzipper(ctrl *gomock.Controller) *MockUnzipper { + mock := &MockUnzipper{ctrl: ctrl} + mock.recorder = &MockUnzipperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockUnzipper) EXPECT() *MockUnzipperMockRecorder { + return m.recorder +} + +// FetchAndExtract mocks base method. +func (m *MockUnzipper) FetchAndExtract(arg0 context.Context, arg1 string) (map[string][]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchAndExtract", arg0, arg1) + ret0, _ := ret[0].(map[string][]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchAndExtract indicates an expected call of FetchAndExtract. +func (mr *MockUnzipperMockRecorder) FetchAndExtract(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchAndExtract", reflect.TypeOf((*MockUnzipper)(nil).FetchAndExtract), arg0, arg1) +} diff --git a/internal/provider/common/mocks_generate_test.go b/internal/provider/common/mocks_generate_test.go index 6127e693..bc44437a 100644 --- a/internal/provider/common/mocks_generate_test.go +++ b/internal/provider/common/mocks_generate_test.go @@ -2,4 +2,4 @@ package common // Exceptionally, these mocks are exported since they are used by all // provider subpackages tests, and it reduces test code duplication a lot. -//go:generate mockgen -destination=mocks.go -package $GOPACKAGE . ParallelResolver,Storage +//go:generate mockgen -destination=mocks.go -package $GOPACKAGE . ParallelResolver,Storage,Unzipper diff --git a/internal/provider/common/updater.go b/internal/provider/common/updater.go index 56bd50fd..905650e7 100644 --- a/internal/provider/common/updater.go +++ b/internal/provider/common/updater.go @@ -20,7 +20,8 @@ type ParallelResolver interface { } type Unzipper interface { - FetchAndExtract(ctx context.Context, url string) (contents map[string][]byte, err error) + FetchAndExtract(ctx context.Context, url string) ( + contents map[string][]byte, err error) } type Warner interface { diff --git a/internal/provider/custom/connection.go b/internal/provider/custom/connection.go index 2e2d0dbe..9a879a18 100644 --- a/internal/provider/custom/connection.go +++ b/internal/provider/custom/connection.go @@ -8,7 +8,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/openvpn/extract" ) var ( @@ -28,7 +27,7 @@ func (p *Provider) GetConnection(selection settings.ServerSelection) ( } } -func getOpenVPNConnection(extractor extract.Interface, +func getOpenVPNConnection(extractor extractor, selection settings.ServerSelection) ( connection models.Connection, err error) { _, connection, err = extractor.Data(*selection.OpenVPN.ConfFile) diff --git a/internal/provider/custom/interfaces.go b/internal/provider/custom/interfaces.go new file mode 100644 index 00000000..c7f462c1 --- /dev/null +++ b/internal/provider/custom/interfaces.go @@ -0,0 +1,8 @@ +package custom + +import "github.com/qdm12/gluetun/internal/models" + +type extractor interface { + Data(filepath string) (lines []string, + connection models.Connection, err error) +} diff --git a/internal/provider/custom/provider.go b/internal/provider/custom/provider.go index c4cc2d20..0bc5c7b9 100644 --- a/internal/provider/custom/provider.go +++ b/internal/provider/custom/provider.go @@ -8,7 +8,7 @@ import ( ) type Provider struct { - extractor extract.Interface + extractor extractor utils.NoPortForwarder common.Fetcher } diff --git a/internal/provider/expressvpn/updater/updater.go b/internal/provider/expressvpn/updater/updater.go index 3fff5dc8..452ef1ce 100644 --- a/internal/provider/expressvpn/updater/updater.go +++ b/internal/provider/expressvpn/updater/updater.go @@ -2,20 +2,15 @@ package updater import ( "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, presolver: newParallelResolver(), diff --git a/internal/provider/fastestvpn/updater/updater.go b/internal/provider/fastestvpn/updater/updater.go index 3fff5dc8..452ef1ce 100644 --- a/internal/provider/fastestvpn/updater/updater.go +++ b/internal/provider/fastestvpn/updater/updater.go @@ -2,20 +2,15 @@ package updater import ( "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, presolver: newParallelResolver(), diff --git a/internal/provider/hidemyass/updater/updater.go b/internal/provider/hidemyass/updater/updater.go index ea12152e..fbecad18 100644 --- a/internal/provider/hidemyass/updater/updater.go +++ b/internal/provider/hidemyass/updater/updater.go @@ -9,14 +9,10 @@ import ( type Updater struct { client *http.Client presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(client *http.Client, warner Warner) *Updater { +func New(client *http.Client, warner common.Warner) *Updater { return &Updater{ client: client, presolver: newParallelResolver(), diff --git a/internal/provider/ipvanish/updater/servers_test.go b/internal/provider/ipvanish/updater/servers_test.go index b23db9a5..0ce64ce8 100644 --- a/internal/provider/ipvanish/updater/servers_test.go +++ b/internal/provider/ipvanish/updater/servers_test.go @@ -10,7 +10,6 @@ import ( "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip/mock_unzip" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -22,7 +21,7 @@ func Test_Updater_GetServers(t *testing.T) { minServers int // Mocks - warnerBuilder func(ctrl *gomock.Controller) Warner + warnerBuilder func(ctrl *gomock.Controller) common.Warner // Unzip unzipContents map[string][]byte @@ -40,25 +39,25 @@ func Test_Updater_GetServers(t *testing.T) { err error }{ "unzipper error": { - warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil }, + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { return nil }, unzipErr: errors.New("dummy"), err: errors.New("dummy"), }, "not enough unzip contents": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil }, + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { return nil }, unzipContents: map[string][]byte{}, err: errors.New("not enough servers found: 0 and expected at least 1"), }, "no openvpn file": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil }, + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { return nil }, unzipContents: map[string][]byte{"somefile.txt": {}}, err: errors.New("not enough servers found: 0 and expected at least 1"), }, "invalid proto": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("unknown protocol: invalid in badproto.ovpn") return warner @@ -68,7 +67,7 @@ func Test_Updater_GetServers(t *testing.T) { }, "no host": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("remote host not found in nohost.ovpn") return warner @@ -78,7 +77,7 @@ func Test_Updater_GetServers(t *testing.T) { }, "multiple hosts": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("only using the first host \"hosta\" and discarding 1 other hosts") return warner @@ -91,7 +90,7 @@ func Test_Updater_GetServers(t *testing.T) { err: errors.New("not enough servers found: 0 and expected at least 1"), }, "resolve error": { - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("resolve warning") return warner @@ -107,7 +106,7 @@ func Test_Updater_GetServers(t *testing.T) { }, "filename parsing error": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("country code is unknown: unknown in ipvanish-unknown-City-A-hosta.ovpn") return warner @@ -119,7 +118,7 @@ func Test_Updater_GetServers(t *testing.T) { }, "success": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("resolve warning") return warner @@ -163,7 +162,7 @@ func Test_Updater_GetServers(t *testing.T) { ctx := context.Background() - unzipper := mock_unzip.NewMockUnzipper(ctrl) + unzipper := common.NewMockUnzipper(ctrl) const zipURL = "https://www.ipvanish.com/software/configs/configs.zip" unzipper.EXPECT().FetchAndExtract(ctx, zipURL). Return(testCase.unzipContents, testCase.unzipErr) diff --git a/internal/provider/ipvanish/updater/updater.go b/internal/provider/ipvanish/updater/updater.go index 97b0c342..3d64a73e 100644 --- a/internal/provider/ipvanish/updater/updater.go +++ b/internal/provider/ipvanish/updater/updater.go @@ -2,20 +2,15 @@ package updater import ( "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { - unzipper unzip.Unzipper - warner Warner + unzipper common.Unzipper + warner common.Warner presolver common.ParallelResolver } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, warner: warner, diff --git a/internal/provider/ivpn/updater/servers_test.go b/internal/provider/ivpn/updater/servers_test.go index f2520de7..7ba69701 100644 --- a/internal/provider/ivpn/updater/servers_test.go +++ b/internal/provider/ivpn/updater/servers_test.go @@ -25,7 +25,7 @@ func Test_Updater_GetServers(t *testing.T) { minServers int // Mocks - warnerBuilder func(ctrl *gomock.Controller) Warner + warnerBuilder func(ctrl *gomock.Controller) common.Warner // From API responseBody string @@ -43,12 +43,12 @@ func Test_Updater_GetServers(t *testing.T) { err error }{ "http response error": { - warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil }, + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { return nil }, responseStatus: http.StatusNoContent, err: errors.New("failed fetching API: HTTP status code not OK: 204 No Content"), }, "resolve error": { - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("resolve warning") return warner @@ -65,7 +65,7 @@ func Test_Updater_GetServers(t *testing.T) { }, "not enough servers": { minServers: 2, - warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil }, + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { return nil }, responseBody: `{"servers":[ {"hostnames":{"openvpn":"hosta"}} ]}`, @@ -74,7 +74,7 @@ func Test_Updater_GetServers(t *testing.T) { }, "success": { minServers: 1, - warnerBuilder: func(ctrl *gomock.Controller) Warner { + warnerBuilder: func(ctrl *gomock.Controller) common.Warner { warner := NewMockWarner(ctrl) warner.EXPECT().Warn("resolve warning") return warner diff --git a/internal/provider/ivpn/updater/updater.go b/internal/provider/ivpn/updater/updater.go index ea12152e..fbecad18 100644 --- a/internal/provider/ivpn/updater/updater.go +++ b/internal/provider/ivpn/updater/updater.go @@ -9,14 +9,10 @@ import ( type Updater struct { client *http.Client presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(client *http.Client, warner Warner) *Updater { +func New(client *http.Client, warner common.Warner) *Updater { return &Updater{ client: client, presolver: newParallelResolver(), diff --git a/internal/provider/nordvpn/updater/updater.go b/internal/provider/nordvpn/updater/updater.go index 89f66afe..ff0d41cd 100644 --- a/internal/provider/nordvpn/updater/updater.go +++ b/internal/provider/nordvpn/updater/updater.go @@ -2,18 +2,16 @@ package updater import ( "net/http" + + "github.com/qdm12/gluetun/internal/provider/common" ) type Updater struct { client *http.Client - warner Warner + warner common.Warner } -type Warner interface { - Warn(message string) -} - -func New(client *http.Client, warner Warner) *Updater { +func New(client *http.Client, warner common.Warner) *Updater { return &Updater{ client: client, warner: warner, diff --git a/internal/provider/perfectprivacy/updater/updater.go b/internal/provider/perfectprivacy/updater/updater.go index bfaa903d..66a2b327 100644 --- a/internal/provider/perfectprivacy/updater/updater.go +++ b/internal/provider/perfectprivacy/updater/updater.go @@ -1,17 +1,15 @@ package updater -import "github.com/qdm12/gluetun/internal/updater/unzip" +import ( + "github.com/qdm12/gluetun/internal/provider/common" +) type Updater struct { - unzipper unzip.Unzipper - warner Warner + unzipper common.Unzipper + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, warner: warner, diff --git a/internal/provider/privado/updater/updater.go b/internal/provider/privado/updater/updater.go index 37d0e74a..0a8c5c02 100644 --- a/internal/provider/privado/updater/updater.go +++ b/internal/provider/privado/updater/updater.go @@ -4,22 +4,17 @@ import ( "net/http" "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { client *http.Client - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(client *http.Client, unzipper unzip.Unzipper, - warner Warner) *Updater { +func New(client *http.Client, unzipper common.Unzipper, + warner common.Warner) *Updater { return &Updater{ client: client, unzipper: unzipper, diff --git a/internal/provider/privateinternetaccess/updater/updater.go b/internal/provider/privateinternetaccess/updater/updater.go index 44b49db9..a987c0fd 100644 --- a/internal/provider/privateinternetaccess/updater/updater.go +++ b/internal/provider/privateinternetaccess/updater/updater.go @@ -8,10 +8,6 @@ type Updater struct { client *http.Client } -type Warner interface { - Warn(s string) -} - func New(client *http.Client) *Updater { return &Updater{ client: client, diff --git a/internal/provider/privatevpn/updater/updater.go b/internal/provider/privatevpn/updater/updater.go index 3fff5dc8..452ef1ce 100644 --- a/internal/provider/privatevpn/updater/updater.go +++ b/internal/provider/privatevpn/updater/updater.go @@ -2,20 +2,15 @@ package updater import ( "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, presolver: newParallelResolver(), diff --git a/internal/provider/protonvpn/updater/updater.go b/internal/provider/protonvpn/updater/updater.go index f46ecfb5..ff0d41cd 100644 --- a/internal/provider/protonvpn/updater/updater.go +++ b/internal/provider/protonvpn/updater/updater.go @@ -2,18 +2,16 @@ package updater import ( "net/http" + + "github.com/qdm12/gluetun/internal/provider/common" ) type Updater struct { client *http.Client - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(client *http.Client, warner Warner) *Updater { +func New(client *http.Client, warner common.Warner) *Updater { return &Updater{ client: client, warner: warner, diff --git a/internal/provider/providers.go b/internal/provider/providers.go index 18ff51b6..59480934 100644 --- a/internal/provider/providers.go +++ b/internal/provider/providers.go @@ -82,7 +82,7 @@ func NewProviders(storage Storage, timeNow func() time.Time, } } -func (p *Providers) Get(providerName string) (provider Provider) { +func (p *Providers) Get(providerName string) (provider Provider) { //nolint:ireturn provider, ok := p.providerNameToProvider[providerName] if !ok { panic(fmt.Sprintf("provider %q not found", providerName)) diff --git a/internal/provider/purevpn/updater/updater.go b/internal/provider/purevpn/updater/updater.go index 37d0e74a..0a8c5c02 100644 --- a/internal/provider/purevpn/updater/updater.go +++ b/internal/provider/purevpn/updater/updater.go @@ -4,22 +4,17 @@ import ( "net/http" "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { client *http.Client - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(client *http.Client, unzipper unzip.Unzipper, - warner Warner) *Updater { +func New(client *http.Client, unzipper common.Unzipper, + warner common.Warner) *Updater { return &Updater{ client: client, unzipper: unzipper, diff --git a/internal/provider/surfshark/updater/updater.go b/internal/provider/surfshark/updater/updater.go index 37d0e74a..0a8c5c02 100644 --- a/internal/provider/surfshark/updater/updater.go +++ b/internal/provider/surfshark/updater/updater.go @@ -4,22 +4,17 @@ import ( "net/http" "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { client *http.Client - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(client *http.Client, unzipper unzip.Unzipper, - warner Warner) *Updater { +func New(client *http.Client, unzipper common.Unzipper, + warner common.Warner) *Updater { return &Updater{ client: client, unzipper: unzipper, diff --git a/internal/provider/surfshark/updater/zip.go b/internal/provider/surfshark/updater/zip.go index 28ae82ae..a27d69f6 100644 --- a/internal/provider/surfshark/updater/zip.go +++ b/internal/provider/surfshark/updater/zip.go @@ -4,13 +4,13 @@ import ( "context" "strings" + "github.com/qdm12/gluetun/internal/provider/common" "github.com/qdm12/gluetun/internal/provider/surfshark/servers" "github.com/qdm12/gluetun/internal/updater/openvpn" - "github.com/qdm12/gluetun/internal/updater/unzip" ) func addOpenVPNServersFromZip(ctx context.Context, - unzipper unzip.Unzipper, hts hostToServer) ( + unzipper common.Unzipper, hts hostToServer) ( warnings []string, err error) { const url = "https://my.surfshark.com/vpn/api/v1/server/configurations" contents, err := unzipper.FetchAndExtract(ctx, url) diff --git a/internal/provider/torguard/updater/updater.go b/internal/provider/torguard/updater/updater.go index 3fff5dc8..452ef1ce 100644 --- a/internal/provider/torguard/updater/updater.go +++ b/internal/provider/torguard/updater/updater.go @@ -2,20 +2,15 @@ package updater import ( "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, presolver: newParallelResolver(), diff --git a/internal/provider/vpnunlimited/updater/updater.go b/internal/provider/vpnunlimited/updater/updater.go index 3fff5dc8..452ef1ce 100644 --- a/internal/provider/vpnunlimited/updater/updater.go +++ b/internal/provider/vpnunlimited/updater/updater.go @@ -2,20 +2,15 @@ package updater import ( "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, presolver: newParallelResolver(), diff --git a/internal/provider/vyprvpn/updater/updater.go b/internal/provider/vyprvpn/updater/updater.go index 3fff5dc8..452ef1ce 100644 --- a/internal/provider/vyprvpn/updater/updater.go +++ b/internal/provider/vyprvpn/updater/updater.go @@ -2,20 +2,15 @@ package updater import ( "github.com/qdm12/gluetun/internal/provider/common" - "github.com/qdm12/gluetun/internal/updater/unzip" ) type Updater struct { - unzipper unzip.Unzipper + unzipper common.Unzipper presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(unzipper unzip.Unzipper, warner Warner) *Updater { +func New(unzipper common.Unzipper, warner common.Warner) *Updater { return &Updater{ unzipper: unzipper, presolver: newParallelResolver(), diff --git a/internal/provider/wevpn/updater/updater.go b/internal/provider/wevpn/updater/updater.go index a556bc6e..06a68c69 100644 --- a/internal/provider/wevpn/updater/updater.go +++ b/internal/provider/wevpn/updater/updater.go @@ -4,14 +4,10 @@ import "github.com/qdm12/gluetun/internal/provider/common" type Updater struct { presolver common.ParallelResolver - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(warner Warner) *Updater { +func New(warner common.Warner) *Updater { return &Updater{ presolver: newParallelResolver(), warner: warner, diff --git a/internal/provider/windscribe/updater/updater.go b/internal/provider/windscribe/updater/updater.go index f46ecfb5..ff0d41cd 100644 --- a/internal/provider/windscribe/updater/updater.go +++ b/internal/provider/windscribe/updater/updater.go @@ -2,18 +2,16 @@ package updater import ( "net/http" + + "github.com/qdm12/gluetun/internal/provider/common" ) type Updater struct { client *http.Client - warner Warner + warner common.Warner } -type Warner interface { - Warn(s string) -} - -func New(client *http.Client, warner Warner) *Updater { +func New(client *http.Client, warner common.Warner) *Updater { return &Updater{ client: client, warner: warner, diff --git a/internal/publicip/alias.go b/internal/publicip/alias.go deleted file mode 100644 index 5e0c5fdd..00000000 --- a/internal/publicip/alias.go +++ /dev/null @@ -1,6 +0,0 @@ -package publicip - -import "github.com/qdm12/gluetun/internal/publicip/state" - -type GetSetter = state.DataGetSetter -type SettingsGetSetter = state.SettingsGetSetter diff --git a/internal/publicip/fetch.go b/internal/publicip/fetch.go index 56eda31f..7b9d69ed 100644 --- a/internal/publicip/fetch.go +++ b/internal/publicip/fetch.go @@ -12,12 +12,6 @@ import ( "strings" ) -var _ Fetcher = (*Fetch)(nil) - -type Fetcher interface { - FetchPublicIP(ctx context.Context) (ip net.IP, err error) -} - type Fetch struct { client *http.Client randIntn func(n int) int diff --git a/internal/publicip/interfaces.go b/internal/publicip/interfaces.go new file mode 100644 index 00000000..3cfdbe0f --- /dev/null +++ b/internal/publicip/interfaces.go @@ -0,0 +1,28 @@ +package publicip + +import ( + "context" + "net" + + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/models" + publicipmodels "github.com/qdm12/gluetun/internal/publicip/models" +) + +type statusManager interface { + GetStatus() (status models.LoopStatus) + SetStatus(status models.LoopStatus) + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} + +type stateManager interface { + GetData() (data publicipmodels.IPInfoData) + SetData(data publicipmodels.IPInfoData) + GetSettings() (settings settings.PublicIP) + SetSettings(ctx context.Context, settings settings.PublicIP) (outcome string) +} + +type fetcher interface { + FetchPublicIP(ctx context.Context) (ip net.IP, err error) +} diff --git a/internal/publicip/loop.go b/internal/publicip/loop.go index 5fa61c4a..f96a3b62 100644 --- a/internal/publicip/loop.go +++ b/internal/publicip/loop.go @@ -11,22 +11,11 @@ import ( "github.com/qdm12/gluetun/internal/publicip/state" ) -var _ Looper = (*Loop)(nil) - -type Looper interface { - Runner - RestartTickerRunner - loopstate.Getter - loopstate.Applier - SettingsGetSetter - GetSetter -} - type Loop struct { - statusManager loopstate.Manager - state state.Manager + statusManager statusManager + state stateManager // Objects - fetcher Fetcher + fetcher fetcher client *http.Client logger Logger // Fixed settings diff --git a/internal/publicip/runner.go b/internal/publicip/runner.go index 1fbab3f2..2a5325af 100644 --- a/internal/publicip/runner.go +++ b/internal/publicip/runner.go @@ -8,10 +8,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type Runner interface { - Run(ctx context.Context, done chan<- struct{}) -} - func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) diff --git a/internal/publicip/state/publicip.go b/internal/publicip/state/publicip.go index 119c616a..79d5533d 100644 --- a/internal/publicip/state/publicip.go +++ b/internal/publicip/state/publicip.go @@ -4,11 +4,6 @@ import ( "github.com/qdm12/gluetun/internal/publicip/models" ) -type DataGetSetter interface { - GetData() (data models.IPInfoData) - SetData(data models.IPInfoData) -} - func (s *State) GetData() (data models.IPInfoData) { s.ipDataMu.RLock() defer s.ipDataMu.RUnlock() diff --git a/internal/publicip/state/settings.go b/internal/publicip/state/settings.go index d57ef338..258df6a4 100644 --- a/internal/publicip/state/settings.go +++ b/internal/publicip/state/settings.go @@ -7,12 +7,6 @@ import ( "github.com/qdm12/gluetun/internal/configuration/settings" ) -type SettingsGetSetter interface { - GetSettings() (settings settings.PublicIP) - SetSettings(ctx context.Context, - settings settings.PublicIP) (outcome string) -} - func (s *State) GetSettings() (settings settings.PublicIP) { s.settingsMu.RLock() defer s.settingsMu.RUnlock() diff --git a/internal/publicip/state/state.go b/internal/publicip/state/state.go index 39e0e0a7..795f42e3 100644 --- a/internal/publicip/state/state.go +++ b/internal/publicip/state/state.go @@ -1,21 +1,15 @@ package state import ( + "context" "sync" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/loopstate" - "github.com/qdm12/gluetun/internal/publicip/models" + "github.com/qdm12/gluetun/internal/models" + publicipmodels "github.com/qdm12/gluetun/internal/publicip/models" ) -var _ Manager = (*State)(nil) - -type Manager interface { - SettingsGetSetter - DataGetSetter -} - -func New(statusApplier loopstate.Applier, +func New(statusApplier StatusApplier, settings settings.PublicIP, updateTicker chan<- struct{}) *State { return &State{ @@ -26,13 +20,18 @@ func New(statusApplier loopstate.Applier, } type State struct { - statusApplier loopstate.Applier + statusApplier StatusApplier settings settings.PublicIP settingsMu sync.RWMutex - ipData models.IPInfoData + ipData publicipmodels.IPInfoData ipDataMu sync.RWMutex updateTicker chan<- struct{} } + +type StatusApplier interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} diff --git a/internal/publicip/ticker.go b/internal/publicip/ticker.go index 3c14be0d..24af8656 100644 --- a/internal/publicip/ticker.go +++ b/internal/publicip/ticker.go @@ -7,10 +7,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type RestartTickerRunner interface { - RunRestartTicker(ctx context.Context, done chan<- struct{}) -} - func (l *Loop) RunRestartTicker(ctx context.Context, done chan<- struct{}) { defer close(done) timer := time.NewTimer(time.Hour) @@ -30,7 +26,7 @@ func (l *Loop) RunRestartTicker(ctx context.Context, done chan<- struct{}) { return case <-timer.C: lastTick = l.timeNow() - _, _ = l.ApplyStatus(ctx, constants.Running) + _, _ = l.statusManager.ApplyStatus(ctx, constants.Running) timer.Reset(*l.state.GetSettings().Period) case <-l.updateTicker: if !timerIsStopped && !timer.Stop() { diff --git a/internal/routing/default.go b/internal/routing/default.go index 728d0504..334eab5e 100644 --- a/internal/routing/default.go +++ b/internal/routing/default.go @@ -12,10 +12,6 @@ var ( ErrRouteDefaultNotFound = errors.New("default route not found") ) -type DefaultRouteGetter interface { - DefaultRoutes() (defaultRoutes []DefaultRoute, err error) -} - type DefaultRoute struct { NetInterface string Gateway net.IP diff --git a/internal/routing/enable.go b/internal/routing/enable.go index e4c93437..2d3046ed 100644 --- a/internal/routing/enable.go +++ b/internal/routing/enable.go @@ -4,10 +4,6 @@ import ( "fmt" ) -type Setuper interface { - Setup() (err error) -} - func (r *Routing) Setup() (err error) { defaultRoutes, err := r.DefaultRoutes() if err != nil { @@ -40,10 +36,6 @@ func (r *Routing) Setup() (err error) { return nil } -type TearDowner interface { - TearDown() error -} - func (r *Routing) TearDown() error { defaultRoutes, err := r.DefaultRoutes() if err != nil { diff --git a/internal/routing/local.go b/internal/routing/local.go index 31bdb312..b5d9e81e 100644 --- a/internal/routing/local.go +++ b/internal/routing/local.go @@ -20,10 +20,6 @@ type LocalNetwork struct { IP net.IP } -type LocalNetworksGetter interface { - LocalNetworks() (localNetworks []LocalNetwork, err error) -} - func (r *Routing) LocalNetworks() (localNetworks []LocalNetwork, err error) { links, err := r.netLinker.LinkList() if err != nil { diff --git a/internal/routing/mocks_generate_test.go b/internal/routing/mocks_generate_test.go new file mode 100644 index 00000000..c8362794 --- /dev/null +++ b/internal/routing/mocks_generate_test.go @@ -0,0 +1,3 @@ +package routing + +//go:generate mockgen -destination=mocks_test.go -package=$GOPACKAGE . NetLinker diff --git a/internal/netlink/mock_netlink/interface.go b/internal/routing/mocks_test.go similarity index 98% rename from internal/netlink/mock_netlink/interface.go rename to internal/routing/mocks_test.go index 7e87ebaf..fa3faf4c 100644 --- a/internal/netlink/mock_netlink/interface.go +++ b/internal/routing/mocks_test.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/qdm12/gluetun/internal/netlink (interfaces: NetLinker) +// Source: github.com/qdm12/gluetun/internal/routing (interfaces: NetLinker) -// Package mock_netlink is a generated GoMock package. -package mock_netlink +// Package routing is a generated GoMock package. +package routing import ( reflect "reflect" diff --git a/internal/routing/outbound.go b/internal/routing/outbound.go index 9f42ea7a..2a5f083b 100644 --- a/internal/routing/outbound.go +++ b/internal/routing/outbound.go @@ -12,10 +12,6 @@ const ( outboundPriority = 99 ) -type OutboundRoutesSetter interface { - SetOutboundRoutes(outboundSubnets []net.IPNet) error -} - func (r *Routing) SetOutboundRoutes(outboundSubnets []net.IPNet) error { defaultRoutes, err := r.DefaultRoutes() if err != nil { diff --git a/internal/routing/routing.go b/internal/routing/routing.go index a7e85255..9daacdf9 100644 --- a/internal/routing/routing.go +++ b/internal/routing/routing.go @@ -8,37 +8,37 @@ import ( "github.com/qdm12/gluetun/internal/netlink" ) -type ReadWriter interface { - Reader - Writer -} - -type Reader interface { - DefaultRouteGetter - LocalNetworksGetter - VPNGetter -} - -type VPNGetter interface { - VPNDestinationIPGetter - VPNLocalGatewayIPGetter -} - -type Writer interface { - Setuper - TearDowner - OutboundRoutesSetter +type NetLinker interface { + AddrList(link netlink.Link, family int) ( + addresses []netlink.Addr, err error) + AddrAdd(link netlink.Link, addr *netlink.Addr) error + IsWireguardSupported() (ok bool, err error) + RouteList(link netlink.Link, family int) ( + routes []netlink.Route, err error) + RouteAdd(route *netlink.Route) error + RouteDel(route *netlink.Route) error + RouteReplace(route *netlink.Route) error + RuleList(family int) (rules []netlink.Rule, err error) + RuleAdd(rule *netlink.Rule) error + RuleDel(rule *netlink.Rule) error + LinkList() (links []netlink.Link, err error) + LinkByName(name string) (link netlink.Link, err error) + LinkByIndex(index int) (link netlink.Link, err error) + LinkAdd(link netlink.Link) (err error) + LinkDel(link netlink.Link) (err error) + LinkSetUp(link netlink.Link) (err error) + LinkSetDown(link netlink.Link) (err error) } type Routing struct { - netLinker netlink.NetLinker + netLinker NetLinker logger Logger outboundSubnets []net.IPNet stateMutex sync.RWMutex } // New creates a new routing instance. -func New(netLinker netlink.NetLinker, logger Logger) *Routing { +func New(netLinker NetLinker, logger Logger) *Routing { return &Routing{ netLinker: netLinker, logger: logger, diff --git a/internal/routing/rules_test.go b/internal/routing/rules_test.go index f7b49ce1..f4d89b5c 100644 --- a/internal/routing/rules_test.go +++ b/internal/routing/rules_test.go @@ -7,7 +7,6 @@ import ( "github.com/golang/mock/gomock" "github.com/qdm12/gluetun/internal/netlink" - "github.com/qdm12/gluetun/internal/netlink/mock_netlink" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -118,7 +117,7 @@ func Test_Routing_addIPRule(t *testing.T) { logger := NewMockLogger(ctrl) logger.EXPECT().Debug(testCase.dbgMsg) - netLinker := mock_netlink.NewMockNetLinker(ctrl) + netLinker := NewMockNetLinker(ctrl) netLinker.EXPECT().RuleList(netlink.FAMILY_ALL). Return(testCase.ruleList.rules, testCase.ruleList.err) if testCase.ruleAdd.expected { @@ -236,7 +235,7 @@ func Test_Routing_deleteIPRule(t *testing.T) { logger := NewMockLogger(ctrl) logger.EXPECT().Debug(testCase.dbgMsg) - netLinker := mock_netlink.NewMockNetLinker(ctrl) + netLinker := NewMockNetLinker(ctrl) netLinker.EXPECT().RuleList(netlink.FAMILY_ALL). Return(testCase.ruleList.rules, testCase.ruleList.err) if testCase.ruleDel.expected { diff --git a/internal/routing/vpn.go b/internal/routing/vpn.go index 70df8fc4..ba2478b9 100644 --- a/internal/routing/vpn.go +++ b/internal/routing/vpn.go @@ -14,10 +14,6 @@ var ( ErrVPNLocalGatewayIPNotFound = errors.New("VPN local gateway IP address not found") ) -type VPNDestinationIPGetter interface { - VPNDestinationIP() (ip net.IP, err error) -} - func (r *Routing) VPNDestinationIP() (ip net.IP, err error) { routes, err := r.netLinker.RouteList(nil, netlink.FAMILY_ALL) if err != nil { @@ -46,10 +42,6 @@ func (r *Routing) VPNDestinationIP() (ip net.IP, err error) { return nil, fmt.Errorf("%w: in %d routes", ErrVPNDestinationIPNotFound, len(routes)) } -type VPNLocalGatewayIPGetter interface { - VPNLocalGatewayIP(vpnIntf string) (ip net.IP, err error) -} - func (r *Routing) VPNLocalGatewayIP(vpnIntf string) (ip net.IP, err error) { routes, err := r.netLinker.RouteList(nil, netlink.FAMILY_ALL) if err != nil { diff --git a/internal/server/dns.go b/internal/server/dns.go index 20b9f3a0..a77310f7 100644 --- a/internal/server/dns.go +++ b/internal/server/dns.go @@ -5,22 +5,20 @@ import ( "encoding/json" "net/http" "strings" - - "github.com/qdm12/gluetun/internal/dns" ) -func newDNSHandler(ctx context.Context, looper dns.Looper, +func newDNSHandler(ctx context.Context, loop DNSLoop, warner warner) http.Handler { return &dnsHandler{ ctx: ctx, - looper: looper, + loop: loop, warner: warner, } } type dnsHandler struct { ctx context.Context //nolint:containedctx - looper dns.Looper + loop DNSLoop warner warner } @@ -42,7 +40,7 @@ func (h *dnsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (h *dnsHandler) getStatus(w http.ResponseWriter) { - status := h.looper.GetStatus() + status := h.loop.GetStatus() encoder := json.NewEncoder(w) data := statusWrapper{Status: string(status)} if err := encoder.Encode(data); err != nil { @@ -64,7 +62,7 @@ func (h *dnsHandler) setStatus(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - outcome, err := h.looper.ApplyStatus(h.ctx, status) + outcome, err := h.loop.ApplyStatus(h.ctx, status) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/internal/server/handler.go b/internal/server/handler.go index 3d126946..4b01aa3a 100644 --- a/internal/server/handler.go +++ b/internal/server/handler.go @@ -5,20 +5,16 @@ import ( "net/http" "strings" - "github.com/qdm12/gluetun/internal/dns" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/portforward" - "github.com/qdm12/gluetun/internal/publicip" - "github.com/qdm12/gluetun/internal/vpn" ) func newHandler(ctx context.Context, logger infoWarner, logging bool, buildInfo models.BuildInformation, - vpnLooper vpn.Looper, - pfGetter portforward.Getter, - unboundLooper dns.Looper, + vpnLooper VPNLooper, + pfGetter PortForwardedGetter, + unboundLooper DNSLoop, updaterLooper UpdaterLooper, - publicIPLooper publicip.Looper, + publicIPLooper PublicIPLoop, ) http.Handler { handler := &handler{} diff --git a/internal/server/handlerv0.go b/internal/server/handlerv0.go index 93e6645d..9313b68e 100644 --- a/internal/server/handlerv0.go +++ b/internal/server/handlerv0.go @@ -5,12 +5,10 @@ import ( "net/http" "github.com/qdm12/gluetun/internal/constants" - "github.com/qdm12/gluetun/internal/dns" - "github.com/qdm12/gluetun/internal/vpn" ) func newHandlerV0(ctx context.Context, logger infoWarner, - vpn vpn.Looper, dns dns.Looper, updater UpdaterLooper) http.Handler { + vpn VPNLooper, dns DNSLoop, updater UpdaterLooper) http.Handler { return &handlerV0{ ctx: ctx, logger: logger, @@ -23,8 +21,8 @@ func newHandlerV0(ctx context.Context, logger infoWarner, type handlerV0 struct { ctx context.Context //nolint:containedctx logger infoWarner - vpn vpn.Looper - dns dns.Looper + vpn VPNLooper + dns DNSLoop updater UpdaterLooper } diff --git a/internal/server/interfaces.go b/internal/server/interfaces.go new file mode 100644 index 00000000..30921765 --- /dev/null +++ b/internal/server/interfaces.go @@ -0,0 +1,30 @@ +package server + +import ( + "context" + + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/models" + publicipmodels "github.com/qdm12/gluetun/internal/publicip/models" +) + +type VPNLooper interface { + GetStatus() (status models.LoopStatus) + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) + GetSettings() (settings settings.VPN) +} + +type DNSLoop interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) + GetStatus() (status models.LoopStatus) +} + +type PortForwardedGetter interface { + GetPortForwarded() (portForwarded uint16) +} + +type PublicIPLoop interface { + GetData() (data publicipmodels.IPInfoData) +} diff --git a/internal/server/openvpn.go b/internal/server/openvpn.go index 4033d734..f5ff1247 100644 --- a/internal/server/openvpn.go +++ b/internal/server/openvpn.go @@ -5,13 +5,10 @@ import ( "encoding/json" "net/http" "strings" - - "github.com/qdm12/gluetun/internal/portforward" - "github.com/qdm12/gluetun/internal/vpn" ) -func newOpenvpnHandler(ctx context.Context, looper vpn.Looper, - pfGetter portforward.Getter, w warner) http.Handler { +func newOpenvpnHandler(ctx context.Context, looper VPNLooper, + pfGetter PortForwardedGetter, w warner) http.Handler { return &openvpnHandler{ ctx: ctx, looper: looper, @@ -22,8 +19,8 @@ func newOpenvpnHandler(ctx context.Context, looper vpn.Looper, type openvpnHandler struct { ctx context.Context //nolint:containedctx - looper vpn.Looper - pf portforward.Getter + looper VPNLooper + pf PortForwardedGetter warner warner } diff --git a/internal/server/publicip.go b/internal/server/publicip.go index 25efe6e0..7a5dba92 100644 --- a/internal/server/publicip.go +++ b/internal/server/publicip.go @@ -4,19 +4,17 @@ import ( "encoding/json" "net/http" "strings" - - "github.com/qdm12/gluetun/internal/publicip" ) -func newPublicIPHandler(looper publicip.Looper, w warner) http.Handler { +func newPublicIPHandler(loop PublicIPLoop, w warner) http.Handler { return &publicIPHandler{ - looper: looper, + loop: loop, warner: w, } } type publicIPHandler struct { - looper publicip.Looper + loop PublicIPLoop warner warner } @@ -36,7 +34,7 @@ func (h *publicIPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (h *publicIPHandler) getPublicIP(w http.ResponseWriter) { - data := h.looper.GetData() + data := h.loop.GetData() encoder := json.NewEncoder(w) if err := encoder.Encode(data); err != nil { h.warner.Warn(err.Error()) diff --git a/internal/server/server.go b/internal/server/server.go index b55d978b..727194a8 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -5,18 +5,14 @@ import ( "context" "fmt" - "github.com/qdm12/gluetun/internal/dns" "github.com/qdm12/gluetun/internal/httpserver" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/portforward" - "github.com/qdm12/gluetun/internal/publicip" - "github.com/qdm12/gluetun/internal/vpn" ) func New(ctx context.Context, address string, logEnabled bool, logger Logger, - buildInfo models.BuildInformation, openvpnLooper vpn.Looper, - pfGetter portforward.Getter, unboundLooper dns.Looper, - updaterLooper UpdaterLooper, publicIPLooper publicip.Looper) (server httpserver.Runner, err error) { + buildInfo models.BuildInformation, openvpnLooper VPNLooper, + pfGetter PortForwardedGetter, unboundLooper DNSLoop, + updaterLooper UpdaterLooper, publicIPLooper PublicIPLoop) (server *httpserver.Server, err error) { handler := newHandler(ctx, logger, logEnabled, buildInfo, openvpnLooper, pfGetter, unboundLooper, updaterLooper, publicIPLooper) diff --git a/internal/shadowsocks/loop.go b/internal/shadowsocks/loop.go index a9698d50..5c544c47 100644 --- a/internal/shadowsocks/loop.go +++ b/internal/shadowsocks/loop.go @@ -12,17 +12,7 @@ import ( shadowsockslib "github.com/qdm12/ss-server/pkg/tcpudp" ) -type Looper interface { - Run(ctx context.Context, done chan<- struct{}) - SetStatus(ctx context.Context, status models.LoopStatus) ( - outcome string, err error) - GetStatus() (status models.LoopStatus) - GetSettings() (settings settings.Shadowsocks) - SetSettings(ctx context.Context, settings settings.Shadowsocks) ( - outcome string) -} - -type looper struct { +type Loop struct { state state // Other objects logger Logger @@ -34,7 +24,7 @@ type looper struct { backoffTime time.Duration } -func (l *looper) logAndWait(ctx context.Context, err error) { +func (l *Loop) logAndWait(ctx context.Context, err error) { if err != nil { l.logger.Error(err.Error()) } @@ -52,8 +42,8 @@ func (l *looper) logAndWait(ctx context.Context, err error) { const defaultBackoffTime = 10 * time.Second -func NewLooper(settings settings.Shadowsocks, logger Logger) Looper { - return &looper{ +func NewLoop(settings settings.Shadowsocks, logger Logger) *Loop { + return &Loop{ state: state{ status: constants.Stopped, settings: settings, @@ -67,7 +57,7 @@ func NewLooper(settings settings.Shadowsocks, logger Logger) Looper { } } -func (l *looper) Run(ctx context.Context, done chan<- struct{}) { +func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) crashed := false diff --git a/internal/shadowsocks/state.go b/internal/shadowsocks/state.go index 145573b3..b7bc360d 100644 --- a/internal/shadowsocks/state.go +++ b/internal/shadowsocks/state.go @@ -25,7 +25,7 @@ func (s *state) setStatusWithLock(status models.LoopStatus) { s.status = status } -func (l *looper) GetStatus() (status models.LoopStatus) { +func (l *Loop) GetStatus() (status models.LoopStatus) { l.state.statusMu.RLock() defer l.state.statusMu.RUnlock() return l.state.status @@ -33,7 +33,7 @@ func (l *looper) GetStatus() (status models.LoopStatus) { var ErrInvalidStatus = errors.New("invalid status") -func (l *looper) SetStatus(ctx context.Context, status models.LoopStatus) ( +func (l *Loop) SetStatus(ctx context.Context, status models.LoopStatus) ( outcome string, err error) { l.state.statusMu.Lock() defer l.state.statusMu.Unlock() @@ -84,13 +84,13 @@ func (l *looper) SetStatus(ctx context.Context, status models.LoopStatus) ( } } -func (l *looper) GetSettings() (settings settings.Shadowsocks) { +func (l *Loop) GetSettings() (settings settings.Shadowsocks) { l.state.settingsMu.RLock() defer l.state.settingsMu.RUnlock() return l.state.settings } -func (l *looper) SetSettings(ctx context.Context, settings settings.Shadowsocks) ( +func (l *Loop) SetSettings(ctx context.Context, settings settings.Shadowsocks) ( outcome string) { l.state.settingsMu.Lock() settingsUnchanged := reflect.DeepEqual(settings, l.state.settings) diff --git a/internal/tun/check.go b/internal/tun/check.go index 7620e23c..245b8a79 100644 --- a/internal/tun/check.go +++ b/internal/tun/check.go @@ -7,10 +7,6 @@ import ( "syscall" ) -type Checker interface { - Check(path string) error -} - var ( ErrTUNInfo = errors.New("cannot get syscall stat info of TUN file") ErrTUNBadRdev = errors.New("TUN file has an unexpected rdev") diff --git a/internal/tun/create.go b/internal/tun/create.go index e642a2e4..2e90dec9 100644 --- a/internal/tun/create.go +++ b/internal/tun/create.go @@ -8,10 +8,6 @@ import ( "golang.org/x/sys/unix" ) -type Creator interface { - Create(path string) error -} - // Create creates a TUN device at the path specified. func (t *Tun) Create(path string) error { parentDir := filepath.Dir(path) diff --git a/internal/tun/tun.go b/internal/tun/tun.go index f9e2f18d..4fac89c6 100644 --- a/internal/tun/tun.go +++ b/internal/tun/tun.go @@ -2,13 +2,6 @@ package tun import "golang.org/x/sys/unix" -var _ Interface = (*Tun)(nil) - -type Interface interface { - Checker - Creator -} - type Tun struct { mknod func(path string, mode uint32, dev int) (err error) } diff --git a/internal/updater/interfaces.go b/internal/updater/interfaces.go new file mode 100644 index 00000000..1c50bb87 --- /dev/null +++ b/internal/updater/interfaces.go @@ -0,0 +1,33 @@ +package updater + +import ( + "context" + + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/provider" +) + +type Providers interface { + Get(providerName string) provider.Provider +} + +type Storage interface { + SetServers(provider string, servers []models.Server) (err error) + GetServersCount(provider string) (count int) + ServersAreEqual(provider string, servers []models.Server) (equal bool) + // Extra methods to match the provider.New storage interface + FilterServers(provider string, selection settings.ServerSelection) (filtered []models.Server, err error) + GetServerByName(provider string, name string) (server models.Server, ok bool) +} + +type Unzipper interface { + FetchAndExtract(ctx context.Context, url string) ( + contents map[string][]byte, err error) +} + +type Logger interface { + Info(s string) + Warn(s string) + Error(s string) +} diff --git a/internal/updater/loop/loop.go b/internal/updater/loop/loop.go index 95a028bb..99d8b87e 100644 --- a/internal/updater/loop/loop.go +++ b/internal/updater/loop/loop.go @@ -12,21 +12,11 @@ import ( "github.com/qdm12/gluetun/internal/updater" ) -type Looper interface { - Run(ctx context.Context, done chan<- struct{}) - RunRestartTicker(ctx context.Context, done chan<- struct{}) - GetStatus() (status models.LoopStatus) - SetStatus(ctx context.Context, status models.LoopStatus) ( - outcome string, err error) - GetSettings() (settings settings.Updater) - SetSettings(settings settings.Updater) (outcome string) -} - type Updater interface { UpdateServers(ctx context.Context, providers []string) (err error) } -type looper struct { +type Loop struct { state state // Objects updater Updater @@ -52,9 +42,9 @@ type Logger interface { Error(s string) } -func NewLooper(settings settings.Updater, providers updater.Providers, - storage updater.Storage, client *http.Client, logger Logger) Looper { - return &looper{ +func NewLoop(settings settings.Updater, providers updater.Providers, + storage updater.Storage, client *http.Client, logger Logger) *Loop { + return &Loop{ state: state{ status: constants.Stopped, settings: settings, @@ -72,7 +62,7 @@ func NewLooper(settings settings.Updater, providers updater.Providers, } } -func (l *looper) logAndWait(ctx context.Context, err error) { +func (l *Loop) logAndWait(ctx context.Context, err error) { if err != nil { l.logger.Error(err.Error()) } @@ -88,7 +78,7 @@ func (l *looper) logAndWait(ctx context.Context, err error) { } } -func (l *looper) Run(ctx context.Context, done chan<- struct{}) { +func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) crashed := false select { @@ -156,7 +146,7 @@ func (l *looper) Run(ctx context.Context, done chan<- struct{}) { } } -func (l *looper) RunRestartTicker(ctx context.Context, done chan<- struct{}) { +func (l *Loop) RunRestartTicker(ctx context.Context, done chan<- struct{}) { defer close(done) timer := time.NewTimer(time.Hour) timer.Stop() diff --git a/internal/updater/loop/state.go b/internal/updater/loop/state.go index b6972172..551a1112 100644 --- a/internal/updater/loop/state.go +++ b/internal/updater/loop/state.go @@ -25,7 +25,7 @@ func (s *state) setStatusWithLock(status models.LoopStatus) { s.status = status } -func (l *looper) GetStatus() (status models.LoopStatus) { +func (l *Loop) GetStatus() (status models.LoopStatus) { l.state.statusMu.RLock() defer l.state.statusMu.RUnlock() return l.state.status @@ -33,7 +33,7 @@ func (l *looper) GetStatus() (status models.LoopStatus) { var ErrInvalidStatus = errors.New("invalid status") -func (l *looper) SetStatus(ctx context.Context, status models.LoopStatus) (outcome string, err error) { +func (l *Loop) SetStatus(ctx context.Context, status models.LoopStatus) (outcome string, err error) { l.state.statusMu.Lock() defer l.state.statusMu.Unlock() existingStatus := l.state.status @@ -84,13 +84,13 @@ func (l *looper) SetStatus(ctx context.Context, status models.LoopStatus) (outco } } -func (l *looper) GetSettings() (settings settings.Updater) { +func (l *Loop) GetSettings() (settings settings.Updater) { l.state.periodMu.RLock() defer l.state.periodMu.RUnlock() return l.state.settings } -func (l *looper) SetSettings(settings settings.Updater) (outcome string) { +func (l *Loop) SetSettings(settings settings.Updater) (outcome string) { l.state.periodMu.Lock() defer l.state.periodMu.Unlock() settingsUnchanged := reflect.DeepEqual(settings, l.state.settings) diff --git a/internal/updater/unzip/fetch.go b/internal/updater/unzip/fetch.go index 7e9c526b..9a2e83e9 100644 --- a/internal/updater/unzip/fetch.go +++ b/internal/updater/unzip/fetch.go @@ -12,7 +12,7 @@ var ( ErrHTTPStatusCodeNotOK = errors.New("HTTP status code not OK") ) -func (u *unzipper) FetchAndExtract(ctx context.Context, url string) ( +func (u *Unzipper) FetchAndExtract(ctx context.Context, url string) ( contents map[string][]byte, err error) { request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { diff --git a/internal/updater/unzip/mock_unzip/unzip.go b/internal/updater/unzip/mock_unzip/unzip.go deleted file mode 100644 index a866c705..00000000 --- a/internal/updater/unzip/mock_unzip/unzip.go +++ /dev/null @@ -1,50 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/qdm12/gluetun/internal/updater/unzip (interfaces: Unzipper) - -// Package mock_unzip is a generated GoMock package. -package mock_unzip - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" -) - -// MockUnzipper is a mock of Unzipper interface. -type MockUnzipper struct { - ctrl *gomock.Controller - recorder *MockUnzipperMockRecorder -} - -// MockUnzipperMockRecorder is the mock recorder for MockUnzipper. -type MockUnzipperMockRecorder struct { - mock *MockUnzipper -} - -// NewMockUnzipper creates a new mock instance. -func NewMockUnzipper(ctrl *gomock.Controller) *MockUnzipper { - mock := &MockUnzipper{ctrl: ctrl} - mock.recorder = &MockUnzipperMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockUnzipper) EXPECT() *MockUnzipperMockRecorder { - return m.recorder -} - -// FetchAndExtract mocks base method. -func (m *MockUnzipper) FetchAndExtract(arg0 context.Context, arg1 string) (map[string][]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchAndExtract", arg0, arg1) - ret0, _ := ret[0].(map[string][]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// FetchAndExtract indicates an expected call of FetchAndExtract. -func (mr *MockUnzipperMockRecorder) FetchAndExtract(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchAndExtract", reflect.TypeOf((*MockUnzipper)(nil).FetchAndExtract), arg0, arg1) -} diff --git a/internal/updater/unzip/unzip.go b/internal/updater/unzip/unzip.go index 50f56844..30d815b5 100644 --- a/internal/updater/unzip/unzip.go +++ b/internal/updater/unzip/unzip.go @@ -3,22 +3,15 @@ package unzip import ( - "context" "net/http" ) -//go:generate mockgen -destination=mock_$GOPACKAGE/$GOFILE . Unzipper - -type Unzipper interface { - FetchAndExtract(ctx context.Context, url string) (contents map[string][]byte, err error) -} - -type unzipper struct { +type Unzipper struct { client *http.Client } -func New(client *http.Client) Unzipper { - return &unzipper{ +func New(client *http.Client) *Unzipper { + return &Unzipper{ client: client, } } diff --git a/internal/updater/updater.go b/internal/updater/updater.go index 22288e3e..8f5f48e1 100644 --- a/internal/updater/updater.go +++ b/internal/updater/updater.go @@ -6,9 +6,6 @@ import ( "net/http" "time" - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider" "github.com/qdm12/gluetun/internal/updater/unzip" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -24,26 +21,7 @@ type Updater struct { logger Logger timeNow func() time.Time client *http.Client - unzipper unzip.Unzipper -} - -type Providers interface { - Get(providerName string) provider.Provider -} - -type Storage interface { - SetServers(provider string, servers []models.Server) (err error) - GetServersCount(provider string) (count int) - ServersAreEqual(provider string, servers []models.Server) (equal bool) - // Extra methods to match the provider.New storage interface - FilterServers(provider string, selection settings.ServerSelection) (filtered []models.Server, err error) - GetServerByName(provider string, name string) (server models.Server, ok bool) -} - -type Logger interface { - Info(s string) - Warn(s string) - Error(s string) + unzipper Unzipper } func New(httpClient *http.Client, storage Storage, diff --git a/internal/vpn/interfaces.go b/internal/vpn/interfaces.go new file mode 100644 index 00000000..000b5b5e --- /dev/null +++ b/internal/vpn/interfaces.go @@ -0,0 +1,88 @@ +package vpn + +import ( + "context" + "net" + + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/netlink" + "github.com/qdm12/gluetun/internal/portforward" + "github.com/qdm12/gluetun/internal/provider" + publicipmodels "github.com/qdm12/gluetun/internal/publicip/models" +) + +type Firewall interface { + SetVPNConnection(ctx context.Context, connection models.Connection, interfaceName string) error + SetAllowedPort(ctx context.Context, port uint16, interfaceName string) error + RemoveAllowedPort(ctx context.Context, port uint16) error +} + +type Routing interface { + VPNLocalGatewayIP(vpnInterface string) (gateway net.IP, err error) +} + +type PortForward interface { + Start(ctx context.Context, data portforward.StartData) (outcome string, err error) + Stop(ctx context.Context) (outcome string, err error) +} + +type OpenVPN interface { + WriteConfig(lines []string) error + WriteAuthFile(user, password string) error +} + +type StateManager interface { + GetSettings() (vpn settings.VPN) + SetSettings(ctx context.Context, vpn settings.VPN) (outcome string) +} + +type Providers interface { + Get(providerName string) provider.Provider +} + +type Storage interface { + FilterServers(provider string, selection settings.ServerSelection) (servers []models.Server, err error) + GetServerByName(provider, name string) (server models.Server, ok bool) +} + +type NetLinker interface { + AddrAdd(link netlink.Link, addr *netlink.Addr) error + IsWireguardSupported() (ok bool, err error) + RouteList(link netlink.Link, family int) ( + routes []netlink.Route, err error) + RouteAdd(route *netlink.Route) error + RuleAdd(rule *netlink.Rule) error + RuleDel(rule *netlink.Rule) error + LinkList() (links []netlink.Link, err error) + LinkByName(name string) (link netlink.Link, err error) + LinkAdd(link netlink.Link) (err error) + LinkDel(link netlink.Link) (err error) + LinkSetUp(link netlink.Link) (err error) + LinkSetDown(link netlink.Link) (err error) +} + +type DNSLoop interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) + GetSettings() (settings settings.DNS) +} + +type PublicIPLoop interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) + SetData(data publicipmodels.IPInfoData) +} + +type statusManager interface { + GetStatus() (status models.LoopStatus) + SetStatus(status models.LoopStatus) + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) + Lock() + Unlock() +} + +type runner interface { + Run(ctx context.Context, waitError chan<- error, tunnelReady chan<- struct{}) +} diff --git a/internal/vpn/loop.go b/internal/vpn/loop.go index c36ce97b..07eacb80 100644 --- a/internal/vpn/loop.go +++ b/internal/vpn/loop.go @@ -6,33 +6,16 @@ import ( "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" - "github.com/qdm12/gluetun/internal/dns" - "github.com/qdm12/gluetun/internal/firewall" "github.com/qdm12/gluetun/internal/loopstate" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/netlink" - "github.com/qdm12/gluetun/internal/openvpn" - "github.com/qdm12/gluetun/internal/portforward" - "github.com/qdm12/gluetun/internal/provider" - "github.com/qdm12/gluetun/internal/publicip" - "github.com/qdm12/gluetun/internal/routing" "github.com/qdm12/gluetun/internal/vpn/state" "github.com/qdm12/golibs/command" "github.com/qdm12/log" ) -var _ Looper = (*Loop)(nil) - -type Looper interface { - Runner - loopstate.Getter - loopstate.Applier - SettingsGetSetter -} - type Loop struct { - statusManager loopstate.Manager - state state.Manager + statusManager statusManager + state StateManager providers Providers storage Storage // Fixed parameters @@ -40,13 +23,13 @@ type Loop struct { versionInfo bool vpnInputPorts []uint16 // TODO make changeable through stateful firewall // Configurators - openvpnConf openvpn.Interface - netLinker netlink.NetLinker - fw firewallConfigurer - routing routing.VPNGetter - portForward portforward.StartStopper - publicip publicip.Looper - dnsLooper dns.Looper + openvpnConf OpenVPN + netLinker NetLinker + fw Firewall + routing Routing + portForward PortForward + publicip PublicIPLoop + dnsLooper DNSLoop // Other objects starter command.Starter // for OpenVPN logger log.LoggerInterface @@ -61,29 +44,15 @@ type Loop struct { backoffTime time.Duration } -type firewallConfigurer interface { - firewall.VPNConnectionSetter - firewall.PortAllower -} - -type Providers interface { - Get(providerName string) provider.Provider -} - -type Storage interface { - FilterServers(provider string, selection settings.ServerSelection) (servers []models.Server, err error) - GetServerByName(provider, name string) (server models.Server, ok bool) -} - const ( defaultBackoffTime = 15 * time.Second ) func NewLoop(vpnSettings settings.VPN, vpnInputPorts []uint16, - providers Providers, storage Storage, openvpnConf openvpn.Interface, - netLinker netlink.NetLinker, fw firewallConfigurer, routing routing.VPNGetter, - portForward portforward.StartStopper, starter command.Starter, - publicip publicip.Looper, dnsLooper dns.Looper, + providers Providers, storage Storage, openvpnConf OpenVPN, + netLinker NetLinker, fw Firewall, routing Routing, + portForward PortForward, starter command.Starter, + publicip PublicIPLoop, dnsLooper DNSLoop, logger log.LoggerInterface, client *http.Client, buildInfo models.BuildInformation, versionInfo bool) *Loop { start := make(chan struct{}) diff --git a/internal/vpn/openvpn.go b/internal/vpn/openvpn.go index d6fd48a5..7bcb4a07 100644 --- a/internal/vpn/openvpn.go +++ b/internal/vpn/openvpn.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/firewall" "github.com/qdm12/gluetun/internal/openvpn" "github.com/qdm12/gluetun/internal/provider" "github.com/qdm12/golibs/command" @@ -13,10 +12,10 @@ import ( // setupOpenVPN sets OpenVPN up using the configurators and settings given. // It returns a serverName for port forwarding (PIA) and an error if it fails. -func setupOpenVPN(ctx context.Context, fw firewall.VPNConnectionSetter, - openvpnConf openvpn.Interface, providerConf provider.Provider, +func setupOpenVPN(ctx context.Context, fw Firewall, + openvpnConf OpenVPN, providerConf provider.Provider, settings settings.VPN, starter command.Starter, logger openvpn.Logger) ( - runner vpnRunner, serverName string, err error) { + runner *openvpn.Runner, serverName string, err error) { connection, err := providerConf.GetConnection(settings.Provider.ServerSelection) if err != nil { return nil, "", fmt.Errorf("failed finding a valid server connection: %w", err) diff --git a/internal/vpn/run.go b/internal/vpn/run.go index 6222943f..693cd8fa 100644 --- a/internal/vpn/run.go +++ b/internal/vpn/run.go @@ -8,14 +8,6 @@ import ( "github.com/qdm12/log" ) -type Runner interface { - Run(ctx context.Context, done chan<- struct{}) -} - -type vpnRunner interface { - Run(ctx context.Context, errCh chan<- error, ready chan<- struct{}) -} - func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { defer close(done) @@ -31,7 +23,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { providerConf := l.providers.Get(*settings.Provider.Name) portForwarding := *settings.Provider.PortForwarding.Enabled - var vpnRunner vpnRunner + var vpnRunner runner var serverName, vpnInterface string var err error subLogger := l.logger.New(log.SetComponent(settings.Type)) diff --git a/internal/vpn/settings.go b/internal/vpn/settings.go index 7256c4a2..052e6561 100644 --- a/internal/vpn/settings.go +++ b/internal/vpn/settings.go @@ -4,11 +4,8 @@ import ( "context" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/vpn/state" ) -type SettingsGetSetter = state.SettingsGetSetter - func (l *Loop) GetSettings() (settings settings.VPN) { return l.state.GetSettings() } diff --git a/internal/vpn/state/state.go b/internal/vpn/state/state.go index df48aaa7..7ed8cdf6 100644 --- a/internal/vpn/state/state.go +++ b/internal/vpn/state/state.go @@ -1,19 +1,14 @@ package state import ( + "context" "sync" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/loopstate" + "github.com/qdm12/gluetun/internal/models" ) -var _ Manager = (*State)(nil) - -type Manager interface { - SettingsGetSetter -} - -func New(statusApplier loopstate.Applier, vpn settings.VPN) *State { +func New(statusApplier StatusApplier, vpn settings.VPN) *State { return &State{ statusApplier: statusApplier, vpn: vpn, @@ -21,8 +16,13 @@ func New(statusApplier loopstate.Applier, vpn settings.VPN) *State { } type State struct { - statusApplier loopstate.Applier + statusApplier StatusApplier vpn settings.VPN settingsMu sync.RWMutex } + +type StatusApplier interface { + ApplyStatus(ctx context.Context, status models.LoopStatus) ( + outcome string, err error) +} diff --git a/internal/vpn/state/vpn.go b/internal/vpn/state/vpn.go index 7af2b992..34d75298 100644 --- a/internal/vpn/state/vpn.go +++ b/internal/vpn/state/vpn.go @@ -8,11 +8,6 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -type SettingsGetSetter interface { - GetSettings() (vpn settings.VPN) - SetSettings(ctx context.Context, vpn settings.VPN) (outcome string) -} - func (s *State) GetSettings() (vpn settings.VPN) { s.settingsMu.RLock() vpn = s.vpn diff --git a/internal/vpn/wireguard.go b/internal/vpn/wireguard.go index 3f9771d6..44e0f8fe 100644 --- a/internal/vpn/wireguard.go +++ b/internal/vpn/wireguard.go @@ -5,8 +5,6 @@ import ( "fmt" "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/firewall" - "github.com/qdm12/gluetun/internal/netlink" "github.com/qdm12/gluetun/internal/provider" "github.com/qdm12/gluetun/internal/provider/utils" "github.com/qdm12/gluetun/internal/wireguard" @@ -14,10 +12,10 @@ import ( // setupWireguard sets Wireguard up using the configurators and settings given. // It returns a serverName for port forwarding (PIA) and an error if it fails. -func setupWireguard(ctx context.Context, netlinker netlink.NetLinker, - fw firewall.VPNConnectionSetter, providerConf provider.Provider, +func setupWireguard(ctx context.Context, netlinker NetLinker, + fw Firewall, providerConf provider.Provider, settings settings.VPN, logger wireguard.Logger) ( - wireguarder wireguard.Wireguarder, serverName string, err error) { + wireguarder *wireguard.Wireguard, serverName string, err error) { connection, err := providerConf.GetConnection(settings.Provider.ServerSelection) if err != nil { return nil, "", fmt.Errorf("failed finding a VPN server: %w", err) diff --git a/internal/wireguard/constructor.go b/internal/wireguard/constructor.go index a8cbe954..15c4f7c1 100644 --- a/internal/wireguard/constructor.go +++ b/internal/wireguard/constructor.go @@ -1,12 +1,5 @@ package wireguard -var _ Wireguarder = (*Wireguard)(nil) - -type Wireguarder interface { - Runner - Runner -} - type Wireguard struct { logger Logger settings Settings diff --git a/internal/wireguard/run.go b/internal/wireguard/run.go index 6c679607..584c5ea0 100644 --- a/internal/wireguard/run.go +++ b/internal/wireguard/run.go @@ -34,10 +34,6 @@ var ( ErrDeviceWaited = errors.New("device waited for") ) -type Runner interface { - Run(ctx context.Context, waitError chan<- error, ready chan<- struct{}) -} - // See https://git.zx2c4.com/wireguard-go/tree/main.go func (w *Wireguard) Run(ctx context.Context, waitError chan<- error, ready chan<- struct{}) { doIPv6, err := w.isIPv6Supported()