dust-deploy 0.13.3 → 0.13.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,16 @@
1
1
  Changelog
2
2
  =============
3
3
 
4
+ 0.13.4
5
+ ------------
6
+
7
+ - adds cron recipe that maintains cronjobs
8
+
9
+ recipes:
10
+ cron:
11
+ mycronjob_name: { minute: '*/1', command: 'my command' }
12
+
13
+
4
14
  0.13.3
5
15
  ------------
6
16
 
@@ -74,6 +74,11 @@ class String
74
74
  rescue NameError
75
75
  false
76
76
  end
77
+
78
+ # checks if string is a valid integer
79
+ def is_int?
80
+ true if Integer(self) rescue false
81
+ end
77
82
  end
78
83
 
79
84
 
@@ -0,0 +1,161 @@
1
+ class Cron < Recipe
2
+
3
+ desc 'cron:deploy', 'maintains cronjobs'
4
+ def deploy
5
+ # check config
6
+ # install cron
7
+ # enable name: remove to remove a job
8
+
9
+ unless @node.dir_exists? '/etc/cron.d'
10
+ return @node.messages.add('your system does not support /etc/cron.d').failed
11
+ end
12
+
13
+ @config.each do |name, job|
14
+ # remove job if requested
15
+ if job == 'remove'
16
+ remove(name)
17
+ next
18
+ end
19
+
20
+ @node.messages.add("processing cronjob '#{name}'\n")
21
+
22
+ # apply default settings, unless set
23
+ job = default_job.merge job
24
+
25
+ parse_cronjob(job)
26
+ next unless check_cronjob(job)
27
+ cronjob = generate_cronjob(job)
28
+
29
+ # deploy rule file
30
+ msg = @node.messages.add('deploying', :indent => 2)
31
+ msg.parse_result(@node.write("/etc/cron.d/#{name}", cronjob, :quiet => true))
32
+ end
33
+ end
34
+
35
+
36
+ private
37
+
38
+ # removes all files in /etc/cron.d/
39
+ def remove(name)
40
+ msg = @node.messages.add("removing cronjob #{name}")
41
+ msg.parse_result(@node.rm("/etc/cron.d/#{name}", :quiet => true))
42
+ end
43
+
44
+ # default settings for a cronjob
45
+ def default_job
46
+ { 'minute' => '*', 'hour' => '*', 'monthday' => '*',
47
+ 'month' => '*', 'weekday' => '*', 'user' => 'root' }
48
+ end
49
+
50
+ def generate_cronjob(job)
51
+ "#{job['minute']} #{job['hour']} #{job['monthday']} " +
52
+ "#{job['month']} #{job['weekday']} #{job['user']} " +
53
+ "#{job['command']}\n"
54
+ end
55
+
56
+ # translate month and day names to numbers
57
+ def parse_cronjob(job)
58
+
59
+ # valid months and days
60
+ months = { 'january' => 1, 'jan' => 1,
61
+ 'february' => 2, 'feb' => 2,
62
+ 'march' => 3, 'mar' => 3,
63
+ 'april' => 4, 'apr' => 4,
64
+ 'may' => 5,
65
+ 'june' => 6, 'jun' => 6,
66
+ 'july' => 7, 'jul' => 7,
67
+ 'august' => 8, 'aug' => 8,
68
+ 'september' => 9, 'sep' => 9,
69
+ 'october' => 10, 'oct' => 10,
70
+ 'november' => 11, 'nov' => 11,
71
+ 'december' => 12, 'dec' => 12 }
72
+
73
+ days = { 'sunday' => 0, 'sun' => 0,
74
+ 'monday' => 1, 'mon' => 1,
75
+ 'tuesday' => 2, 'tue' => 2,
76
+ 'wednesday' => 3, 'wed' => 3,
77
+ 'thursday' => 4, 'thu' => 4,
78
+ 'friday' => 5, 'fri' => 5,
79
+ 'saturday' => 6, 'sat' => 6 }
80
+
81
+ # only process, if month is a string
82
+ if job['month'].is_a? String and not job['month'] == '*'
83
+ m = []
84
+
85
+ # multiple month are allowed, splitting using ','
86
+ job['month'].split(',').each do |i|
87
+
88
+ # if month is an int, add it to list and continue
89
+ if i.is_int?
90
+ d << i.to_i
91
+ next
92
+ end
93
+
94
+ # find month number in hash, add it to list
95
+ if months[i.downcase]
96
+ m << months[i.downcase]
97
+
98
+ # if month is not found, add -1 (will throw error on check_cronjob later)
99
+ else
100
+ m << -1
101
+ end
102
+
103
+ end
104
+
105
+ # join the numbers pack together
106
+ job['month'] = m.join(',')
107
+ end
108
+
109
+ # do the same with weekdays
110
+ if job['weekday'].is_a? String and not job['weekday'] == '*'
111
+ d = []
112
+ job['weekday'].split(',').each do |i|
113
+ if i.is_int?
114
+ d << i.to_i
115
+ next
116
+ end
117
+
118
+ if days[i.downcase]
119
+ d << days[i.downcase]
120
+ else
121
+ d << -1
122
+ end
123
+ end
124
+ job['weekday'] = d.join(',')
125
+ end
126
+
127
+ end
128
+
129
+ # check if cronjob is valid
130
+ def check_cronjob(job)
131
+ msg = @node.messages.add('validating', :indent => 2)
132
+
133
+ return msg.failed(': no command given') unless job['command'].is_a? String
134
+ return msg.failed(': invalid user') unless job['user'].is_a? String
135
+ return msg.failed(': minute field invalid') unless check_period(job['minute'], 0, 59)
136
+ return msg.failed(': hour field invalid') unless check_period(job['hour'], 0, 23)
137
+ return msg.failed(': monthday field invalid') unless check_period(job['monthday'], 1, 31)
138
+ return msg.failed(': month field invalid') unless check_period(job['month'], 1, 12)
139
+ return msg.failed(': weekday field invalid') unless check_period(job['weekday'], 0, 6)
140
+
141
+ msg.ok
142
+ end
143
+
144
+ # check if a cronjob time period is valid
145
+ def check_period(period, from, to)
146
+ # if period is an int, directly check if it's between from and to
147
+ return period.to_i.between?(from, to) if period.is_a? Fixnum
148
+
149
+ # cron supports multiple periods
150
+ # and e.g */5 for e.g. every 5 minutes/hours
151
+ period.split(/[\/,]/).each do |p|
152
+ next if p.is_int? and p.to_i.between?(from, to)
153
+ next if p == '*'
154
+
155
+ # if none of the criteria matches, this period is invalid.
156
+ return false
157
+ end
158
+
159
+ true
160
+ end
161
+ end
@@ -76,7 +76,7 @@ module Dust
76
76
  # the use of > < && || | and ; doesn't screw things up
77
77
  if @node['sudo']
78
78
  channel.request_pty
79
- command = "sudo sh -c \"#{command.gsub('"','\\"')}\""
79
+ command = "sudo -k -- sh -c \"#{command.gsub('"','\\"')}\""
80
80
  end
81
81
 
82
82
  channel.exec command do |ch, success|
@@ -1,3 +1,3 @@
1
1
  module Dust
2
- VERSION = "0.13.3"
2
+ VERSION = "0.13.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dust-deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.3
4
+ version: 0.13.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-29 00:00:00.000000000 Z
12
+ date: 2012-05-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -170,6 +170,7 @@ files:
170
170
  - lib/dust/recipes/aliases.rb
171
171
  - lib/dust/recipes/apt.rb
172
172
  - lib/dust/recipes/cjdroute.rb
173
+ - lib/dust/recipes/cron.rb
173
174
  - lib/dust/recipes/cups_client.rb
174
175
  - lib/dust/recipes/debsecan.rb
175
176
  - lib/dust/recipes/dnsmasq.rb