Code maintenance: OS user abstraction interface

This commit is contained in:
Quentin McGaw
2020-12-29 01:16:53 +00:00
parent da4e410bb7
commit f55fb4055f
6 changed files with 108 additions and 14 deletions

View File

@@ -23,6 +23,7 @@ import (
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/openvpn"
"github.com/qdm12/gluetun/internal/os"
"github.com/qdm12/gluetun/internal/os/user"
"github.com/qdm12/gluetun/internal/params"
"github.com/qdm12/gluetun/internal/publicip"
"github.com/qdm12/gluetun/internal/routing"
@@ -53,11 +54,12 @@ func main() {
ctx := context.Background()
args := nativeos.Args
os := os.New()
nativeos.Exit(_main(ctx, args, os))
osUser := user.New()
nativeos.Exit(_main(ctx, args, os, osUser))
}
//nolint:gocognit,gocyclo
func _main(background context.Context, args []string, os os.OS) int {
func _main(background context.Context, args []string, os os.OS, osUser user.OSUser) int {
if len(args) > 1 { // cli operation
var err error
switch args[1] {
@@ -86,7 +88,7 @@ func _main(background context.Context, args []string, os os.OS) int {
httpClient := &http.Client{Timeout: clientTimeout}
client := network.NewClient(clientTimeout)
// Create configurators
alpineConf := alpine.NewConfigurator(os.OpenFile)
alpineConf := alpine.NewConfigurator(os.OpenFile, osUser)
unix := unix.New()
ovpnConf := openvpn.NewConfigurator(logger, os, unix)
dnsConf := dns.NewConfigurator(logger, client, os.OpenFile)

View File

@@ -1,9 +1,8 @@
package alpine
import (
"os/user"
"github.com/qdm12/gluetun/internal/os"
"github.com/qdm12/gluetun/internal/os/user"
)
type Configurator interface {
@@ -11,15 +10,13 @@ type Configurator interface {
}
type configurator struct {
openFile os.OpenFileFunc
lookupUID func(uid string) (*user.User, error)
lookupUser func(username string) (*user.User, error)
openFile os.OpenFileFunc
osUser user.OSUser
}
func NewConfigurator(openFile os.OpenFileFunc) Configurator {
func NewConfigurator(openFile os.OpenFileFunc, osUser user.OSUser) Configurator {
return &configurator{
openFile: openFile,
lookupUID: user.LookupId,
lookupUser: user.Lookup,
openFile: openFile,
osUser: osUser,
}
}

View File

@@ -9,7 +9,7 @@ import (
// CreateUser creates a user in Alpine with the given UID.
func (c *configurator) CreateUser(username string, uid int) (createdUsername string, err error) {
UIDStr := fmt.Sprintf("%d", uid)
u, err := c.lookupUID(UIDStr)
u, err := c.osUser.LookupID(UIDStr)
_, unknownUID := err.(user.UnknownUserIdError)
if err != nil && !unknownUID {
return "", fmt.Errorf("cannot create user: %w", err)
@@ -19,7 +19,7 @@ func (c *configurator) CreateUser(username string, uid int) (createdUsername str
}
return u.Username, nil
}
u, err = c.lookupUser(username)
u, err = c.osUser.Lookup(username)
_, unknownUsername := err.(user.UnknownUserError)
if err != nil && !unknownUsername {
return "", fmt.Errorf("cannot create user: %w", err)

View File

@@ -0,0 +1,7 @@
package user
import osuser "os/user"
// Aliases used for convenience so "os/user" does not have to be imported
type User osuser.User

View File

@@ -0,0 +1,64 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/qdm12/gluetun/internal/os/user (interfaces: OSUser)
// Package mock_user is a generated GoMock package.
package mock_user
import (
gomock "github.com/golang/mock/gomock"
user "os/user"
reflect "reflect"
)
// MockOSUser is a mock of OSUser interface
type MockOSUser struct {
ctrl *gomock.Controller
recorder *MockOSUserMockRecorder
}
// MockOSUserMockRecorder is the mock recorder for MockOSUser
type MockOSUserMockRecorder struct {
mock *MockOSUser
}
// NewMockOSUser creates a new mock instance
func NewMockOSUser(ctrl *gomock.Controller) *MockOSUser {
mock := &MockOSUser{ctrl: ctrl}
mock.recorder = &MockOSUserMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockOSUser) EXPECT() *MockOSUserMockRecorder {
return m.recorder
}
// Lookup mocks base method
func (m *MockOSUser) Lookup(arg0 string) (*user.User, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Lookup", arg0)
ret0, _ := ret[0].(*user.User)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Lookup indicates an expected call of Lookup
func (mr *MockOSUserMockRecorder) Lookup(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lookup", reflect.TypeOf((*MockOSUser)(nil).Lookup), arg0)
}
// LookupID mocks base method
func (m *MockOSUser) LookupID(arg0 string) (*user.User, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "LookupID", arg0)
ret0, _ := ret[0].(*user.User)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// LookupID indicates an expected call of LookupID
func (mr *MockOSUserMockRecorder) LookupID(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupID", reflect.TypeOf((*MockOSUser)(nil).LookupID), arg0)
}

24
internal/os/user/user.go Normal file
View File

@@ -0,0 +1,24 @@
package user
import osuser "os/user"
//go:generate mockgen -destination=mock_$GOPACKAGE/$GOFILE . OSUser
type OSUser interface {
LookupID(uid string) (*osuser.User, error)
Lookup(username string) (*osuser.User, error)
}
func New() OSUser {
return &osUser{}
}
type osUser struct{}
func (u *osUser) LookupID(uid string) (*osuser.User, error) {
return osuser.LookupId(uid)
}
func (u *osUser) Lookup(username string) (*osuser.User, error) {
return osuser.Lookup(username)
}