chore(updater): common GetServers signature

- Log warnings when running outside of CLI mode
- Remove updater CLI bool setting
- Warnings are logged in updating functions
This commit is contained in:
Quentin McGaw
2022-05-28 20:58:50 +00:00
parent 381089ebdf
commit 90c6c8485b
50 changed files with 896 additions and 325 deletions

View File

@@ -0,0 +1,3 @@
package ivpn
//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . Warner

View File

@@ -0,0 +1,46 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/qdm12/gluetun/internal/provider/ivpn/updater (interfaces: Warner)
// Package ivpn is a generated GoMock package.
package ivpn
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
)
// MockWarner is a mock of Warner interface.
type MockWarner struct {
ctrl *gomock.Controller
recorder *MockWarnerMockRecorder
}
// MockWarnerMockRecorder is the mock recorder for MockWarner.
type MockWarnerMockRecorder struct {
mock *MockWarner
}
// NewMockWarner creates a new mock instance.
func NewMockWarner(ctrl *gomock.Controller) *MockWarner {
mock := &MockWarner{ctrl: ctrl}
mock.recorder = &MockWarnerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockWarner) EXPECT() *MockWarnerMockRecorder {
return m.recorder
}
// Warn mocks base method.
func (m *MockWarner) Warn(arg0 string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Warn", arg0)
}
// Warn indicates an expected call of Warn.
func (mr *MockWarnerMockRecorder) Warn(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warn", reflect.TypeOf((*MockWarner)(nil).Warn), arg0)
}

View File

@@ -6,23 +6,20 @@ import (
"context"
"errors"
"fmt"
"net/http"
"github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/updater/resolver"
)
var (
ErrNotEnoughServers = errors.New("not enough servers found")
)
func GetServers(ctx context.Context, client *http.Client,
presolver resolver.Parallel, minServers int) (
servers []models.Server, warnings []string, err error) {
data, err := fetchAPI(ctx, client)
func (u *Updater) GetServers(ctx context.Context, minServers int) (
servers []models.Server, err error) {
data, err := fetchAPI(ctx, u.client)
if err != nil {
return nil, nil, fmt.Errorf("failed fetching API: %w", err)
return nil, fmt.Errorf("failed fetching API: %w", err)
}
hosts := make([]string, 0, len(data.Servers))
@@ -40,13 +37,16 @@ func GetServers(ctx context.Context, client *http.Client,
}
if len(hosts) < minServers {
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
return nil, fmt.Errorf("%w: %d and expected at least %d",
ErrNotEnoughServers, len(hosts), minServers)
}
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
for _, warning := range warnings {
u.warner.Warn(warning)
}
if err != nil {
return nil, warnings, err
return nil, err
}
servers = make([]models.Server, 0, len(hosts))
@@ -78,5 +78,5 @@ func GetServers(ctx context.Context, client *http.Client,
sortServers(servers)
return servers, warnings, nil
return servers, nil
}

View File

@@ -18,13 +18,16 @@ import (
"github.com/stretchr/testify/require"
)
func Test_GetServers(t *testing.T) {
func Test_Updater_GetServers(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
// Inputs
minServers int
// Mocks
warnerBuilder func(ctrl *gomock.Controller) Warner
// From API
responseBody string
responseStatus int
@@ -38,15 +41,20 @@ func Test_GetServers(t *testing.T) {
resolveErr error
// Output
servers []models.Server
warnings []string
err error
servers []models.Server
err error
}{
"http response error": {
warnerBuilder: func(ctrl *gomock.Controller) 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 {
warner := NewMockWarner(ctrl)
warner.EXPECT().Warn("resolve warning")
return warner
},
responseBody: `{"servers":[
{"hostnames":{"openvpn":"hosta"}}
]}`,
@@ -56,11 +64,11 @@ func Test_GetServers(t *testing.T) {
resolveSettings: getResolveSettings(0),
resolveWarnings: []string{"resolve warning"},
resolveErr: errors.New("dummy"),
warnings: []string{"resolve warning"},
err: errors.New("dummy"),
},
"not enough servers": {
minServers: 2,
minServers: 2,
warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil },
responseBody: `{"servers":[
{"hostnames":{"openvpn":"hosta"}}
]}`,
@@ -69,6 +77,11 @@ func Test_GetServers(t *testing.T) {
},
"success": {
minServers: 1,
warnerBuilder: func(ctrl *gomock.Controller) Warner {
warner := NewMockWarner(ctrl)
warner.EXPECT().Warn("resolve warning")
return warner
},
responseBody: `{"servers":[
{"country":"Country1","city":"City A","hostnames":{"openvpn":"hosta"}},
{"country":"Country2","city":"City B","hostnames":{"openvpn":"hostb"},"wg_public_key":"xyz"},
@@ -97,7 +110,6 @@ func Test_GetServers(t *testing.T) {
WgPubKey: "xyz",
IPs: []net.IP{{5, 5, 5, 5}, {6, 6, 6, 6}}},
},
warnings: []string{"resolve warning"},
},
}
for name, testCase := range testCases {
@@ -126,10 +138,13 @@ func Test_GetServers(t *testing.T) {
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
}
servers, warnings, err := GetServers(ctx, client, presolver, testCase.minServers)
warner := testCase.warnerBuilder(ctrl)
updater := New(client, presolver, warner)
servers, err := updater.GetServers(ctx, testCase.minServers)
assert.Equal(t, testCase.servers, servers)
assert.Equal(t, testCase.warnings, warnings)
if testCase.err != nil {
require.Error(t, err)
assert.Equal(t, testCase.err.Error(), err.Error())

View File

@@ -0,0 +1,26 @@
package ivpn
import (
"net/http"
"github.com/qdm12/gluetun/internal/updater/resolver"
)
type Updater struct {
client *http.Client
presolver resolver.Parallel
warner Warner
}
type Warner interface {
Warn(s string)
}
func New(client *http.Client, presolver resolver.Parallel,
warner Warner) *Updater {
return &Updater{
client: client,
presolver: presolver,
warner: warner,
}
}