Linter updates

This commit is contained in:
IamTheFij 2022-02-22 16:55:41 -08:00
parent a1969b681a
commit 048e062102
8 changed files with 143 additions and 53 deletions

View File

@ -1,43 +1,105 @@
---
linters:
enable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- asciicheck
- bidichk
- bodyclose
- dogsled
- containedctx
- contextcheck
- cyclop
- decorder
- depguard
- dupl
- durationcheck
- errchkjson
- errname
- errorlint
- exhaustive
- exhaustivestruct
- exportloopref
- forcetypeassert
- funlen
- gci
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- goerr113
- gofumpt
# - gocyclo # Using cyclop
- godot
# - goerr113 # Using errorlint
- gofmt
- goheader
- goimports
- gomnd
- gomoddirectives
- gomodguard
- goprintffuncname
# - gosec
# - ifshort
- interfacer
- maligned
- gosec
- grouper
- ifshort
- importas
# - ireturn
- lll
- maintidx
- makezero
- misspell
- nakedret
- nestif
- nilerr
- nilnil
- nlreturn
- noctx
- nolintlint
- paralleltest
- prealloc
- predeclared
# - promlinter # Not common enough
- revive
- rowserrcheck
- sqlclosecheck
# - stylecheck # Using revive
- tagliatelle
- tenv
- testpackage
- thelper
- tparallel
- unconvert
- unparam
- varnamelen
- wastedassign
- whitespace
- wrapcheck
- wsl
# - errorlint
disable:
- gochecknoglobals
- godox
- forbidigo
# Deprecated
- golint
- interfacer
- maligned
- scopelint
linters-settings:
gosec:
excludes:
- G204
# gomnd:
# settings:
# mnd:
# ignored-functions: math.*
# gosec:
# excludes:
# - G204
gomnd:
settings:
mnd:
ignored-functions: math.*
issues:
exclude-rules:
@ -45,4 +107,5 @@ issues:
linters:
- errcheck
- gosec
- maligned
# Enable autofix
fix: true

3
go.mod
View File

@ -2,11 +2,12 @@ module git.iamthefij.com/iamthefij/restic-scheduler
go 1.17
require github.com/hashicorp/hcl/v2 v2.11.1
require (
github.com/agext/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/google/go-cmp v0.3.1 // indirect
github.com/hashicorp/hcl/v2 v2.11.1 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect
golang.org/x/text v0.3.5 // indirect

6
go.sum
View File

@ -5,7 +5,9 @@ github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -14,13 +16,17 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/hashicorp/hcl/v2 v2.11.1 h1:yTyWcXcm9XB0TEkyU/JCRU6rYy4K+mgLtzn2wlrJbcc=
github.com/hashicorp/hcl/v2 v2.11.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

46
job.go
View File

@ -16,7 +16,7 @@ type TaskConfig struct {
Restic *ResticCmd
}
// ResticConfig is all configuration to be sent to Restic
// ResticConfig is all configuration to be sent to Restic.
type ResticConfig struct {
Repo string `hcl:"repo"`
Passphrase string `hcl:"passphrase,optional"`
@ -24,14 +24,14 @@ type ResticConfig struct {
GlobalOpts *ResticGlobalOpts `hcl:"options,block"`
}
// ExecutableTask is a task to be run before or after backup/retore
// ExecutableTask is a task to be run before or after backup/retore.
type ExecutableTask interface {
RunBackup(cfg TaskConfig) error
RunRestore(cfg TaskConfig) error
Name() string
}
// JobTaskScript is a sript to be executed as part of a job task
// JobTaskScript is a sript to be executed as part of a job task.
type JobTaskScript struct {
OnBackup string `hcl:"on_backup,optional"`
OnRestore string `hcl:"on_restore,optional"`
@ -40,7 +40,7 @@ type JobTaskScript struct {
name string
}
// RunBackup runs script on backup
// RunBackup runs script on backup.
func (t JobTaskScript) RunBackup(cfg TaskConfig) error {
env := MergeEnv(cfg.Env, t.env)
if env == nil {
@ -61,7 +61,7 @@ func (t JobTaskScript) RunBackup(cfg TaskConfig) error {
return nil
}
// RunRestore script on restore
// RunRestore script on restore.
func (t JobTaskScript) RunRestore(cfg TaskConfig) error {
env := MergeEnv(cfg.Env, t.env)
if env == nil {
@ -90,7 +90,7 @@ func (t *JobTaskScript) SetName(name string) {
t.name = name
}
// JobTaskMySQL is a sqlite backup task that performs required pre and post tasks
// JobTaskMySQL is a sqlite backup task that performs required pre and post tasks.
type JobTaskMySQL struct {
Name string `hcl:"name,label"`
Hostname string `hcl:"hostname,optional"`
@ -102,6 +102,7 @@ type JobTaskMySQL struct {
func (t JobTaskMySQL) GetPreTask() ExecutableTask {
return JobTaskScript{
name: t.Name,
env: nil,
OnBackup: fmt.Sprintf(
"mysqldump -h '%s' -u '%s' -p '%s' '%s' > './%s.sql'",
t.Hostname,
@ -110,13 +111,16 @@ func (t JobTaskMySQL) GetPreTask() ExecutableTask {
t.Database,
t.Name,
),
OnRestore: "",
FromJobDir: true,
}
}
func (t JobTaskMySQL) GetPostTask() ExecutableTask {
return JobTaskScript{
name: t.Name,
name: t.Name,
env: nil,
OnBackup: "",
OnRestore: fmt.Sprintf(
"mysql -h '%s' -u '%s' -p '%s' '%s' << './%s.sql'",
t.Hostname,
@ -129,7 +133,7 @@ func (t JobTaskMySQL) GetPostTask() ExecutableTask {
}
}
// JobTaskSqlite is a sqlite backup task that performs required pre and post tasks
// JobTaskSqlite is a sqlite backup task that performs required pre and post tasks.
type JobTaskSqlite struct {
Name string `hcl:"name,label"`
Path string `hcl:"path"`
@ -138,17 +142,23 @@ type JobTaskSqlite struct {
func (t JobTaskSqlite) GetPreTask() ExecutableTask {
return JobTaskScript{
name: t.Name,
env: nil,
OnBackup: fmt.Sprintf(
"sqlite3 %s '.backup $RESTIC_JOB_DIR/%s.bak'",
t.Path, t.Name,
),
OnRestore: "",
FromJobDir: false,
}
}
func (t JobTaskSqlite) GetPostTask() ExecutableTask {
return JobTaskScript{
name: t.Name,
OnRestore: fmt.Sprintf("cp '$RESTIC_JOB_DIR/%s.bak' '%s'", t.Name, t.Path),
name: t.Name,
env: nil,
OnBackup: "",
OnRestore: fmt.Sprintf("cp '$RESTIC_JOB_DIR/%s.bak' '%s'", t.Name, t.Path),
FromJobDir: false,
}
}
@ -189,7 +199,7 @@ func (t *BackupFilesTask) SetName(name string) {
t.name = name
}
// JobTask represents a single task within a backup job
// JobTask represents a single task within a backup job.
type JobTask struct {
Name string `hcl:"name,label"`
Scripts []JobTaskScript `hcl:"script,block"`
@ -213,7 +223,7 @@ func (t JobTask) GetTasks() []ExecutableTask {
}
// Job contains all configuration required to construct and run a backup
// and restore job
// and restore job.
type Job struct {
Name string `hcl:"name,label"`
Schedule string `hcl:"schedule"`
@ -223,7 +233,7 @@ type Job struct {
Forget *ForgetOpts `hcl:"forget,block"`
// Meta Tasks
MySql []JobTaskMySQL `hcl:"mysql,block"`
MySQL []JobTaskMySQL `hcl:"mysql,block"`
Sqlite []JobTaskSqlite `hcl:"sqlite,block"`
}
@ -231,7 +241,7 @@ func (j Job) AllTasks() []ExecutableTask {
allTasks := []ExecutableTask{}
// Pre tasks
for _, mysql := range j.MySql {
for _, mysql := range j.MySQL {
allTasks = append(allTasks, mysql.GetPreTask())
}
@ -245,7 +255,7 @@ func (j Job) AllTasks() []ExecutableTask {
}
// Post tasks
for _, mysql := range j.MySql {
for _, mysql := range j.MySQL {
allTasks = append(allTasks, mysql.GetPreTask())
}
@ -277,6 +287,7 @@ func (j Job) RunTasks() error {
JobDir: jobDir,
Logger: GetChildLogger(logger, exTask.Name()),
Restic: restic,
Env: nil,
}
if err := exTask.RunBackup(taskCfg); err != nil {
@ -285,7 +296,9 @@ func (j Job) RunTasks() error {
}
if j.Forget != nil {
restic.Forget(j.Forget)
if err := restic.Forget(j.Forget); err != nil {
return fmt.Errorf("failed forgetting and pruning job %s: %w", j.Name, err)
}
}
return nil
@ -298,6 +311,7 @@ func (j Job) NewRestic() *ResticCmd {
Env: j.Config.Env,
Passphrase: j.Config.Passphrase,
GlobalOpts: j.Config.GlobalOpts,
Cwd: "",
}
}

View File

@ -9,7 +9,7 @@ import (
)
var (
// version of restic-scheduler being run
// version of restic-scheduler being run.
version = "dev"
)

View File

@ -15,7 +15,7 @@ type CommandOptions interface {
type NoOpts struct{}
func (_ NoOpts) ToArgs() []string {
func (NoOpts) ToArgs() []string {
return []string{}
}
@ -23,7 +23,7 @@ type ResticGlobalOpts struct {
CaCertFile string `hcl:"CaCertFile,optional"`
CacheDir string `hcl:"CacheDir,optional"`
PasswordFile string `hcl:"PasswordFile,optional"`
TlsClientCertFile string `hcl:"TlsClientCertFile,optional"`
TLSClientCertFile string `hcl:"TlsClientCertFile,optional"`
LimitDownload int `hcl:"LimitDownload,optional"`
LimitUpload int `hcl:"LimitUpload,optional"`
VerboseLevel int `hcl:"VerboseLevel,optional"`
@ -32,6 +32,7 @@ type ResticGlobalOpts struct {
NoLock bool `hcl:"NoLock,optional"`
}
// nolint:cyclop
func (glo ResticGlobalOpts) ToArgs() (args []string) {
if glo.CaCertFile != "" {
args = append(args, "--cacert", glo.CaCertFile)
@ -65,8 +66,8 @@ func (glo ResticGlobalOpts) ToArgs() (args []string) {
args = append(args, "--password-file", glo.PasswordFile)
}
if glo.TlsClientCertFile != "" {
args = append(args, "--tls-client-cert", glo.TlsClientCertFile)
if glo.TLSClientCertFile != "" {
args = append(args, "--tls-client-cert", glo.TLSClientCertFile)
}
if glo.VerboseLevel > 0 {
@ -120,9 +121,11 @@ func (rcmd ResticCmd) RunRestic(command string, options CommandOptions, commandA
cmd.Env = rcmd.BuildEnv()
cmd.Dir = rcmd.Cwd
err := cmd.Run()
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running restic: %w", err)
}
return err
return nil
}
type BackupOpts struct {
@ -146,7 +149,7 @@ func (bo BackupOpts) ToArgs() (args []string) {
func (rcmd ResticCmd) Backup(files []string, options *BackupOpts) error {
if options == nil {
options = &BackupOpts{}
options = &BackupOpts{} // nolint:exhaustivestruct
}
err := rcmd.RunRestic("backup", options, files...)
@ -198,7 +201,7 @@ func (ro RestoreOpts) ToArgs() (args []string) {
func (rcmd ResticCmd) Restore(snapshot string, opts *RestoreOpts) error {
if opts == nil {
opts = &RestoreOpts{}
opts = &RestoreOpts{} // nolint:exhaustivestruct
}
err := rcmd.RunRestic("restore", opts, snapshot)
@ -227,6 +230,7 @@ type ForgetOpts struct {
Prune bool `hcl:"Prune,optional"`
}
// nolint:funlen,cyclop
func (fo ForgetOpts) ToArgs() (args []string) {
// Add keep-*
if fo.KeepLast > 0 {
@ -298,7 +302,7 @@ func (fo ForgetOpts) ToArgs() (args []string) {
func (rcmd ResticCmd) Forget(forgetOpts *ForgetOpts) error {
if forgetOpts == nil {
forgetOpts = &ForgetOpts{}
forgetOpts = &ForgetOpts{} // nolint:exhaustivestruct
}
err := rcmd.RunRestic("forget", forgetOpts)

View File

@ -30,25 +30,25 @@ func GetChildLogger(parent *log.Logger, name string) *log.Logger {
return GetLogger(childName)
}
type logWriter struct {
type LogWriter struct {
logger *log.Logger
}
func NewLogWriter(logger *log.Logger) *logWriter {
return &logWriter{logger}
func NewLogWriter(logger *log.Logger) *LogWriter {
return &LogWriter{logger}
}
func (w logWriter) Write(p []byte) (n int, err error) {
message := fmt.Sprintf("%s", p)
func (w LogWriter) Write(content []byte) (n int, err error) {
message := string(content)
for _, line := range strings.Split(message, "\n") {
w.logger.Printf(" %s", line)
}
return len(p), nil
return len(content), nil
}
func RunShell(script string, cwd string, env map[string]string, logger *log.Logger) error {
cmd := exec.Command("sh", "-c", strings.TrimSpace(script))
cmd := exec.Command("sh", "-c", strings.TrimSpace(script)) // nolint:gosec
// Make both stderr and stdout go to logger
// fmt.Println("LOGGER PREFIX", logger.Prefix())

View File

@ -1,6 +1,8 @@
package main
func MergeEnv(parent, child map[string]string) (result map[string]string) {
func MergeEnv(parent, child map[string]string) map[string]string {
result := map[string]string{}
for key, value := range parent {
result[key] = value
}
@ -9,5 +11,5 @@ func MergeEnv(parent, child map[string]string) (result map[string]string) {
result[key] = value
}
return
return result
}