Add ability to unlock repos that may have stale locks
Defaults to remove all locks, even non-stale
This commit is contained in:
parent
cddc290ee0
commit
a0db27be1a
32
main.go
32
main.go
@ -189,10 +189,32 @@ func runRestoreJobs(jobs []Job, names string, snapshot string) error {
|
|||||||
return filterJobErr
|
return filterJobErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runUnlockJobs(jobs []Job, names string) error {
|
||||||
|
if names == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
namesSlice := strings.Split(names, ",")
|
||||||
|
|
||||||
|
if len(namesSlice) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs, filterJobErr := FilterJobs(jobs, namesSlice)
|
||||||
|
for _, job := range jobs {
|
||||||
|
if err := job.NewRestic().Unlock(UnlockOpts{RemoveAll: true}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterJobErr
|
||||||
|
}
|
||||||
|
|
||||||
type Flags struct {
|
type Flags struct {
|
||||||
showVersion bool
|
showVersion bool
|
||||||
backup string
|
backup string
|
||||||
restore string
|
restore string
|
||||||
|
unlock string
|
||||||
restoreSnapshot string
|
restoreSnapshot string
|
||||||
once bool
|
once bool
|
||||||
healthCheckAddr string
|
healthCheckAddr string
|
||||||
@ -204,6 +226,7 @@ func readFlags() Flags {
|
|||||||
flag.BoolVar(&flags.showVersion, "version", false, "Display the version and exit")
|
flag.BoolVar(&flags.showVersion, "version", false, "Display the version and exit")
|
||||||
flag.StringVar(&flags.backup, "backup", "", "Run backup jobs now. Names are comma separated. `all` will run all.")
|
flag.StringVar(&flags.backup, "backup", "", "Run backup jobs now. Names are comma separated. `all` will run all.")
|
||||||
flag.StringVar(&flags.restore, "restore", "", "Run restore jobs now. Names are comma separated. `all` will run all.")
|
flag.StringVar(&flags.restore, "restore", "", "Run restore jobs now. Names are comma separated. `all` will run all.")
|
||||||
|
flag.StringVar(&flags.unlock, "unlock", "", "Unlock job repos now. Names are comma separated. `all` will run all.")
|
||||||
flag.BoolVar(&flags.once, "once", false, "Run jobs specified using -backup and -restore once and exit")
|
flag.BoolVar(&flags.once, "once", false, "Run jobs specified using -backup and -restore once and exit")
|
||||||
flag.StringVar(&flags.healthCheckAddr, "addr", "0.0.0.0:8080", "address to bind health check API")
|
flag.StringVar(&flags.healthCheckAddr, "addr", "0.0.0.0:8080", "address to bind health check API")
|
||||||
flag.StringVar(&flags.metricsPushGateway, "push-gateway", "", "url of push gateway service for batch runs (optional)")
|
flag.StringVar(&flags.metricsPushGateway, "push-gateway", "", "url of push gateway service for batch runs (optional)")
|
||||||
@ -214,7 +237,12 @@ func readFlags() Flags {
|
|||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSpecifiedJobs(jobs []Job, backupJobs, restoreJobs, snapshot string) error {
|
func runSpecifiedJobs(jobs []Job, backupJobs, restoreJobs, unlockJobs, snapshot string) error {
|
||||||
|
// Run specified job unlocks
|
||||||
|
if err := runUnlockJobs(jobs, unlockJobs); err != nil {
|
||||||
|
return fmt.Errorf("Failed running unlock for jobs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Run specified backup jobs
|
// Run specified backup jobs
|
||||||
if err := runBackupJobs(jobs, backupJobs); err != nil {
|
if err := runBackupJobs(jobs, backupJobs); err != nil {
|
||||||
return fmt.Errorf("Failed running backup jobs: %w", err)
|
return fmt.Errorf("Failed running backup jobs: %w", err)
|
||||||
@ -261,7 +289,7 @@ func main() {
|
|||||||
log.Fatalf("Failed to read jobs from files: %v", err)
|
log.Fatalf("Failed to read jobs from files: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runSpecifiedJobs(jobs, flags.backup, flags.restore, flags.restoreSnapshot); err != nil {
|
if err := runSpecifiedJobs(jobs, flags.backup, flags.restore, flags.unlock, flags.restoreSnapshot); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
restic.go
16
restic.go
@ -72,6 +72,16 @@ func (NoOpts) ToArgs() []string {
|
|||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UnlockOpts struct {
|
||||||
|
RemoveAll bool `hcl:"RemoveAll,optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uo UnlockOpts) ToArgs() (args []string) {
|
||||||
|
args = maybeAddArgBool(args, "--remove-all", uo.RemoveAll)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type BackupOpts struct {
|
type BackupOpts struct {
|
||||||
Exclude []string `hcl:"Exclude,optional"`
|
Exclude []string `hcl:"Exclude,optional"`
|
||||||
Include []string `hcl:"Include,optional"`
|
Include []string `hcl:"Include,optional"`
|
||||||
@ -333,6 +343,12 @@ func (rcmd Restic) Check() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rcmd Restic) Unlock(unlockOpts UnlockOpts) error {
|
||||||
|
_, err := rcmd.RunRestic("unlock", unlockOpts)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
type Snapshot struct {
|
type Snapshot struct {
|
||||||
UID int `json:"uid"`
|
UID int `json:"uid"`
|
||||||
GID int `json:"gid"`
|
GID int `json:"gid"`
|
||||||
|
@ -152,6 +152,20 @@ func TestForgetOpts(t *testing.T) {
|
|||||||
AssertEqual(t, "args didn't match", expected, args)
|
AssertEqual(t, "args didn't match", expected, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnlockOpts(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
args := main.UnlockOpts{
|
||||||
|
RemoveAll: true,
|
||||||
|
}.ToArgs()
|
||||||
|
|
||||||
|
expected := []string{
|
||||||
|
"--remove-all",
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertEqual(t, "args didn't match", expected, args)
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuildEnv(t *testing.T) {
|
func TestBuildEnv(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -299,4 +313,8 @@ func TestResticInterface(t *testing.T) {
|
|||||||
value, err = os.ReadFile(restoredDataFile)
|
value, err = os.ReadFile(restoredDataFile)
|
||||||
AssertEqualFail(t, "unexpected error reading from test file", nil, err)
|
AssertEqualFail(t, "unexpected error reading from test file", nil, err)
|
||||||
AssertEqualFail(t, "incorrect value in test file", "testing", string(value))
|
AssertEqualFail(t, "incorrect value in test file", "testing", string(value))
|
||||||
|
|
||||||
|
// Try to unlock the repo (repo shouldn't really be locked, but this should still run without error
|
||||||
|
err = restic.Unlock(main.UnlockOpts{}) //nolint:exhaustruct
|
||||||
|
AssertEqualFail(t, "unexpected error unlocking repo", nil, err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user