gaddygaddy 0.1.78

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.
data/lib/interval.rb ADDED
@@ -0,0 +1,280 @@
1
+ APPLICATION_NAME = "interval"
2
+
3
+ require 'optparse'
4
+ require 'json'
5
+ require 'logging/logging'
6
+ require 'systemu'
7
+ require 'uri'
8
+
9
+ SENSU_HOST = "127.0.0.1"
10
+
11
+ class Interval
12
+ include Logging
13
+
14
+ ##################################################################
15
+ # Read and parse command line options
16
+ #
17
+ def read_options(argv)
18
+ @options = {}
19
+ optparse = OptionParser.new do|opts|
20
+ opts.banner = "Usage: interval [options] -p <proc_name> -c <command_to_run>"
21
+
22
+ @options[:proc_name] = nil
23
+ opts.on( '-p', '--proc_name <name>', 'Process name to use' ) do |proc_name|
24
+ @options[:proc_name] = proc_name
25
+ end
26
+
27
+ @options[:cmd] = nil
28
+ opts.on( '-c', '--cmd <path>', 'Command to run' ) do |cmd|
29
+ @options[:cmd] = cmd
30
+ end
31
+
32
+ opts.on( '-u', '--uri_cmd <path>', 'Command to run (URI-encoded)' ) do |ucmd|
33
+ @options[:cmd] = URI.unescape(ucmd)
34
+ end
35
+
36
+ @options[:config_name] = nil
37
+ opts.on( '-C', '--config_name <name>', 'Config name to use' ) do |config_name|
38
+ @options[:config_name] = config_name
39
+ end
40
+
41
+ @options[:home] = nil
42
+ opts.on( '-h', '--home <home>', 'Home directory of application' ) do |home|
43
+ @options[:home] = home
44
+ end
45
+
46
+ @options[:log_file] = nil
47
+ opts.on( '-l', '--logfile FILE', 'Write log to FILE, defaults to STDOUT' ) do |file|
48
+ @options[:log_file] = file
49
+ end
50
+
51
+ @options[:log_level] = 'info'
52
+ opts.on( '-L', '--log_level level', 'Set the log level (debug, info, warn, error, fatal)' ) do| level|
53
+ @options[:log_level] = level
54
+ end
55
+
56
+ @options[:count] = nil
57
+ opts.on( '-n', '--num <count>', 'Run the command <count> times and then exit (use for testing)' ) do |count|
58
+ @options[:count] = count.to_i
59
+ end
60
+
61
+ @options[:fail_on_error] = false
62
+ opts.on( '-f', '--fail_on_error', 'Abort if the program fails' ) do
63
+ @options[:fail_on_error] = true
64
+ end
65
+
66
+ @options[:sensu_enabled] = false
67
+ opts.on( '-z', '--sensu', 'Do report status to Sensu' ) do
68
+ @options[:sensu_enabled] = true
69
+ end
70
+
71
+ @options[:sensu_port] = 3030
72
+ opts.on( '--sensu_port <port>', Integer, 'Port to talk to sensu on' ) do |port|
73
+ @options[:sensu_port] = port
74
+ end
75
+
76
+ @options[:status_file] = nil
77
+ opts.on( '-s', '--status_file <status>', 'File to write last run status to' ) do |status|
78
+ @options[:status_file] = status
79
+ end
80
+
81
+ @options[:interval] = nil
82
+ opts.on( '-i', '--interval <interval>', 'Time between runs of program (seconds if no unit is specified)' ) do |interval|
83
+ @options[:interval] = interval
84
+ end
85
+
86
+ @options[:time_stamp] = nil
87
+ opts.on( '-t', '--time <time>', 'Run command at a specific time each day, could be comma separated. Format HHMM. Example 1430,0230 will run the command at 14:30 and 02:30 each day' ) do |time|
88
+ @options[:time_stamp] = time.split(",")
89
+ end
90
+
91
+ opts.on_tail("-h", "--help", "Show this message") do
92
+ puts opts
93
+ exit
94
+ end
95
+ end
96
+
97
+ begin
98
+ optparse.parse!(argv)
99
+ if @options[:config_name].nil?
100
+ @options[:config_name] = @options[:proc_name]
101
+ end
102
+ mandatory = [:proc_name, :cmd]
103
+ missing = mandatory.select{ |param| @options[param].nil? }
104
+ unless missing.empty?
105
+ STDERR.puts "Missing options: #{missing.join(', ')}"
106
+ STDERR.puts optparse
107
+ exit 1
108
+ end
109
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument #
110
+ STDERR.puts $!.to_s # Friendly output when parsing fails
111
+ STDERR.puts optparse #
112
+ exit 1 #
113
+ end
114
+ end
115
+
116
+ ##################################################################
117
+ # Parse a time expression
118
+ #
119
+ # The argument should be in one of the following forms
120
+ # <number> - parsed as seconds
121
+ # <number>s - parsed as seconds
122
+ # <number>m - parsed as minutes
123
+ # <number>h - parsed as hours
124
+ #
125
+ # @param s [String] String to parse
126
+ #
127
+ # return [Numeric] number of seconds time represents
128
+
129
+ def parse_time(s)
130
+ case s
131
+ when /^\d+s?$/
132
+ s.to_i
133
+ when /^\d+m$/
134
+ s.to_i * 60
135
+ when /^\d+h$/
136
+ s.to_i * 60 * 60
137
+ else
138
+ -1
139
+ end
140
+ end
141
+
142
+ ##################################################################
143
+ # Store status on disk
144
+ def store_status(exit_code)
145
+ if @options[:status_file]
146
+ File.open(@options[:status_file], 'w') do |f| f.puts("result=#{exit_code}") end
147
+ end
148
+ end
149
+
150
+ ##################################################################
151
+ # Fail, exit with an error message
152
+ def my_fail(msg)
153
+ logger.fatal msg if logger
154
+ STDERR.puts msg
155
+ send_to_sensu(1, "Error running interval for #{@options[:proc_name]}, #{msg}")
156
+ store_status 1
157
+ exit 1
158
+ end
159
+
160
+ ###################################################################
161
+ # Send message to sensu
162
+ #
163
+ def send_to_sensu(status, message)
164
+ if @options[:sensu_enabled]
165
+ report = {
166
+ :name => "interval_error_#{@options[:proc_name]}",
167
+ :output => "",
168
+ :status => status
169
+ }
170
+ if status != 0
171
+ report[:output] = "Failed to run #{@options[:proc_name]} #{message}"
172
+ end
173
+
174
+ begin
175
+ s = TCPSocket.open(SENSU_HOST, @options[:sensu_port])
176
+ s.print JSON.generate(report)
177
+ s.close
178
+ rescue Exception => e
179
+ logger.error "Failed to send report to sensu: #{e.message}"
180
+ end
181
+ end
182
+ end
183
+
184
+ def get_prop(option_name)
185
+ prop_value = nil
186
+ if @options[option_name]
187
+ prop_value = @options[option_name]
188
+ end
189
+ logger.debug "Found value #{prop_value} for #{option_name.to_s}"
190
+ prop_value
191
+ end
192
+
193
+ def run
194
+ read_options(ARGV)
195
+
196
+ # Check binary
197
+ unless File.executable?(@options[:cmd].split[0])
198
+ my_fail "Specified binary '#{@options[:cmd]}' does not exist or is not executable"
199
+ end
200
+
201
+ set_log_level @options[:log_level]
202
+ set_log_file @options[:log_file] if @options[:log_file]
203
+
204
+ if @options[:home]
205
+ Dir.chdir(@options[:home])
206
+ end
207
+
208
+ # Get properties
209
+ conf_name = @options[:config_name] ? @options[:config_name] : @options[:proc_name]
210
+
211
+ begin
212
+ interval_in = get_prop :interval
213
+ if interval_in
214
+ interval = parse_time interval_in
215
+ logger.info "Using an run interval of #{interval} seconds"
216
+ if interval < 1
217
+ my_fail "Illegal interval #{interval} given for property #{conf_name}.run.interval"
218
+ end
219
+
220
+ else
221
+ time_stamp = get_prop :time_stamp
222
+ raise "Could not found interval or time_stamp option, one of those is needed" unless time_stamp
223
+ logger.info "Will run at time stamp #{time_stamp.join(",")}"
224
+ end
225
+ rescue StandardError => e
226
+ puts e.message
227
+ my_fail "Did not find config value for #{conf_name}"
228
+ end
229
+
230
+
231
+ logger.info "Starting interval #{@options.inspect}"
232
+
233
+ store_status 0
234
+
235
+ count = 0
236
+ first = true
237
+ loop do
238
+ unless time_stamp && first
239
+ count = count+1
240
+ logger.info "Launching[#{count}]: #{@options[:cmd]}"
241
+ result, stdout, stderr = systemu @options[:cmd]
242
+ store_status result.exitstatus
243
+ if result != 0
244
+ logger.error "Failed to run #{@options[:cmd]} (exit code #{result})"
245
+ logger.error "Stdout: #{stdout.strip}" if stdout.length > 0
246
+ logger.error "Stderr: #{stderr.strip}" if stderr.length > 0
247
+ send_to_sensu(1, "Result is #{result}. Stderr is: #{stderr}, stdout is #{stdout}")
248
+ if @options[:fail_on_error]
249
+ exit result
250
+ end
251
+ else
252
+ logger.info "Command completed successfully"
253
+ logger.info "Stdout: #{stdout.strip}" if stdout.length > 0
254
+ send_to_sensu(0, "")
255
+ end
256
+ end
257
+ first = false
258
+
259
+ if @options[:count] && count >= @options[:count]
260
+ exit 0
261
+ end
262
+ if time_stamp
263
+ diff = []
264
+ time_stamp.each do |time|
265
+ current = Time.now.strftime("%H%M%S")
266
+ diff_time = ((time[0..1].to_i * 60 + time[2..3].to_i) - (current[0..1].to_i * 60 + current[2..3].to_i))*60 - current[4..5].to_i
267
+ diff_time += 24*60*60 if diff_time <= 0
268
+ diff << diff_time
269
+ end
270
+ logger.debug "sleep for #{diff.min + 1} seconds"
271
+ sleep diff.min + 1
272
+ else
273
+ logger.debug "sleep for #{interval} seconds"
274
+ sleep interval
275
+ end
276
+ end
277
+ end
278
+
279
+ end
280
+
@@ -0,0 +1,62 @@
1
+ #
2
+ # Name:
3
+ # logging.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ require 'log4r'
17
+ require 'log4r/outputter/datefileoutputter'
18
+ require 'log4r/yamlconfigurator'
19
+
20
+ module Logging
21
+ # This is the magical bit that gets mixed into your classes
22
+ @@log_conf = const_defined?(:APPLICATION_NAME) ? APPLICATION_NAME : "default"
23
+
24
+ def logger
25
+ Logging.logger
26
+ end
27
+
28
+ def set_log_level(level_str)
29
+ logger.level = (Log4r::Log4rConfig::LogLevels.index level_str.upcase) + 1
30
+ end
31
+
32
+ def set_log_file(new_filename)
33
+ format = Log4r::PatternFormatter.new(:pattern => "[%5l] %d :: %m", :date_pattern => '%y%m%d %H:%M:%S')
34
+ dir_name = File.dirname(new_filename)
35
+ file_name = File.basename(new_filename)
36
+ logger.outputters << Log4r::DateFileOutputter.new('log_file', :filename => file_name, :dirname => dir_name, :formatter => format, :date_pattern => '%Y%m%d')
37
+ end
38
+
39
+ def self.set_log_conf log_conf
40
+ @@log_conf = log_conf
41
+ end
42
+
43
+ # create a new log4r logger with config
44
+
45
+ def self.create_logger
46
+ log_cfg = Log4r::YamlConfigurator
47
+ conf_file = File.join(File.dirname(__FILE__), "..", "..", "conf","log4r.yml")
48
+ log_cfg.load_yaml_file(conf_file)
49
+
50
+ # app logger
51
+ new_logger = Log4r::Logger[@@log_conf]
52
+ raise "Missing logger config #{@@log_conf} in log config file #{conf_file}" unless new_logger
53
+ new_logger.level = Log4r::INFO
54
+ new_logger.info "Log initiated"
55
+ new_logger
56
+ end
57
+
58
+ # Global, memoized, lazy initialized instance of a logger
59
+ def self.logger
60
+ @logger ||= create_logger
61
+ end
62
+ end
@@ -0,0 +1,34 @@
1
+ #
2
+ # Name:
3
+ # hash.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ class Hash
17
+ # Return a new hash with all keys converted to symbols, as long as
18
+ # they respond to +to_sym+.
19
+ #
20
+ # { 'name' => 'Rob', 'years' => '28' }.symbolize_keys
21
+ # #=> { :name => "Rob", :years => "28" }
22
+ def symbolize_keys
23
+ dup.symbolize_keys!
24
+ end
25
+
26
+ # Destructively convert all keys to symbols, as long as they respond
27
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
28
+ def symbolize_keys!
29
+ keys.each do |key|
30
+ self[(key.to_sym rescue key) || key] = delete(key)
31
+ end
32
+ self
33
+ end
34
+ end
@@ -0,0 +1,52 @@
1
+ #
2
+ # Name:
3
+ # requests.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+ require 'cgi'
16
+
17
+ require_relative '../utils/retriable'
18
+ require_relative '../logging/logging'
19
+ class Request
20
+ extend Logging
21
+ extend Retriable
22
+
23
+ # Get a base url for accessing the client service
24
+ # TODO Change this to https but we need a certificate for that
25
+ def self.get_base_url(host)
26
+ url = host
27
+ url = "http://" + url unless url[0..3] == "http"
28
+ url
29
+ end
30
+
31
+
32
+ #
33
+ # Will do a request
34
+ # path will be evaluated so there could be parameters in that one and then use '' for the string
35
+ # to have the parameters evaluated in this function
36
+ #
37
+ def self.client_service_get(host, path)
38
+ url = get_base_url(host) + path
39
+ logger.debug "Will request url #{url}"
40
+ result = with_retries(:limit => 10, :sleep=> 5) { RestClient.get url }
41
+ result_json = JSON.parse(result)
42
+ logger.debug "The result of the request is #{result.inspect}"
43
+ result_json
44
+ end
45
+
46
+ def self.client_service_post(url, param)
47
+ logger.debug "Will request url #{url}"
48
+ result = with_retries(:limit => 10, :sleep=> 5) { RestClient.post url, param }
49
+ JSON.parse(result)
50
+ end
51
+
52
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # Name:
3
+ # retriable.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+
12
+ module Retriable
13
+
14
+ @@test_mode = false
15
+
16
+ # This will catch any exception and retry twice (three tries total):
17
+ # with_retries { ... }
18
+ #
19
+ # This will catch any exception and retry four times (five tries total):
20
+ # with_retries(:limit => 5) { ... }
21
+ #
22
+ # This will catch a specific exception and retry once (two tries total):
23
+ # with_retries(Some::Error, :limit => 2) { ... }
24
+ #
25
+ # You can also sleep inbetween tries. This is helpful if you're hoping
26
+ # that some external service recovers from its issues.
27
+ # with_retries(Service::Error, :sleep => 1) { ... }
28
+ #
29
+ def with_retries(*args, &block)
30
+
31
+ options = extract_options args
32
+ exceptions = args
33
+
34
+ options[:limit] ||= 3
35
+ options[:limit] = 0 if @@test_mode
36
+ options[:sleep] ||= 0
37
+ exceptions = [Exception] if exceptions.empty?
38
+
39
+ retried = 0
40
+ begin
41
+ yield
42
+ rescue *exceptions => e
43
+ logger.warn "Could not do command, will retry. Error message is #{e.inspect.to_s}"
44
+ if retried + 1 < options[:limit]
45
+ retried += 1
46
+ sleep options[:sleep]
47
+ retry
48
+ else
49
+ raise e
50
+ end
51
+ end
52
+ end
53
+
54
+ def extract_options(array)
55
+ array.last.is_a?(::Hash) ? array.pop : {}
56
+ end
57
+
58
+ def self.set_test_mode
59
+ @@test_mode = true
60
+ end
61
+
62
+
63
+ end
data/lib/utils/run.rb ADDED
@@ -0,0 +1,20 @@
1
+ #
2
+ # Name:
3
+ # run.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+
17
+ def run_cmd(cmd)
18
+ status, stdout, stderr = systemu cmd
19
+ raise "Could not run command: #{cmd}, stdout is #{stdout}, error message is #{stderr}" if status != 0
20
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,24 @@
1
+ en:
2
+ event:
3
+ converge:
4
+ chef_failed: ! 'Installation of gaddy failed. Please contact the support. Installation failed at %s. Reason: %s and %s'
5
+ chef_failed_v1: ! 'Installation of gaddy failed. Please contact the support. Installation failed at %s. Reason: %s'
6
+ ok: The device has been successful installed
7
+ repair: Repair of installation done.
8
+ usb_drive_missing: A USB drive is not connected. It should be connected as %s
9
+ init:
10
+ config_updated: The device has been succesfully initiated, installation will now start
11
+ connected: The device is successful connected to internet
12
+ install:
13
+ installation_begin: Installation of gApp %s has started
14
+ installation_failed: Installation of gApp %s failed. The gApp is not running
15
+ installation_finished: Installation of gApp %s is finished
16
+ log:
17
+ error: Error in log %s message %s
18
+ not_running: ! '%s not working. '
19
+ not_running_v1: gApp is not running
20
+ ok: Running normally
21
+ spotify_config_not_ok: There is a problem with the Spotify configuration. Try to update username and password
22
+ vpn_proxy:
23
+ missing_user_or_password: Missing user name or password for vpn_proxy, check gApp
24
+ no_connection: Could not connect to the VPN server, check configuration
data/locales/sv.yml ADDED
@@ -0,0 +1,11 @@
1
+ sv:
2
+ event:
3
+ converge:
4
+ chef_failed:
5
+ ok:
6
+ init:
7
+ config_updated:
8
+ connected:
9
+ install:
10
+ installation_begin:
11
+ installation_finished: