daemon-kit 0.1.7.9 → 0.1.7.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -57,3 +57,46 @@ instance call also be modified from the command line using the special
57
57
 
58
58
  This happens after <em>config/environment.rb</em> is processed, so all
59
59
  command line arguments will overwrite those values.
60
+
61
+ === Daemon umask
62
+
63
+ By default daemon processes run with a umask of 022, but this can be changed
64
+ on the command line or in +config/environment.rb+.
65
+
66
+ To set a more restrictive umask via command line arguments, you can start your
67
+ daemon like this:
68
+
69
+ $ ./bin/daemon start --config umask=0077
70
+
71
+ Or the same in +config/environment.rb+
72
+
73
+ DaemonKit::Initializer.run do |config|
74
+ # ...
75
+
76
+ # restrictive umask
77
+ config.umask = 0077
78
+
79
+ # ...
80
+ end
81
+
82
+ === Privilege Separation
83
+
84
+ By default daemon processes run as the user that starts them, inheriting all
85
+ their privileges (or lack thereof). Getting daemon-kit to drop privileges
86
+ can currently only be done using command-line parameters, and only works
87
+ reliable on *nix (OSX seemed cranky at the time of testing).
88
+
89
+ $ ./bin/daemon start --config user=nobody --config group=nobody
90
+
91
+ Privileges are dropped at the earliest possible phase of starting the daemon.
92
+
93
+ Things to note on privilege separation:
94
+
95
+ * You generally have to be root to be able to perform this
96
+ * File system permissions for +log/+ needs to be correct
97
+ * Daemon-kit will only shed privileges on the +start+ command, not on +run+
98
+ * Make sure your code is secure if accepting stuff from the outside world
99
+
100
+ The implementation stems from the advice given by Joe Damato on his blog post
101
+ http://timetobleed.com/tag/privilege-escalation/
102
+
@@ -1,3 +1,11 @@
1
+ == 0.1.7.10 (WIP)
2
+
3
+ * Ruote remote participants
4
+ * Allow process umask to be configured, defaults to 022
5
+ * Updates to DaemonKit::Config hashes
6
+ * Fixed argument parsing bug (reported by Mathijs Kwik (bluescreen303)
7
+ * Support for privilege separation (See Configuration.txt)
8
+
1
9
  == 0.1.7.9 2009-06-22
2
10
 
3
11
  * Backtraces only logged on unclean shutdown
@@ -6,6 +6,7 @@ Manifest.txt
6
6
  PostInstall.txt
7
7
  README.rdoc
8
8
  Rakefile
9
+ RuoteParticipants.txt
9
10
  TODO.txt
10
11
  app_generators/daemon_kit/USAGE
11
12
  app_generators/daemon_kit/daemon_kit_generator.rb
@@ -65,6 +66,14 @@ daemon_generators/rspec/templates/spec.rb
65
66
  daemon_generators/rspec/templates/spec/spec.opts
66
67
  daemon_generators/rspec/templates/spec/spec_helper.rb
67
68
  daemon_generators/rspec/templates/tasks/rspec.rake
69
+ daemon_generators/ruote/USAGE
70
+ daemon_generators/ruote/ruote_generator.rb
71
+ daemon_generators/ruote/templates/config/amqp.yml
72
+ daemon_generators/ruote/templates/config/initializers/ruote.rb
73
+ daemon_generators/ruote/templates/config/ruote.yml
74
+ daemon_generators/ruote/templates/lib/daemon.rb
75
+ daemon_generators/ruote/templates/lib/sample.rb
76
+ daemon_generators/ruote/templates/libexec/daemon.rb
68
77
  lib/daemon_kit.rb
69
78
  lib/daemon_kit/abstract_logger.rb
70
79
  lib/daemon_kit/amqp.rb
@@ -83,11 +92,15 @@ lib/daemon_kit/em.rb
83
92
  lib/daemon_kit/error_handlers/base.rb
84
93
  lib/daemon_kit/error_handlers/hoptoad.rb
85
94
  lib/daemon_kit/error_handlers/mail.rb
95
+ lib/daemon_kit/exceptions.rb
86
96
  lib/daemon_kit/initializer.rb
87
97
  lib/daemon_kit/jabber.rb
88
98
  lib/daemon_kit/nanite.rb
89
99
  lib/daemon_kit/nanite/agent.rb
90
100
  lib/daemon_kit/pid_file.rb
101
+ lib/daemon_kit/ruote_participants.rb
102
+ lib/daemon_kit/ruote_pseudo_participant.rb
103
+ lib/daemon_kit/ruote_workitem.rb
91
104
  lib/daemon_kit/safety.rb
92
105
  lib/daemon_kit/tasks.rb
93
106
  lib/daemon_kit/tasks/environment.rake
@@ -122,6 +135,7 @@ test/test_generator_helper.rb
122
135
  test/test_helper.rb
123
136
  test/test_jabber_generator.rb
124
137
  test/test_nanite_agent_generator.rb
138
+ test/test_ruote_generator.rb
125
139
  vendor/tmail-1.2.3/tmail.rb
126
140
  vendor/tmail-1.2.3/tmail/address.rb
127
141
  vendor/tmail-1.2.3/tmail/attachments.rb
@@ -13,9 +13,11 @@ Using simple built-in generators it is easy to created evented and non-evented d
13
13
 
14
14
  Supported generators:
15
15
 
16
- * Evented and non-evented Jabber Bot (coming next)
17
- * Evented and non-evented loops (coming soon)
18
- * Queue poller (SQS, AMQP, etc) (coming soon)
16
+ * XMPP bot (non-evented)
17
+ * AMQP consumer (evented)
18
+ * Nanite agent
19
+ * Cron-style daemon
20
+ * ruote remote participants
19
21
 
20
22
  == Features/Problems
21
23
 
@@ -24,17 +26,21 @@ Supported generators:
24
26
 
25
27
  == Synopsis
26
28
 
27
- $ daemon-kit [/path/to/your/daemon] [options]
29
+ $ daemon_kit -h
30
+
31
+ Get some help
32
+
33
+ $ daemon_kit [/path/to/your/daemon] [options]
28
34
 
29
35
  The above command generates a skeleton daemon environment for you to adapt.
30
36
 
31
- $ daemon-kit [/path/to/your/daemon] -i jabber
37
+ $ daemon_kit [/path/to/your/daemon] -i jabber
32
38
 
33
39
  Use the 'jabber' generator instead of the default one.
34
40
 
35
41
  == Generators
36
42
 
37
- Currently only two generators exist, a 'default' generator and a 'jabber' generator.
43
+ Currently six generators exist: default, jabber, amqp, cron, nanite & ruote
38
44
 
39
45
  The default generator creates a simple daemon with an infinite loop inside that you can adapt.
40
46
 
@@ -50,6 +56,14 @@ The cron generator creates a simple daemon that leverages the "rufus-scheduler":
50
56
 
51
57
  The AMQP generator creates a simple daemon that has all the stub code and configuration in place to help you write AMQP consumers quickly and effectively. The generated daemon relies on the presence of the "amqp":http://github.com/tmm1/amqp gem.
52
58
 
59
+ === Nanite Agent Generator
60
+
61
+ The "nanite":http://github.com/ezmobius/nanite agent generator gets you up and running with nanite agents very quickly.
62
+
63
+ === ruote Remote Participants
64
+
65
+ The "ruote":http://openwfe.rubyforge.org remote participant generator speeds up the development of workflow participants that run outside of the Ruby process that houses the engine. Daemon-kit handles all the communication and delegation logic, allowing you to focus purely on your participant's activities.
66
+
53
67
  == Requirements
54
68
 
55
69
  * Ruby 1.8.6
@@ -61,8 +75,10 @@ The AMQP generator creates a simple daemon that has all the stub code and config
61
75
  Depending on the generator you choose for your daemon, it might require additional gems to run.
62
76
 
63
77
  * jabber - xmpp4r-simple[http://xmpp4r-simple.rubyforge.org]
64
- * cron - rufus-scheduler[http://github.com/jmettraux/rufus-scheduler]
78
+ * cron - rufus-scheduler[http://github.com/jmettraux/rufus-scheduler] (at least version 2.0.0)
65
79
  * amqp - amqp[http://github.com/tmm1/amqp]
80
+ * nanite - nanite[http://github.com/ezmobius/nanite]
81
+ * ruote - none, although ruote[http://openwfe.rubyforge.org] should probably be running somewhere
66
82
 
67
83
  == Install
68
84
 
@@ -84,6 +100,9 @@ Stable versions, when released are available directly from Rubyforge:
84
100
 
85
101
  * Configuration.txt
86
102
  * Deployment.txt
103
+ * Logging.txt
104
+ * RuoteParticipants.txt
105
+ * http://www.opensourcery.co.za/tag/daemon-kit/
87
106
 
88
107
  == License
89
108
 
data/Rakefile CHANGED
@@ -1,9 +1,16 @@
1
- %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
2
5
  require File.dirname(__FILE__) + '/lib/daemon_kit'
3
6
 
7
+ Hoe.plugin :newgem
8
+ Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
10
+
4
11
  # Generate all the Rake tasks
5
12
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
- $hoe = Hoe.new('daemon-kit', DaemonKit::VERSION) do |p|
13
+ $hoe = Hoe.spec('daemon-kit') do |p|
7
14
  p.summary = 'Daemon Kit aims to simplify creating Ruby daemons by providing a sound application skeleton (through a generator), task specific generators (jabber bot, etc) and robust environment management code.'
8
15
  p.developer('Kenneth Kalmer', 'kenneth.kalmer@gmail.com')
9
16
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
@@ -0,0 +1,113 @@
1
+ = Writing remote ruote participants with daemon-kit
2
+
3
+ daemon-kit is an ideal housing for remote ruote participants, providing a lot
4
+ of convenience in terms of receiving and sending workitems, delegating work to
5
+ pseudo-participant classes, handling configuration of the communication channel
6
+ between ruote and the remote participant, and much more.
7
+
8
+ == What is ruote?
9
+
10
+ Ruote is a Ruby workflow engine. It is a powerful tool for defining, running and
11
+ orchestrating business processes.
12
+
13
+ * http://openwferu.rubyforge.org/
14
+ * http://www.opensourcery.co.za/2009/03/04/ruote-in-20-minutes/
15
+ * http://www.opensourcery.co.za/2009/07/06/driving-business-processes-in-ruby/
16
+
17
+ == What are remote participants?
18
+
19
+ Remote participants are participants that perform their work in a different
20
+ Ruby processes from the one running the engine. This is useful in two cases,
21
+ possibily many more, that involves autonomous participants.
22
+
23
+ * Autonomous participants located on remote servers, driven by identity
24
+ * Clustering autonomous participants to process workitems from a queue
25
+
26
+ To learn more about the differences between local and remote participants
27
+ please see http://openwferu.rubyforge.org/part.html
28
+
29
+ Currently on the AMQP components are in place in daemon-kit, with XMPP coming
30
+ soon.
31
+
32
+ == Creating a remote participant with daemon-kit
33
+
34
+ Generate your daemon using the 'ruote' generator:
35
+
36
+ $ daemon_kit partd -i ruote
37
+
38
+ Make sure you have the JSON gem install, and the AMQP gem as well.
39
+
40
+ == Configuring the daemon
41
+
42
+ You need to review +config/ruote.yml+ to specify the AMQP queues that the daemon
43
+ will subscribe to for receiving workitems. You'll also need to configure the
44
+ AMQP gem be updating +config/amqp.yml+
45
+
46
+ The generated daemon in +libexec/+ already defaults to using AMQP as a transport
47
+ for workitems.
48
+
49
+ == Writing pseudo-participants
50
+
51
+ Pseudo-participants in daemon-kit are pure Ruby classes. Implement your classes
52
+ in +lib/+ and require them from +lib/<daemon_name>.rb+.
53
+
54
+ Register your classes as pseudo-participants by registering them in the daemon
55
+ file in +libexec+, just as the Sample class is registered in the generated
56
+ code. Your class will be instantiated upon registration, and will be re-used
57
+ for every incoming workitem passed to it.
58
+
59
+ All your public methods in the pseudo-participant classes should be accept
60
+ a single parameter, which is a ruote workitem in pure Hash form.
61
+
62
+ == Wiring up the remote participant in ruote
63
+
64
+ See the complete code here: http://gist.github.com/144861
65
+
66
+ A sample process definition might look something like this:
67
+
68
+ class QuoteProcess < OpenWFE::ProcessDefinition
69
+ sequence do
70
+ kit :command => '/sample/quote', :queue => 'work1'
71
+
72
+ console
73
+ end
74
+ end
75
+
76
+ +kit+ in the above process definition is registered with the ruote engine as an
77
+ AMQPParticipant. The AMQPParticipant delivers workitems to the specified AMQP
78
+ queue.
79
+
80
+ Based on the values in +config/ruote.yml+, your daemon will be subscribed to
81
+ those queues.
82
+
83
+ The second part is delegating the workitem inside the daemon to the correct
84
+ pseudo-participant. This is handled by the +:command+ parameter in the process
85
+ definition. DaemonKit::Workitem looks at the command parameter of the incoming
86
+ workitem, and then finds a registered pseudo-participant instance and calls the
87
+ requested method on that class.
88
+
89
+ The +:command+ parameter follows the following convention (stolen shamelessly
90
+ from Nanite):
91
+
92
+ :command => '/class_name/method_name'
93
+
94
+ When classes are registered, the name of the class is downcased and camel-case
95
+ words are separated by underscores. Method names are not changed, but methods
96
+ are required to be public.
97
+
98
+ == Processing workitems and replying to the engine
99
+
100
+ The methods called in the pseudo-participants receive a single parameter, a
101
+ ruote workitem as a hash. The participant is then free to analyze the hash
102
+ and perform the appropriate actions required. The return value of the method
103
+ is discarded, and the workitem is returned back to the engine. If the method
104
+ modified the workitem, these changes will be sent along as well.
105
+
106
+ == Random other notes
107
+
108
+ Apart from configuring the AMPQ client (or XMPP in future) and the ruote.yml
109
+ file, daemon developers don't need to worry about anything related to receiving
110
+ workitems or sending replies.
111
+
112
+ Our aim is to allow you to swap between participants on both sides of the
113
+ transport without changing any of your code.
@@ -3,7 +3,7 @@ class DaemonKitGenerator < RubiGen::Base
3
3
  DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
4
4
  Config::CONFIG['ruby_install_name'])
5
5
 
6
- VALID_GENERATORS = ['default', 'jabber', 'cron', 'amqp', 'nanite_agent']
6
+ VALID_GENERATORS = ['default', 'jabber', 'cron', 'amqp', 'nanite_agent', 'ruote']
7
7
 
8
8
  DEPLOYERS = ['none', 'capistrano']
9
9
 
@@ -76,13 +76,13 @@ class DaemonKitGenerator < RubiGen::Base
76
76
  m.directory "config/post-daemonize"
77
77
  m.file "config/post-daemonize/readme", "config/post-daemonize/readme"
78
78
  m.directory "script"
79
- m.file "script/destroy", "script/destroy"
80
- m.file "script/console", "script/console"
81
- m.file "script/generate", "script/generate"
79
+ m.file "script/destroy", "script/destroy", script_options
80
+ m.file "script/console", "script/console", script_options
81
+ m.file "script/generate", "script/generate", script_options
82
82
 
83
83
  # Libraries
84
84
  m.directory "lib"
85
- m.file "lib/daemon.rb", "lib/#{daemon_name}.rb"
85
+ m.file "lib/daemon.rb", "lib/#{daemon_name}.rb", :collision => :skip
86
86
 
87
87
  # Tasks
88
88
  m.directory "tasks"
@@ -0,0 +1,5 @@
1
+ Description:
2
+
3
+
4
+ Usage:
5
+
@@ -0,0 +1,67 @@
1
+ class RuoteGenerator < RubiGen::Base
2
+
3
+ default_options :author => nil
4
+
5
+ attr_reader :name
6
+
7
+ def initialize(runtime_args, runtime_options = {})
8
+ super
9
+ usage if args.empty?
10
+ @name = args.shift
11
+ extract_options
12
+ end
13
+
14
+ def manifest
15
+ record do |m|
16
+ # Ensure appropriate folder(s) exists
17
+ m.directory ''
18
+
19
+ # Create stubs
20
+ # m.template "template.rb.erb", "some_file_after_erb.rb"
21
+ # m.template_copy_each ["template.rb", "template2.rb"]
22
+ # m.template_copy_each ["template.rb", "template2.rb"], "some/path"
23
+ # m.file "file", "some_file_copied"
24
+ # m.file_copy_each ["path/to/file", "path/to/file2"]
25
+ # m.file_copy_each ["path/to/file", "path/to/file2"], "some/path"
26
+
27
+ m.directory 'config'
28
+ m.template 'config/amqp.yml', 'config/amqp.yml'
29
+ m.template 'config/ruote.yml', 'config/ruote.yml'
30
+ m.directory 'config/initializers'
31
+ m.template 'config/initializers/ruote.rb', "config/initializers/#{name}.rb"
32
+
33
+ m.directory 'lib'
34
+ m.template 'lib/daemon.rb', "lib/#{name}.rb"
35
+ m.template 'lib/sample.rb', 'lib/sample.rb'
36
+ m.directory 'libexec'
37
+ m.template 'libexec/daemon.rb', "libexec/#{name}-daemon.rb"
38
+ end
39
+ end
40
+
41
+ protected
42
+ def banner
43
+ <<-EOS
44
+ Creates a ...
45
+
46
+ USAGE: #{$0} #{spec.name} name
47
+ EOS
48
+ end
49
+
50
+ def add_options!(opts)
51
+ # opts.separator ''
52
+ # opts.separator 'Options:'
53
+ # For each option below, place the default
54
+ # at the top of the file next to "default_options"
55
+ # opts.on("-a", "--author=\"Your Name\"", String,
56
+ # "Some comment about this option",
57
+ # "Default: none") { |o| options[:author] = o }
58
+ # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
59
+ end
60
+
61
+ def extract_options
62
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
63
+ # Templates can access these value via the attr_reader-generated methods, but not the
64
+ # raw instance variable value.
65
+ # @author = options[:author]
66
+ end
67
+ end
@@ -0,0 +1,30 @@
1
+ # AMQP client configuration file for ruote remote participants. If you are not
2
+ # planning to use the AMQP participant/listener pair in ruote, you can safely
3
+ # delete this file.
4
+
5
+ # These values will be used to configure the ampq gem, any values
6
+ # omitted will let the gem use it's own defaults.
7
+
8
+ # The configuration specifies the following keys:
9
+ # * user - Username for the broker
10
+ # * pass - Password for the broker
11
+ # * host - Hostname where the broker is running
12
+ # * vhost - Vhost to connect to
13
+ # * port - Port where the broker is running
14
+ # * ssl - Use ssl or not
15
+ # * timeout - Timeout
16
+
17
+ defaults: &defaults
18
+ user: guest
19
+ pass: guest
20
+ host: localhost
21
+ vhost: /
22
+
23
+ development:
24
+ <<: *defaults
25
+
26
+ test:
27
+ <<: *defaults
28
+
29
+ production:
30
+ <<: *defaults