file-watcher 1.0.0
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/watch_config.rb +34 -0
- data/watch_job.rb +47 -0
- data/watcher.rb +90 -0
- metadata +79 -0
data/watch_config.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module WatchConfig
|
2
|
+
|
3
|
+
def self.included base
|
4
|
+
base.extend( ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def validate_new_job wj
|
9
|
+
raise "Error: Watch job is missing watch dir: #{wj.inspect}" unless wj.watch_criteria.keys.include? :target_dir
|
10
|
+
|
11
|
+
raise "Error: Watch directory doesn't exist: #{wj.watch_criteria[:target_dir]}" unless File.exist? wj.watch_criteria[:target_dir]
|
12
|
+
|
13
|
+
raise "Error: Watch configuration did not specify any events to watch for (#{wj.inspect})" if wj.watch_criteria[:events].empty?
|
14
|
+
|
15
|
+
|
16
|
+
raise "Error: Only http watch actions are supported: #{wj}" unless wj.watch_action.keys == [:http]
|
17
|
+
|
18
|
+
raise "Error: Invalid/Unsupported http method [#{wj.watch_action[:http][:method]}] in config [#{wj.watch_action.inspect}]" unless wj.watch_action[:http][:method] == :post
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_watch_job &block
|
22
|
+
wj = WatchJob.new
|
23
|
+
|
24
|
+
yield wj
|
25
|
+
|
26
|
+
validate_new_job wj
|
27
|
+
self.registered_jobs << wj
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
|
data/watch_job.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), 'watch_config')
|
2
|
+
require 'cgi'
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
class WatchJob
|
7
|
+
include WatchConfig
|
8
|
+
attr_accessor :watch_criteria, :watch_action
|
9
|
+
|
10
|
+
@@registered_jobs = []
|
11
|
+
|
12
|
+
def self.registered_jobs
|
13
|
+
@@registered_jobs
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def do_post event
|
18
|
+
Net::HTTP.start(watch_action[:http][:hostname]) do |http|
|
19
|
+
if watch_action[:http][:ssl]
|
20
|
+
protocol = 'https'
|
21
|
+
else
|
22
|
+
protocol = 'http'
|
23
|
+
end
|
24
|
+
|
25
|
+
url = "#{protocol}://#{watch_action[:http][:auth_user]}:#{watch_action[:http][:auth_pass]}@#{watch_action[:http][:hostname]}:#{watch_action[:http][:port]}#{watch_action[:http][:command_uri]}"
|
26
|
+
|
27
|
+
|
28
|
+
body = watch_action[:http][:command].merge({ :args => watch_action[:http][:command][:args].dup.push(event.name) } )
|
29
|
+
|
30
|
+
puts "URL: #{url}"
|
31
|
+
puts "body: #{body}"
|
32
|
+
|
33
|
+
res = Net::HTTP.post_form(URI.parse(url), {'body' => body.to_json } )
|
34
|
+
puts "Response: #{res}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def event_handler event
|
39
|
+
debugger
|
40
|
+
return unless event.name =~ watch_criteria[:file_glob]
|
41
|
+
|
42
|
+
if watch_action.keys.first == :http && watch_action[:http][:method] == :post
|
43
|
+
do_post event
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/watcher.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'ruby-debug'
|
4
|
+
require 'base_app'
|
5
|
+
require 'rb-inotify'
|
6
|
+
require 'json'
|
7
|
+
require File.join( File.dirname(__FILE__), 'watch_job' )
|
8
|
+
|
9
|
+
|
10
|
+
#
|
11
|
+
# to watch the current directory, run:
|
12
|
+
#
|
13
|
+
# ruby watcher.rb -d . -c trigger
|
14
|
+
#
|
15
|
+
# This also specifies a 'command' directory - a place where if you
|
16
|
+
# touch a 'stop' file, the inotify loop will terminate.
|
17
|
+
#
|
18
|
+
|
19
|
+
|
20
|
+
class Watcher < BaseApp
|
21
|
+
|
22
|
+
def command_line_arguments
|
23
|
+
super.concat [["w","watch-job-dir=","Directory of watch jobs.", true],
|
24
|
+
["c","control-dir=","Control directory to watch for a 'stop' file..", true]]
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_flags_map flags
|
28
|
+
flags.inject({}) do |m,f|
|
29
|
+
m[f] = true
|
30
|
+
m
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def stop_file_path
|
35
|
+
"#{@control_dir}/stop"
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_event event, flags
|
39
|
+
if event.name == 'stop'
|
40
|
+
if File.exist?(stop_file_path)
|
41
|
+
@notifier.stop
|
42
|
+
File.delete stop_file_path
|
43
|
+
return
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# we don't care about things like 'ls' or other changes on the directory itself
|
48
|
+
return if flags[:isdir]
|
49
|
+
|
50
|
+
puts "handle event: #{event.name} was #{flags.inspect}"
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
def run
|
56
|
+
@control_dir = self.control_dir || '.'
|
57
|
+
|
58
|
+
|
59
|
+
Dir["#{@watch_job_dir}/*.rb"].each do |f|
|
60
|
+
require File.join( File.dirname(__FILE__), f)
|
61
|
+
end
|
62
|
+
|
63
|
+
@notifier = INotify::Notifier.new
|
64
|
+
# these are all the events we can watch for: :access, :attrib,
|
65
|
+
# :close_write, :close_nowrite, :create, :delete, :delete_self,
|
66
|
+
# :modify, :move_self, :moved_from, :moved_to, :open
|
67
|
+
|
68
|
+
# :access is too noisy for watching a directory (lots and lots of events)
|
69
|
+
# notifier.watch(@dir, :attrib, :close_write, :close_nowrite, :create, :delete, :delete_self, :modify, :move_self, :moved_from, :moved_to, :open) do |event|
|
70
|
+
|
71
|
+
WatchJob.registered_jobs.each do |job|
|
72
|
+
@notifier.watch(job.watch_criteria[:target_dir], *job.watch_criteria[:events]) do |event|
|
73
|
+
job.event_handler event
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
@notifier.watch(@control_dir, :close_write, :close_nowrite, :create, :delete, :modify, :moved_from, :moved_to, :delete_self, :move_self, :recursive) do |event|
|
78
|
+
puts "CONTROL DIR HIT: #{@control_dir}"
|
79
|
+
handle_event event, make_flags_map(event.flags)
|
80
|
+
end
|
81
|
+
|
82
|
+
puts "Entering run loop."
|
83
|
+
@notifier.run
|
84
|
+
puts "Exited run loop."
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
if $0 == __FILE__
|
89
|
+
Watcher.main
|
90
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: file-watcher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Paul Santa Clara
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-25 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rb-inotify
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 8
|
30
|
+
- 4
|
31
|
+
version: 0.8.4
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: |
|
35
|
+
Use inotify to watch for file system modifcations and take a configured action.'
|
36
|
+
|
37
|
+
email: "kburton@relaynetwork.com "
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- watch_config.rb
|
46
|
+
- watcher.rb
|
47
|
+
- watch_job.rb
|
48
|
+
has_rdoc: true
|
49
|
+
homepage:
|
50
|
+
licenses: []
|
51
|
+
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.3.6
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Use inotify to watch for file system modifcations and take a configured action.
|
78
|
+
test_files: []
|
79
|
+
|