-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathcrontab.go
118 lines (101 loc) · 2.08 KB
/
crontab.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
package cronv
import (
"context"
"fmt"
"strings"
"github.com/pkg/errors"
)
type Schedule struct {
Minute string
Hour string
DayOfMonth string
Month string
DayOfWeek string
Year string
Alias string
}
func (s *Schedule) toCrontab() string {
if s.Alias != "" {
return s.Alias
}
dest := strings.Join([]string{s.Minute, s.Hour, s.DayOfMonth, s.Month, s.DayOfWeek, s.Year}, " ")
return strings.Trim(dest, " ")
}
type Extra struct {
Line string
Label string
Job string
}
type Crontab struct {
Line string
Schedule *Schedule
Job string
}
func (c *Crontab) isRunningEveryMinutes() bool {
for i, v := range strings.Split(c.Schedule.toCrontab(), " ") {
if v != "*" && (i > 0 || v != "*/1") {
return false
}
}
return true
}
type InvalidTaskError struct {
Line string
}
func (e *InvalidTaskError) Error() string {
return fmt.Sprintf("invalid task: '%s'", e.Line)
}
func parse(ctx context.Context, line string) (*Crontab, *Extra, error) {
// TODO use regrex to parse: https://gist.github.com/istvanp/310203
parts := strings.Fields(line)
schedule := &Schedule{}
job := []string{}
if strings.HasPrefix(parts[0], "@") {
if len(parts) < 2 {
return nil, nil, &InvalidTaskError{line}
}
// @reboot /something/to/do
if parts[0] == "@reboot" {
extra := &Extra{
Line: line,
Label: parts[0],
Job: strings.Join(parts[1:], " "),
}
return nil, extra, nil
}
schedule.Alias = parts[0]
job = parts[1:]
} else {
if len(parts) < 5 {
return nil, nil, errors.WithStack(&InvalidTaskError{line})
}
// https://en.wikipedia.org/wiki/Cron#Predefined_scheduling_definitions
c := 0
for _, v := range parts {
if len(v) == 0 {
continue
}
switch c {
case 0:
schedule.Minute = v
case 1:
schedule.Hour = v
case 2:
schedule.DayOfMonth = v
case 3:
schedule.Month = v
case 4:
schedule.DayOfWeek = v
default:
job = append(job, v)
}
c++
}
}
crontab := &Crontab{
Line: line,
Schedule: schedule,
Job: strings.Join(job, " "),
}
return crontab, nil, nil
}