Skip to content

Commit 2a59781

Browse files
author
smothiki
committed
feat(cleaner): write unit test for cleaner
1 parent 5e2baaf commit 2a59781

8 files changed

Lines changed: 89 additions & 10 deletions

File tree

boot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func main() {
7474
log.Printf("Starting deleted app cleaner")
7575
cleanerErrCh := make(chan error)
7676
go func() {
77-
if err := cleaner.Run(gitHomeDir, kubeClient.Namespaces()); err != nil {
77+
if err := cleaner.Run(gitHomeDir, kubeClient.Namespaces(), fs); err != nil {
7878
cleanerErrCh <- err
7979
}
8080
}()

pkg/cleaner/cleaner.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,38 @@ package cleaner
33

44
import (
55
"log"
6-
"os"
76

87
"k8s.io/kubernetes/pkg/api"
98

109
"github.com/deis/builder/pkg/k8s"
10+
"github.com/deis/builder/pkg/sys"
1111
)
1212

1313
const (
1414
dotGitSuffix = ".git"
1515
)
1616

17-
// Run starts the deleted app cleaner. Every pollSleepDuration, it compares the result of nsLister.List with the directories in the top level of gitHome on the local file system. On any error, it uses log messages to output a human readable description of what happened.
18-
func Run(gitHome string, nsLister k8s.NamespaceWatcher) error {
19-
17+
// Run starts the deleted app cleaner. This function listens to the Kubernetes event stream for events that indicate namespaces that were `DELETED`.
18+
// If the namespace name matches a folder on the local filesystem, this func deletes that folder.
19+
// Note that this function blocks until the watcher returned by `nsLister.Watch` is closed, so you should launch it in a goroutine.
20+
func Run(gitHome string, nsLister k8s.NamespaceWatcher, fs sys.FS) error {
2021
watcher, err := nsLister.Watch(nil, nil, "")
2122
if err != nil {
2223
log.Printf("unable to get watch events (%s)", err)
2324
}
2425
for {
2526
event := <-watcher.ResultChan()
2627
if event.Type == "DELETED" {
27-
namespace := event.Object.(*api.Namespace)
28-
appToDelete := gitHome + "/" + namespace.ObjectMeta.Name + dotGitSuffix
29-
if err := os.RemoveAll(appToDelete); err != nil {
30-
log.Printf("Cleaner error removing deleted app %s (%s)", appToDelete, err)
28+
switch event.Object.(type) {
29+
case (*api.Namespace):
30+
namespace := event.Object.(*api.Namespace)
31+
appToDelete := gitHome + "/" + namespace.ObjectMeta.Name + dotGitSuffix
32+
if err := fs.RemoveAll(appToDelete); err != nil {
33+
log.Printf("Cleaner error removing deleted app %s (%s)", appToDelete, err)
34+
}
35+
default:
3136
}
3237
}
33-
3438
}
3539

3640
}

pkg/cleaner/cleaner_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package cleaner
2+
3+
import (
4+
"testing"
5+
6+
"time"
7+
8+
"github.com/deis/builder/pkg/sys"
9+
"k8s.io/kubernetes/pkg/api"
10+
"k8s.io/kubernetes/pkg/fields"
11+
"k8s.io/kubernetes/pkg/labels"
12+
"k8s.io/kubernetes/pkg/watch"
13+
)
14+
15+
type namespace struct {
16+
}
17+
18+
// Watch returns a watch.Interface that watches the requested namespaces.
19+
func (r *namespace) Watch(label labels.Selector, field fields.Selector, resourceversion string) (watch.Interface, error) {
20+
nst := watch.NewFake()
21+
go func() {
22+
nst.Add(&api.Namespace{ObjectMeta: api.ObjectMeta{Name: "dir1"}})
23+
nst.Modify(&api.Namespace{ObjectMeta: api.ObjectMeta{Name: "dir1"}})
24+
nst.Delete(&api.Namespace{ObjectMeta: api.ObjectMeta{Name: "dir1"}})
25+
nst.Modify(&api.Namespace{ObjectMeta: api.ObjectMeta{Name: "dir2"}})
26+
nst.Delete(nil)
27+
nst.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "dir3"}})
28+
nst.Delete(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "dir3"}})
29+
nst.Stop()
30+
}()
31+
return nst, nil
32+
}
33+
34+
func (r *namespace) IsAnAPIObject() {}
35+
36+
func TestCleanerRun(t *testing.T) {
37+
ns := &namespace{}
38+
fs := sys.NewFakeFS()
39+
dirhome := "/home/git"
40+
fs.Files["/home/git/dir1.git"] = []byte{}
41+
fs.Files["/home/git/dir2.git"] = []byte{}
42+
fs.Files["/home/git/dir3.git"] = []byte{}
43+
go Run(dirhome, ns, fs)
44+
time.Sleep(5 * time.Second)
45+
// Namespace with name dir1 got deleted directory should be deleted
46+
_, ok := fs.Files["/home/git/dir1.git"]
47+
if ok {
48+
t.Fatal("Test failed: Deleting a namespace should delete respective direcotry")
49+
}
50+
// Namespace with name dir2 got modified directory should not be deleted
51+
_, ok = fs.Files["/home/git/dir2.git"]
52+
if !ok {
53+
t.Fatal("Test failed: Modyfiying a namespace should not delete respective direcotry")
54+
}
55+
// Pod with name dir3 got deleted directory should not be deleted
56+
_, ok = fs.Files["/home/git/dir3.git"]
57+
if !ok {
58+
t.Fatal("Test failed: Deleting a pod should not delete respective direcotry")
59+
}
60+
}

pkg/sys/fs.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package sys
33
import (
44
"fmt"
55
"io/ioutil"
6+
"os"
67
)
78

89
// FS is the interface to a file system
910
type FS interface {
1011
// ReadAll gets the contents of filename, or an error if the file didn't exist or there was an error reading it
1112
ReadFile(filename string) ([]byte, error)
13+
RemoveAll(name string) error
1214
}
1315

1416
// RealFS returns an FS object that interacts with the real local filesystem
@@ -22,6 +24,10 @@ func (r *realFS) ReadFile(name string) ([]byte, error) {
2224
return ioutil.ReadFile(name)
2325
}
2426

27+
func (r *realFS) RemoveAll(name string) error {
28+
return os.RemoveAll(name)
29+
}
30+
2531
// FakeFileNotFound is the error returned by FakeFS when a requested file isn't found
2632
type FakeFileNotFound struct {
2733
Filename string
@@ -47,3 +53,12 @@ func (f *FakeFS) ReadFile(name string) ([]byte, error) {
4753
}
4854
return b, nil
4955
}
56+
57+
func (f *FakeFS) RemoveAll(name string) error {
58+
_, ok := f.Files[name]
59+
if !ok {
60+
return FakeFileNotFound{Filename: name}
61+
}
62+
delete(f.Files, name)
63+
return nil
64+
}

testdata/dir1/.gitkeep

Whitespace-only changes.

testdata/dir2/.gitkeep

Whitespace-only changes.

testdata/dir3/.gitkeep

Whitespace-only changes.

testdata/dir4/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)