Skip to content

Commit

Permalink
Merge pull request #39 from cego/continue-on-missing-dataset
Browse files Browse the repository at this point in the history
Continue when failed to list snapshots for a non-existing dataset
  • Loading branch information
moberghammer authored Oct 7, 2024
2 parents 31f5456 + 373edbe commit 6938805
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 66 deletions.
7 changes: 6 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ func processAll(now time.Time, conf *conf.Config, zfsExecutor zfs.Executor) ([]z
list := zfs.SnapshotList{}
list, err := list.NewSnapshotListFromDataset(zfsExecutor, dataset)
if err != nil {
return nil, err
// Write and Continue when dataset is not found
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
continue
}
list.KeepNamed(plan.Protect)
list.KeepLatest(plan.Latest)
Expand Down Expand Up @@ -114,6 +116,9 @@ func clean(cmd *cobra.Command, args []string) error {
// We can ignore errors here, we're exiting anyway.
_ = syscall.Flock(fd, syscall.LOCK_UN)
}()
if err := zfsExecutor.HasZFSCommand(); err != nil {
return err
}
lists, err := processAll(now, conf, zfsExecutor)
if err != nil {
return err
Expand Down
69 changes: 4 additions & 65 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"errors"
"github.com/cego/zfs-cleaner/zfs"
"io/ioutil"
"os"
Expand Down Expand Up @@ -115,6 +114,10 @@ type testExecutor struct {
getSnapshotListError error
}

func (t *testExecutor) HasZFSCommand() error {
return nil
}

func (t *testExecutor) GetSnapshotList(dataset string) ([]byte, error) {
return t.getSnapshotListResult, t.getSnapshotListError
}
Expand Down Expand Up @@ -175,37 +178,6 @@ playground/fs1@snap5 1492989587
}
}

func TestProcessAllFail(t *testing.T) {
zfsTestExecutor := testExecutor{
getSnapshotListError: errors.New("test fail"),
}

conf := &conf.Config{
Plans: []conf.Plan{
{
Name: "buh",
Paths: []string{"playground/fs1"},
Latest: 10,
Periods: []conf.Period{
{
Frequency: 24 * time.Hour,
Age: 30 * 24 * time.Hour,
},
},
},
},
}

lists, err := processAll(time.Now(), conf, &zfsTestExecutor)
if err == nil {
t.Errorf("processAll() did not return error")
}

if lists != nil {
t.Errorf("processAll() returned lists")
}
}

func TestMainNoArguments(t *testing.T) {
os.Args = []string{os.Args[0]}
defer func() {
Expand All @@ -228,39 +200,6 @@ func TestMainNoConfig(t *testing.T) {
main()
}

func TestMainNoZFS(t *testing.T) {
content := []byte(`
plan buh {
path /buh
keep 1d for 30d
keep latest 10
}
`)
tmpfile, err := ioutil.TempFile("/dev/shm", "test.TestReadConfSyntaxError")
if err != nil {
t.Fatalf("Failed to create config file: %s", err.Error())
}
defer os.Remove(tmpfile.Name())

_, err = tmpfile.Write(content)
if err != nil {
t.Fatalf("Failed to write config file: %s", err.Error())
}

err = tmpfile.Close()
if err != nil {
t.Fatalf("Failed to close config file: %s", err.Error())
}

os.Args = []string{os.Args[0], tmpfile.Name()}
defer func() {
if r := recover(); r == nil {
t.Errorf("The code did not panic for no arguments")
}
}()
main()
}

func TestMainFull(t *testing.T) {
now = time.Unix(1492993419, 0)
verbose = true
Expand Down
4 changes: 4 additions & 0 deletions zfs/SnapshotList_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ type testExecutor struct {
getSnapshotListError error
}

func (t *testExecutor) HasZFSCommand() error {
return nil
}

func (t *testExecutor) GetSnapshotList(dataset string) ([]byte, error) {
return t.getSnapshotListResult, t.getSnapshotListError
}
Expand Down
14 changes: 14 additions & 0 deletions zfs/ZfsExecutor.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package zfs

import (
"errors"
"fmt"
"os"
"os/exec"
"strings"
)

type Executor interface {
HasZFSCommand() error
GetSnapshotList(dataset string) ([]byte, error)
GetFilesystems() ([]byte, error)
HasSnapshot(dataset string) (bool, error)
Expand All @@ -26,6 +29,17 @@ func NewExecutor() Executor {
}
}

func (z *executorImpl) HasZFSCommand() error {
if stat, err := os.Stat(z.zfsCommandName); err == nil {
// Is executable by others
if stat.Mode()&0001 != 0 {
return errors.New("ZFS command is not executable")
}
return nil
}
return fmt.Errorf("ZFS command %s not found", z.zfsCommandName)
}

func (z *executorImpl) GetSnapshotList(dataset string) ([]byte, error) {
commandArguments := []string{"list", "-t", "snapshot", "-o", "name,creation", "-s", "creation", "-d", "1", "-H", "-p", "-r", dataset}
output, err := exec.Command(z.zfsCommandName, commandArguments...).Output()
Expand Down

0 comments on commit 6938805

Please sign in to comment.