Skip to content

Commit b5cc7f8

Browse files
author
smothiki
committed
feat(lock): change cleaner code to listen to k8s namespace events
1 parent 1d926fa commit b5cc7f8

7 files changed

Lines changed: 50 additions & 307 deletions

File tree

boot.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ func main() {
4949
os.Exit(1)
5050
}
5151
pushLock := sshd.NewInMemoryRepositoryLock()
52-
cleanerRef := cleaner.NewRef()
5352
circ := sshd.NewCircuit()
5453

5554
s3Client, err := storage.GetClient(cnf.HealthSrvTestStorageRegion)
@@ -72,15 +71,15 @@ func main() {
7271
log.Printf("Starting deleted app cleaner")
7372
cleanerErrCh := make(chan error)
7473
go func() {
75-
if err := cleanerRef.Run(gitHomeDir, kubeClient.Namespaces(), cnf.CleanerPollSleepDuration()); err != nil {
74+
if err := cleaner.Run(gitHomeDir, kubeClient.Namespaces()); err != nil {
7675
cleanerErrCh <- err
7776
}
7877
}()
7978

8079
log.Printf("Starting SSH server on %s:%d", cnf.SSHHostIP, cnf.SSHHostPort)
8180
sshCh := make(chan int)
8281
go func() {
83-
sshCh <- pkg.RunBuilder(cnf.SSHHostIP, cnf.SSHHostPort, gitHomeDir, circ, pushLock, cleanerRef)
82+
sshCh <- pkg.RunBuilder(cnf.SSHHostIP, cnf.SSHHostPort, gitHomeDir, circ, pushLock)
8483
}()
8584

8685
select {

pkg/builder.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"github.com/Masterminds/cookoo"
1212
clog "github.com/Masterminds/cookoo/log"
13-
"github.com/deis/builder/pkg/cleaner"
1413
"github.com/deis/builder/pkg/sshd"
1514
)
1615

@@ -28,7 +27,7 @@ const (
2827
// Git.
2928
//
3029
// Run returns on of the Status* status code constants.
31-
func RunBuilder(sshHostIP string, sshHostPort int, gitHomeDir string, sshServerCircuit *sshd.Circuit, pushLock sshd.RepositoryLock, cleanerRef cleaner.Ref) int {
30+
func RunBuilder(sshHostIP string, sshHostPort int, gitHomeDir string, sshServerCircuit *sshd.Circuit, pushLock sshd.RepositoryLock) int {
3231
reg, router, ocxt := cookoo.Cookoo()
3332
log.SetFlags(0) // Time is captured elsewhere.
3433

@@ -59,7 +58,7 @@ func RunBuilder(sshHostIP string, sshHostPort int, gitHomeDir string, sshServerC
5958
// Start the SSH service.
6059
// TODO: We could refactor Serve to be a command, and then run this as
6160
// a route.
62-
if err := sshd.Serve(reg, router, sshServerCircuit, gitHomeDir, pushLock, cleanerRef, cxt); err != nil {
61+
if err := sshd.Serve(reg, router, sshServerCircuit, gitHomeDir, pushLock, cxt); err != nil {
6362
clog.Errf(cxt, "SSH server failed: %s", err)
6463
return StatusLocalError
6564
}

pkg/cleaner/cleaner.go

Lines changed: 13 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2,131 +2,35 @@
22
package cleaner
33

44
import (
5-
"io/ioutil"
65
"log"
76
"os"
8-
"path/filepath"
9-
"strings"
10-
"sync"
11-
"time"
127

13-
"github.com/deis/builder/pkg/k8s"
148
"k8s.io/kubernetes/pkg/api"
15-
"k8s.io/kubernetes/pkg/fields"
16-
"k8s.io/kubernetes/pkg/labels"
9+
10+
"github.com/deis/builder/pkg/k8s"
1711
)
1812

1913
const (
2014
dotGitSuffix = ".git"
2115
)
2216

23-
type Ref struct {
24-
mut *sync.Mutex
25-
}
26-
27-
func NewRef() Ref {
28-
return Ref{mut: new(sync.Mutex)}
29-
}
30-
31-
func (c Ref) Lock() {
32-
c.mut.Lock()
33-
}
34-
35-
func (c Ref) Unlock() {
36-
c.mut.Unlock()
37-
}
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 {
3819

39-
// localDirs returns all of the local directories immediately under gitHome that filter returns true for. filter will receive only the names of each of the top level directories (not their fully qualified paths), and should return true if it should be included in the output
40-
func localDirs(gitHome string, filter func(string) bool) ([]string, error) {
41-
fileInfos, err := ioutil.ReadDir(gitHome)
20+
watcher, err := nsLister.Watch(nil, nil, "")
4221
if err != nil {
43-
return nil, err
44-
}
45-
var ret []string
46-
for _, fileInfo := range fileInfos {
47-
nm := fileInfo.Name()
48-
if len(nm) <= 0 || nm == "." || !fileInfo.IsDir() {
49-
continue
50-
}
51-
if filter(nm) {
52-
ret = append(ret, filepath.Join(gitHome, nm))
53-
}
54-
}
55-
return ret, nil
56-
}
57-
58-
// getDiff gets the directories that are not in namespaceList
59-
func getDiff(namespaceList []api.Namespace, dirs []string) []string {
60-
var ret []string
61-
62-
// create a set of lowercase namespace names
63-
namespacesSet := make(map[string]struct{})
64-
for _, ns := range namespaceList {
65-
lowerName := strings.ToLower(ns.Name)
66-
namespacesSet[lowerName] = struct{}{}
22+
log.Printf("unable to get watch events (%s)", err)
6723
}
68-
69-
// get dirs not in the namespaces set
70-
for _, dir := range dirs {
71-
lowerName := strings.ToLower(dir)
72-
if _, ok := namespacesSet[lowerName]; !ok {
73-
ret = append(ret, lowerName)
74-
}
75-
}
76-
77-
return ret
78-
}
79-
80-
func stripSuffixes(strs []string, suffix string) []string {
81-
ret := make([]string, len(strs))
82-
for i, str := range strs {
83-
idx := strings.LastIndex(str, suffix)
84-
if idx >= 0 {
85-
ret[i] = str[:idx]
86-
} else {
87-
ret[i] = str
88-
}
89-
}
90-
return ret
91-
}
92-
93-
func dirHasGitSuffix(dir string) bool {
94-
return strings.HasSuffix(dir, dotGitSuffix)
95-
}
96-
97-
// 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.
98-
func (c Ref) Run(gitHome string, nsLister k8s.NamespaceLister, pollSleepDuration time.Duration) error {
9924
for {
100-
nsList, err := nsLister.List(labels.Everything(), fields.Everything())
101-
if err != nil {
102-
log.Printf("Cleaner error listing namespaces (%s)", err)
103-
continue
104-
} else {
105-
lst := make([]string, len(nsList.Items))
106-
for i, ns := range nsList.Items {
107-
lst[i] = strings.ToLower(ns.Name)
25+
event := <-watcher.ResultChan()
26+
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)
10831
}
10932
}
11033

111-
gitDirs, err := localDirs(gitHome, dirHasGitSuffix)
112-
if err != nil {
113-
log.Printf("Cleaner error listing local git directories (%s)", err)
114-
continue
115-
}
116-
117-
gitDirs = stripSuffixes(gitDirs, dotGitSuffix)
118-
119-
appsToDelete := getDiff(nsList.Items, gitDirs)
120-
121-
for _, appToDelete := range appsToDelete {
122-
dirToDelete := appToDelete + dotGitSuffix
123-
c.Lock()
124-
if err := os.RemoveAll(dirToDelete); err != nil {
125-
log.Printf("Cleaner error removing deleted app %s (%s)", dirToDelete, err)
126-
}
127-
c.Unlock()
128-
}
129-
130-
time.Sleep(pollSleepDuration)
13134
}
35+
13236
}

pkg/cleaner/cleaner_test.go

Lines changed: 0 additions & 80 deletions
This file was deleted.

pkg/k8s/namespace.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"k8s.io/kubernetes/pkg/api"
55
"k8s.io/kubernetes/pkg/fields"
66
"k8s.io/kubernetes/pkg/labels"
7+
"k8s.io/kubernetes/pkg/watch"
78
)
89

910
// NamespaceLister is a (k8s.io/kubernetes/pkg/client/unversioned).NamespaceInterface compatible interface which only has the List function. It's used in places that only need List to make them easier to test and more easily swappable with other implementations.
@@ -14,4 +15,10 @@ import (
1415
// nsl = kubeClient.Namespaces()
1516
type NamespaceLister interface {
1617
List(labels.Selector, fields.Selector) (*api.NamespaceList, error)
18+
19+
}
20+
21+
22+
type NamespaceWatcher interface{
23+
Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
1724
}

0 commit comments

Comments
 (0)