chore(lint): add ireturn linter

- Return concrete structs
- Accept interfaces
- Define narrow interfaces locally where needed
This commit is contained in:
Quentin McGaw
2022-08-28 19:50:02 +00:00
parent 45c684232d
commit 1561babd76
25 changed files with 83 additions and 115 deletions

View File

@@ -41,6 +41,7 @@ linters:
- gosec
# - goerr113 # TODO
- importas
- ireturn
- lll
- misspell
- nakedret

View File

@@ -23,7 +23,7 @@ import (
"github.com/qdm12/ddns-updater/internal/health"
"github.com/qdm12/ddns-updater/internal/models"
jsonparams "github.com/qdm12/ddns-updater/internal/params"
"github.com/qdm12/ddns-updater/internal/persistence"
persistence "github.com/qdm12/ddns-updater/internal/persistence/json"
recordslib "github.com/qdm12/ddns-updater/internal/records"
"github.com/qdm12/ddns-updater/internal/server"
"github.com/qdm12/ddns-updater/internal/update"
@@ -164,7 +164,7 @@ func _main(ctx context.Context, env params.Interface, args []string, logger logg
}
}
persistentDB, err := persistence.NewJSON(config.Paths.DataDir)
persistentDB, err := persistence.NewDatabase(config.Paths.DataDir)
if err != nil {
notify(err.Error())
return err

View File

@@ -3,25 +3,17 @@ package data
import (
"sync"
"github.com/qdm12/ddns-updater/internal/persistence"
"github.com/qdm12/ddns-updater/internal/records"
)
var _ Database = (*database)(nil)
type Database interface {
EphemeralDatabase
PersistentDatabase
}
type database struct {
data []records.Record
sync.RWMutex
persistentDB persistence.Database
persistentDB PersistentDatabase
}
// NewDatabase creates a new in memory database.
func NewDatabase(data []records.Record, persistentDB persistence.Database) Database {
func NewDatabase(data []records.Record, persistentDB PersistentDatabase) *database {
return &database{
data: data,
persistentDB: persistentDB,

View File

@@ -1,20 +1,15 @@
package persistence
package data
import (
"net"
"time"
"github.com/qdm12/ddns-updater/internal/models"
"github.com/qdm12/ddns-updater/internal/persistence/json"
)
type Database interface {
type PersistentDatabase interface {
Close() error
StoreNewIP(domain, host string, ip net.IP, t time.Time) (err error)
GetEvents(domain, host string) (events []models.HistoryEvent, err error)
Check() error
}
func NewJSON(dataDir string) (Database, error) {
return json.NewDatabase(dataDir)
}

View File

@@ -6,11 +6,6 @@ import (
"github.com/qdm12/ddns-updater/internal/records"
)
type EphemeralDatabase interface {
Select(id int) (record records.Record, err error)
SelectAll() (records []records.Record)
}
func (db *database) Select(id int) (record records.Record, err error) {
db.RLock()
defer db.RUnlock()

View File

@@ -7,14 +7,6 @@ import (
"github.com/qdm12/ddns-updater/internal/records"
)
var _ PersistentDatabase = (*database)(nil)
type PersistentDatabase interface {
GetEvents(domain, host string) (events []models.HistoryEvent, err error)
Update(id int, record records.Record) (err error)
Close() (err error)
}
func (db *database) GetEvents(domain, host string) (events []models.HistoryEvent, err error) {
return db.persistentDB.GetEvents(domain, host)
}

View File

@@ -6,20 +6,19 @@ import (
"strings"
"github.com/qdm12/ddns-updater/internal/constants"
"github.com/qdm12/ddns-updater/internal/data"
"github.com/qdm12/golibs/logging"
)
type lookupIPFunc func(host string) ([]net.IP, error)
func MakeIsHealthy(db data.Database, lookupIP lookupIPFunc, logger logging.Logger) func() error {
func MakeIsHealthy(db AllSelecter, lookupIP lookupIPFunc, logger logging.Logger) func() error {
return func() (err error) {
return isHealthy(db, lookupIP)
}
}
// isHealthy checks all the records were updated successfully and returns an error if not.
func isHealthy(db data.Database, lookupIP lookupIPFunc) (err error) {
func isHealthy(db AllSelecter, lookupIP lookupIPFunc) (err error) {
records := db.SelectAll()
for _, record := range records {
if record.Status == constants.FAIL {

View File

@@ -14,15 +14,11 @@ func IsClientMode(args []string) bool {
return len(args) > 1 && args[1] == "healthcheck"
}
type Client interface {
Query(ctx context.Context, port uint16) error
}
type client struct {
*http.Client
}
func NewClient() Client {
func NewClient() *client {
const timeout = 5 * time.Second
return &client{
Client: &http.Client{Timeout: timeout},

View File

@@ -0,0 +1,7 @@
package health
import "github.com/qdm12/ddns-updater/internal/records"
type AllSelecter interface {
SelectAll() (records []records.Record)
}

View File

@@ -8,17 +8,13 @@ import (
"github.com/qdm12/golibs/logging"
)
type Server interface {
Run(ctx context.Context, done chan<- struct{})
}
type server struct {
address string
logger logging.Logger
handler http.Handler
}
func NewServer(address string, logger logging.Logger, healthcheck func() error) Server {
func NewServer(address string, logger logging.Logger, healthcheck func() error) *server {
handler := newHandler(logger, healthcheck)
return &server{
address: address,

View File

@@ -4,15 +4,10 @@ import (
"io/fs"
"os"
"github.com/qdm12/ddns-updater/internal/settings"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/params"
)
type Reader interface {
JSONSettings(filePath string) (allSettings []settings.Settings, warnings []string, err error)
}
type reader struct {
logger logging.Logger
env envInterface
@@ -20,7 +15,7 @@ type reader struct {
writeFile func(filename string, data []byte, perm fs.FileMode) (err error)
}
func NewReader(logger logging.Logger) Reader {
func NewReader(logger logging.Logger) *reader {
return &reader{
logger: logger,
env: params.New(),

View File

@@ -31,7 +31,7 @@ var (
dnsOMaticPassword = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9._-]{5,19}$`)
)
func NewMatcher() Matcher {
func NewMatcher() *matcher {
return &matcher{
gandiKey: gandiKey,
goDaddyKey: goDaddyKey,

View File

@@ -9,15 +9,13 @@ import (
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/qdm12/ddns-updater/internal/data"
"github.com/qdm12/ddns-updater/internal/update"
)
type handlers struct {
ctx context.Context
// Objects
db data.Database
runner update.Runner
db Database
runner UpdateForcer
indexTemplate *template.Template
// Mockable functions
timeNow func() time.Time
@@ -27,7 +25,7 @@ type handlers struct {
var uiFS embed.FS
func newHandler(ctx context.Context, rootURL string,
db data.Database, runner update.Runner) http.Handler {
db Database, runner UpdateForcer) http.Handler {
indexTemplate := template.Must(template.ParseFS(uiFS, "ui/index.html"))
handlers := &handlers{

View File

@@ -0,0 +1,15 @@
package server
import (
"context"
"github.com/qdm12/ddns-updater/internal/records"
)
type Database interface {
SelectAll() (records []records.Record)
}
type UpdateForcer interface {
ForceUpdate(ctx context.Context) (errors []error)
}

View File

@@ -5,23 +5,17 @@ import (
"net/http"
"time"
"github.com/qdm12/ddns-updater/internal/data"
"github.com/qdm12/ddns-updater/internal/update"
"github.com/qdm12/golibs/logging"
)
type Server interface {
Run(ctx context.Context, done chan<- struct{})
}
type server struct {
address string
logger logging.Logger
handler http.Handler
}
func New(ctx context.Context, address, rootURL string, db data.Database, logger logging.Logger,
runner update.Runner) Server {
func New(ctx context.Context, address, rootURL string, db Database,
logger logging.Logger, runner UpdateForcer) *server {
handler := newHandler(ctx, rootURL, db, runner)
return &server{
address: address,

View File

@@ -61,7 +61,7 @@ type Settings interface {
var ErrProviderUnknown = errors.New("unknown provider")
//nolint:gocyclo
func New(provider models.Provider, data json.RawMessage, domain, host string,
func New(provider models.Provider, data json.RawMessage, domain, host string, //nolint:ireturn
ipVersion ipversion.IPVersion, matcher regex.Matcher) (
settings Settings, err error) {
switch provider {

View File

@@ -0,0 +1,25 @@
package update
import (
"context"
"net"
"time"
"github.com/qdm12/ddns-updater/internal/records"
)
type PublicIPFetcher interface {
IP(ctx context.Context) (net.IP, error)
IP4(ctx context.Context) (net.IP, error)
IP6(ctx context.Context) (net.IP, error)
}
type Updater interface {
Update(ctx context.Context, recordID int, ip net.IP, now time.Time) (err error)
}
type Database interface {
Select(recordID int) (record records.Record, err error)
SelectAll() (records []records.Record)
Update(recordID int, record records.Record) (err error)
}

View File

@@ -7,36 +7,29 @@ import (
"time"
"github.com/qdm12/ddns-updater/internal/constants"
"github.com/qdm12/ddns-updater/internal/data"
"github.com/qdm12/ddns-updater/internal/models"
librecords "github.com/qdm12/ddns-updater/internal/records"
"github.com/qdm12/ddns-updater/pkg/publicip"
"github.com/qdm12/ddns-updater/pkg/publicip/ipversion"
"github.com/qdm12/golibs/logging"
)
type Runner interface {
Run(ctx context.Context, done chan<- struct{})
ForceUpdate(ctx context.Context) []error
}
type runner struct {
period time.Duration
db data.Database
db Database
updater Updater
force chan struct{}
forceResult chan []error
ipv6Mask net.IPMask
cooldown time.Duration
resolver *net.Resolver
ipGetter publicip.Fetcher
ipGetter PublicIPFetcher
logger logging.Logger
timeNow func() time.Time
}
func NewRunner(db data.Database, updater Updater, ipGetter publicip.Fetcher,
func NewRunner(db Database, updater Updater, ipGetter PublicIPFetcher,
period time.Duration, ipv6Mask net.IPMask, cooldown time.Duration,
logger logging.Logger, timeNow func() time.Time) Runner {
logger logging.Logger, timeNow func() time.Time) *runner {
return &runner{
period: period,
db: db,
@@ -246,7 +239,7 @@ func getIPMatchingVersion(ip, ipv4, ipv6 net.IP, ipVersion ipversion.IPVersion)
return nil
}
func setInitialUpToDateStatus(db data.Database, id int, updateIP net.IP, now time.Time) error {
func setInitialUpToDateStatus(db Database, id int, updateIP net.IP, now time.Time) error {
record, err := db.Select(id)
if err != nil {
return err

View File

@@ -9,18 +9,13 @@ import (
"time"
"github.com/qdm12/ddns-updater/internal/constants"
"github.com/qdm12/ddns-updater/internal/data"
"github.com/qdm12/ddns-updater/internal/models"
settingserrors "github.com/qdm12/ddns-updater/internal/settings/errors"
"github.com/qdm12/golibs/logging"
)
type Updater interface {
Update(ctx context.Context, id int, ip net.IP, now time.Time) (err error)
}
type updater struct {
db data.Database
db Database
client *http.Client
notify notifyFunc
logger logging.Logger
@@ -28,7 +23,7 @@ type updater struct {
type notifyFunc func(message string)
func NewUpdater(db data.Database, client *http.Client, notify notifyFunc, logger logging.Logger) Updater {
func NewUpdater(db Database, client *http.Client, notify notifyFunc, logger logging.Logger) *updater {
client = makeLogClient(client, logger)
return &updater{
db: db,

View File

@@ -1,18 +1,11 @@
package dns
import (
"context"
"net"
"github.com/miekg/dns"
)
type Fetcher interface {
IP(ctx context.Context) (publicIP net.IP, err error)
IP4(ctx context.Context) (publicIP net.IP, err error)
IP6(ctx context.Context) (publicIP net.IP, err error)
}
type fetcher struct {
ring ring
client Client
@@ -26,7 +19,7 @@ type ring struct {
providers []Provider
}
func New(options ...Option) (f Fetcher, err error) {
func New(options ...Option) (f *fetcher, err error) {
settings := newDefaultSettings()
for _, option := range options {
if err := option(&settings); err != nil {

View File

@@ -11,12 +11,9 @@ import (
func Test_New(t *testing.T) {
t.Parallel()
intf, err := New(SetTimeout(time.Hour))
impl, err := New(SetTimeout(time.Hour))
require.NoError(t, err)
impl, ok := intf.(*fetcher)
require.True(t, ok)
assert.NotNil(t, impl.ring.counter)
assert.NotEmpty(t, impl.ring.providers)
assert.NotNil(t, impl.client)

View File

@@ -1,20 +1,12 @@
package http
import (
"context"
"net"
"net/http"
"time"
"github.com/qdm12/ddns-updater/pkg/publicip/ipversion"
)
type Fetcher interface {
IP(ctx context.Context) (publicIP net.IP, err error)
IP4(ctx context.Context) (publicIP net.IP, err error)
IP6(ctx context.Context) (publicIP net.IP, err error)
}
type fetcher struct {
client *http.Client
timeout time.Duration
@@ -28,7 +20,7 @@ type urlsRing struct {
urls []string
}
func New(client *http.Client, options ...Option) (f Fetcher, err error) {
func New(client *http.Client, options ...Option) (f *fetcher, err error) {
settings := newDefaultSettings()
for _, option := range options {
if err := option(&settings); err != nil {

View File

@@ -75,18 +75,16 @@ func Test_New(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()
f, err := New(client, testCase.options...)
fetcher, err := New(client, testCase.options...)
if testCase.err != nil {
require.Error(t, err)
assert.Equal(t, testCase.err.Error(), err.Error())
assert.Nil(t, f)
assert.Nil(t, fetcher)
return
}
assert.NoError(t, err)
implementation, ok := f.(*fetcher)
require.True(t, ok)
assert.Equal(t, testCase.fetcher, implementation)
assert.Equal(t, testCase.fetcher, fetcher)
})
}
}

View File

@@ -9,7 +9,7 @@ import (
"github.com/qdm12/ddns-updater/pkg/publicip/http"
)
type Fetcher interface {
type ipFetcher interface {
IP(ctx context.Context) (ip net.IP, err error)
IP4(ctx context.Context) (ipv4 net.IP, err error)
IP6(ctx context.Context) (ipv6 net.IP, err error)
@@ -17,14 +17,14 @@ type Fetcher interface {
type fetcher struct {
settings settings
fetchers []Fetcher
fetchers []ipFetcher
// Cycling effect if both are enabled
counter *uint32 // 32 bit for 32 bit systems
}
var ErrNoFetchTypeSpecified = errors.New("at least one fetcher type must be specified")
func NewFetcher(dnsSettings DNSSettings, httpSettings HTTPSettings) (f Fetcher, err error) {
func NewFetcher(dnsSettings DNSSettings, httpSettings HTTPSettings) (f *fetcher, err error) {
settings := settings{
dns: dnsSettings,
http: httpSettings,

View File

@@ -4,7 +4,7 @@ import (
"sync/atomic"
)
func (f *fetcher) getSubFetcher() Fetcher {
func (f *fetcher) getSubFetcher() ipFetcher { //nolint:ireturn
fetcher := f.fetchers[0]
if len(f.fetchers) > 1 { // cycling effect
index := int(atomic.AddUint32(f.counter, 1)) % len(f.fetchers)