-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcleaner.go
More file actions
123 lines (108 loc) · 3.54 KB
/
cleaner.go
File metadata and controls
123 lines (108 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Package cleaner is a background process that compares the kubernetes namespace list with the folders in the local git home directory, deleting what's not in the namespace list
package cleaner
import (
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/deis/builder/pkg/k8s"
"github.com/deis/builder/pkg/sshd"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
)
const (
dotGitSuffix = ".git"
)
func localDirs(gitHome string) ([]string, error) {
fileInfos, err := ioutil.ReadDir(gitHome)
if err != nil {
return nil, err
}
var ret []string
for _, fileInfo := range fileInfos {
nm := fileInfo.Name()
if len(nm) <= 0 || nm == "." || !fileInfo.IsDir() {
continue
}
ret = append(ret, filepath.Join(gitHome, nm))
}
return ret, nil
}
// getDiff gets the directories that are not in namespaceList
func getDiff(namespaceList []api.Namespace, dirs []string) []string {
var ret []string
// create a set of lowercase namespace names
namespacesSet := make(map[string]struct{})
for _, ns := range namespaceList {
lowerName := strings.ToLower(ns.Name)
namespacesSet[lowerName] = struct{}{}
}
// get dirs not in the namespaces set
for _, dir := range dirs {
lowerName := strings.ToLower(dir)
if _, ok := namespacesSet[lowerName]; !ok {
ret = append(ret, lowerName)
}
}
return ret
}
func stripSuffixes(strs []string, suffix string) []string {
ret := make([]string, len(strs))
for i, str := range strs {
idx := strings.LastIndex(str, suffix)
if idx >= 0 {
ret[i] = str[:idx]
}
}
return ret
}
// 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.
func Run(gitHome string, nsLister k8s.NamespaceLister, repoLock sshd.RepositoryLock, pollSleepDuration time.Duration) error {
for {
nsList, err := nsLister.List(labels.Everything(), fields.Everything())
if err != nil {
log.Printf("Cleaner error listing namespaces (%s)", err)
continue
} else {
lst := make([]string, len(nsList.Items))
for i, ns := range nsList.Items {
lst[i] = strings.ToLower(ns.Name)
}
log.Printf("Cleaner found namespaces %s", lst)
}
gitDirs, err := localDirs(gitHome)
if err != nil {
log.Printf("Cleaner error listing local git directories (%s)", err)
continue
} else {
log.Printf("Cleaner found local git directories in %s: %s", gitHome, gitDirs)
}
gitDirs = stripSuffixes(gitDirs, dotGitSuffix)
appsToDelete := getDiff(nsList.Items, gitDirs)
if len(appsToDelete) > 0 {
log.Printf("Cleaner found the following %d apps to delete: %v", len(appsToDelete), appsToDelete)
} else {
log.Printf("Cleaner found no apps to delete")
}
for _, appToDelete := range appsToDelete {
if err := repoLock.Lock(appToDelete, time.Duration(0)); err != nil {
log.Printf("Cleaner error locking repository %s for deletion (%s)", appToDelete, err)
continue
}
dirToDelete := appToDelete + dotGitSuffix
log.Printf("Cleaner deleting %s", dirToDelete)
if err := os.RemoveAll(dirToDelete); err != nil {
log.Printf("Cleaner error removing deleted app %s (%s)", dirToDelete, err)
}
log.Printf("Cleaner deleted %s", dirToDelete)
if err := repoLock.Unlock(appToDelete, time.Duration(0)); err != nil {
log.Printf("Cleaner error unlocking repository %s for deletion (%s)", appToDelete, err)
continue
}
}
time.Sleep(pollSleepDuration)
}
}