-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
222 lines (200 loc) · 4.93 KB
/
main.go
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package main
import (
"archive/tar"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"
)
// ConfigPath : default config path
const ConfigPath = "./config/vacuums.json"
// Config contains a list of vacuums to be used.
type Config struct {
Vacuums []Vacuum
}
// Vacuum specifies destination to be cleaned
type Vacuum struct {
Path string
FilesPrefix string
FilesSufix string
RemoveLogs bool
Compressor string
OutputPath string
OutputName string
UpdateOutput bool
}
// Reads vacuums.json into ./config dir
func loadVacuums() Config {
file, e := ioutil.ReadFile(ConfigPath)
if e != nil {
fmt.Printf("It was impossible load vacuums file from %v. Error %v\n", ConfigPath, e)
os.Exit(1)
}
fmt.Printf("Found vacuum file : %v\n", ConfigPath)
var vacuums Config
json.Unmarshal(file, &vacuums)
return vacuums
}
// Checks if a path exists
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return true, err
}
// Builds a files path pattern using to path + prefix/suffix
func buildFilter(vacuum Vacuum) string {
filesFilter := ""
filesFilter += vacuum.Path
if vacuum.FilesPrefix == "" && vacuum.FilesSufix == "" {
filesFilter += "*"
} else {
if vacuum.FilesPrefix != "" {
filesFilter += vacuum.FilesPrefix
}
if vacuum.FilesSufix != "" {
filesFilter += vacuum.FilesSufix
}
}
return filesFilter
}
// Get output file name formmating with date
func generateOutputFilename(vacuum Vacuum) string {
t := time.Now()
output := vacuum.OutputPath
output += t.Format(vacuum.OutputName)
return output
}
// Creates output file
func createOutput(vacuum Vacuum) *os.File {
outputFile := generateOutputFilename(vacuum)
if outputFile == "" {
fmt.Printf("Invalid output name.\n")
return nil
}
dirExists, err := exists(outputFile)
if (!vacuum.UpdateOutput) && dirExists || err != nil {
fmt.Printf("Output file found at %v but Logs Vacuum isn't allowed to update it.\n", outputFile)
return nil
}
file, err := os.Create(outputFile)
if err != nil {
log.Fatalln(err)
}
return file
}
// Adding a file into a tarball
func addFile(tw *tar.Writer, path string) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
if stat, err := file.Stat(); err == nil {
// now lets create the header as needed for this file within the tarball
header := new(tar.Header)
header.Name = path
header.Size = stat.Size()
header.Mode = int64(stat.Mode())
header.ModTime = stat.ModTime()
// write the header to the tarball archive
if err := tw.WriteHeader(header); err != nil {
return err
}
// copy the file data to the tarball
if _, err := io.Copy(tw, file); err != nil {
return err
}
}
return nil
}
// remove a file
func remove(file string) {
os.Remove(file)
}
// Compress a bunch of files found by vacuum
func compress(vacuum Vacuum, files []string) {
if vacuum.Compressor != "tar.gz" {
fmt.Printf("Error: Logs Vacuum only supports tar.gz compressor at the moment.\n")
return
}
outputFile := createOutput(vacuum)
if outputFile == nil {
fmt.Printf("It was impossible to create output file.\n")
return
}
defer outputFile.Close()
fmt.Printf("Using output file %v\n", outputFile.Name())
// setting up the gzip writer
gw := gzip.NewWriter(outputFile)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
// adding files into output
for _, file := range files {
fmt.Printf("Adding log %s to output file\n", file)
err := addFile(tw, file)
if err != nil {
fmt.Printf("It was impossible to add log file to output due to %v\n", err)
continue
}
if vacuum.RemoveLogs {
fmt.Printf("Removing file %s\n", file)
remove(file)
}
}
}
// Runs a vacuum
func run(vacuum Vacuum) {
dirExists, err := exists(vacuum.Path)
if !dirExists || err != nil {
fmt.Printf("It was impossible clean path %v: It doesn't exit or isn't readable.\n", vacuum.Path)
return
}
fmt.Printf("Running vacuum at: %v\n", vacuum.Path)
var path = buildFilter(vacuum)
files, _ := filepath.Glob(path)
if len(files) == 0 {
fmt.Printf("There isn't files found using pattern %v\n", path)
return
}
compress(vacuum, files)
}
// Validate if a vacuum has all mandatory fields
func isValid(vacuum Vacuum) bool {
if vacuum.Path == "" {
fmt.Printf("You must supply path in your vacuum configuration.\n")
return false
}
if vacuum.OutputName == "" {
fmt.Printf("You must supply outputName in your vacuum configuration.\n")
return false
}
if vacuum.OutputPath == "" {
fmt.Printf("You must supply outputPath in your vacuum configuration.\n")
return false
}
if vacuum.Compressor == "" {
fmt.Printf("You must supply compressor in your vacuum configuration.\n")
return false
}
return true
}
func main() {
fmt.Println("Running Logs Vacuum Cleaner")
vacuums := loadVacuums()
for _, vacuum := range vacuums.Vacuums {
if isValid(vacuum) {
run(vacuum)
}
}
}