Make the registration target collective configurable.  Refactor the base
class to be more testable and provide test coverage for non threaded
code.  Update documentation.

Signed-off-by: R.I.Pienaar <[email protected]>
---
Local-branch: feature/master/7650
 lib/mcollective/config.rb                 |    6 ++-
 lib/mcollective/registration/base.rb      |   74 +++++++++++++++++------
 spec/unit/registration/base_spec.rb       |   93 +++++++++++++++++++++++++++++
 website/changelog.md                      |    1 +
 website/reference/basic/configuration.md  |    1 +
 website/reference/plugins/registration.md |   20 ++++---
 6 files changed, 167 insertions(+), 28 deletions(-)
 create mode 100644 spec/unit/registration/base_spec.rb

diff --git a/lib/mcollective/config.rb b/lib/mcollective/config.rb
index 8574472..6c8e8e4 100644
--- a/lib/mcollective/config.rb
+++ b/lib/mcollective/config.rb
@@ -8,7 +8,8 @@ module MCollective
                     :securityprovider, :factsource, :registration, 
:registerinterval, :topicsep,
                     :classesfile, :rpcauditprovider, :rpcaudit, :configdir, 
:rpcauthprovider,
                     :rpcauthorization, :color, :configfile, :rpchelptemplate, 
:rpclimitmethod,
-                    :logger_type, :fact_cache_time, :collectives, 
:main_collective, :ssl_cipher
+                    :logger_type, :fact_cache_time, :collectives, 
:main_collective, :ssl_cipher,
+                    :registration_collective
 
         def initialize
             @configured = false
@@ -33,6 +34,8 @@ module MCollective
                                     @topicsep = val
                                 when "registration"
                                     @registration = val.capitalize
+                                when "registration_collective"
+                                    @registration_collective = val
                                 when "registerinterval"
                                     @registerinterval = val.to_i
                                 when "collectives"
@@ -125,6 +128,7 @@ module MCollective
             @identity = Socket.gethostname
             @registration = "Agentlist"
             @registerinterval = 0
+            @registration_collective = nil
             @topicsep = "."
             @classesfile = "/var/lib/puppet/classes.txt"
             @rpcaudit = false
diff --git a/lib/mcollective/registration/base.rb 
b/lib/mcollective/registration/base.rb
index 969ee30..9859f61 100644
--- a/lib/mcollective/registration/base.rb
+++ b/lib/mcollective/registration/base.rb
@@ -17,35 +17,73 @@ module MCollective
             # The actual registration notices comes from the 'body' method of 
the registration
             # plugins.
             def run(connection)
-                config = Config.instance
-                return if config.registerinterval == 0
+                return false if interval == 0
 
                 Thread.new do
                     loop do
                         begin
-                            target = Util.make_target("registration", 
:command, config.main_collective)
-                            reqid = 
Digest::MD5.hexdigest("#{config.identity}-#{Time.now.to_f.to_s}-#{target}")
-                            filter = {"agent" => "registration"}
+                            publish(body, connection)
 
-                            registration_message = body
-
-                            unless registration_message.nil?
-                                req = 
PluginManager["security_plugin"].encoderequest(config.identity, target, 
registration_message, reqid, filter)
-
-                                Log.debug("Sending registration #{reqid} to 
#{target}")
-                                connection.publish(target, req)
-                            else
-                                Log.debug("Skipping registration due to nil 
body")
-                            end
-
-                            sleep config.registerinterval
+                            sleep interval
                         rescue Exception => e
                             Log.error("Sending registration message failed: 
#{e}")
-                            sleep config.registerinterval
+                            sleep interval
                         end
                     end
                 end
             end
+
+            def config
+                Config.instance
+            end
+
+            def identity
+                config.identity
+            end
+
+            def msg_filter
+                {"agent" => "registration"}
+            end
+
+            def msg_id(target)
+                reqid = 
Digest::MD5.hexdigest("#{config.identity}-#{Time.now.to_f.to_s}-#{target}")
+            end
+
+            def msg_target
+                Util.make_target("registration", :command, target_collective)
+            end
+
+            def target_collective
+                main_collective = config.main_collective
+
+                collective = config.registration_collective || main_collective
+
+                unless config.collectives.include?(collective)
+                    Log.warn("Sending registration to #{main_collective}: 
#{collective} is not a valid collective")
+                    collective = main_collective
+                end
+
+                return collective
+            end
+
+            def interval
+                config.registerinterval
+            end
+
+            def publish(message, connection)
+                unless message
+                    Log.debug("Skipping registration due to nil body")
+                else
+                    target = msg_target
+                    reqid = msg_id(target)
+
+                    req = 
PluginManager["security_plugin"].encoderequest(identity, target, message, 
reqid, msg_filter)
+
+                    Log.debug("Sending registration #{reqid} to #{target}")
+
+                    connection.publish(target, req)
+                end
+            end
         end
     end
 end
diff --git a/spec/unit/registration/base_spec.rb 
b/spec/unit/registration/base_spec.rb
new file mode 100644
index 0000000..c59b373
--- /dev/null
+++ b/spec/unit/registration/base_spec.rb
@@ -0,0 +1,93 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+module MCollective
+    module Registration
+        describe Base do
+            before do
+                @config = mock
+                @config.stubs(:identity).returns("rspec")
+                @config.stubs(:main_collective).returns("main_collective")
+                Config.stubs(:instance).returns(@config)
+
+                @reg = Base.new
+            end
+
+            describe "#config" do
+                it "should provide access the main configuration class" do
+                    @reg.config.should == @config
+                end
+
+            end
+
+            describe "#identity" do
+                it "should return the correct identity" do
+                    @reg.config.identity.should == "rspec"
+                end
+            end
+
+            describe "#msg_filter" do
+                it "should target the registration agent" do
+                    @reg.msg_filter.should == {"agent" => "registration"}
+                end
+            end
+
+            describe "#msg_id" do
+                it "should create the message id correctly" do
+                    
Digest::MD5.expects(:hexdigest).with(regexp_matches(/rspec-.+-test/))
+                    @reg.msg_id("test")
+                end
+            end
+
+            describe "#msg_target" do
+                it "should create a target for the correct agent and 
collective" do
+                    @reg.expects(:target_collective).returns("test").once
+                    Util.expects(:make_target).with("registration", :command, 
"test").once
+                    @reg.msg_target
+                end
+            end
+
+            describe "#target_collective" do
+                it "should return the configured registration_collective" do
+                    
@config.expects(:registration_collective).returns("registration").once
+                    @config.expects(:collectives).returns(["main_collective", 
"registration"]).once
+                    @reg.target_collective.should == "registration"
+                end
+
+                it "should use the main collective if registration collective 
is not valid" do
+                    
@config.expects(:registration_collective).returns("registration").once
+                    
@config.expects(:collectives).returns(["main_collective"]).once
+
+                    Log.expects(:warn).with("Sending registration to 
main_collective: registration is not a valid collective").once
+
+                    @reg.target_collective.should == "main_collective"
+                end
+            end
+
+            describe "#publish" do
+                it "should skip registration for empty messages" do
+                    Log.expects(:debug).with("Skipping registration due to nil 
body")
+                    @reg.publish(nil, nil)
+                end
+
+                it "should encode the request via the security plugin and 
publish correctly" do
+                    security_plugin = mock
+                    connection = mock
+
+                    
PluginManager.expects("[]").with("security_plugin").returns(security_plugin)
+
+                    @reg.expects(:msg_target).returns("target").once
+                    @reg.expects(:msg_id).with("target").returns("msgid").once
+                    @reg.expects(:msg_filter).returns("msgfilter").once
+
+                    security_plugin.expects(:encoderequest).with("rspec", 
"target", "message", "msgid", "msgfilter").returns("req").once
+                    connection.expects(:publish).with("target", "req")
+                    Log.expects(:debug).with("Sending registration msgid to 
target")
+
+                    @reg.publish("message", connection)
+                end
+            end
+        end
+    end
+end
diff --git a/website/changelog.md b/website/changelog.md
index ee739b1..8a4ff1b 100644
--- a/website/changelog.md
+++ b/website/changelog.md
@@ -11,6 +11,7 @@ title: Changelog
 
 |Date|Description|Ticket|
 |----|-----------|------|
+|2011/05/25|Make the target collective for registration messages 
configurable|7650|
 |2011/05/24|Rename the connector plugins send method to publish to avoid 
issues ruby Object#send|7623|
 |2011/05/23|Log a warning when the CF file parsing fails rather than raise a 
whole ruby exception|7627|
 |2011/05/23|Allow applications to use the exit method as would normally be 
expected|7626|
diff --git a/website/reference/basic/configuration.md 
b/website/reference/basic/configuration.md
index 37f7307..9b70448 100644
--- a/website/reference/basic/configuration.md
+++ b/website/reference/basic/configuration.md
@@ -53,6 +53,7 @@ The server configuration file should be root only readable
 |factsource|Facter|Which fact plugin to use|
 |registration|Agentlist|[Registration] plugin to use|
 |registerinterval|120|How many seconds to sleep between registration messages, 
setting this to zero disables registration|
+|registration_collective|development|Which sub-collective to send registration 
messages to|
 |classesfile|/var/lib/puppet/classes.txt|Where to find a list of classes 
configured by your configuration management system|
 |rpcaudit|1|Enables [SimpleRPC Auditing][Auditing]|
 |rpcauditprovider|Logfile|Enables auditing using _MCollective::Audit::Logfile_|
diff --git a/website/reference/plugins/registration.md 
b/website/reference/plugins/registration.md
index 7ff637f..9392f23 100644
--- a/website/reference/plugins/registration.md
+++ b/website/reference/plugins/registration.md
@@ -8,7 +8,7 @@ disqus: true
 # {{page.title}}
 
 MCollective supports the ability for each node to register with a central 
inventory. The core functionality
-of Mcollective doesn't require registration internally; it's simply provided 
as a framework to enable you to 
+of Mcollective doesn't require registration internally; it's simply provided 
as a framework to enable you to
 build inventory systems or Web UIs.
 
 ## Details
@@ -31,28 +31,30 @@ module MCollective
 end
 {% endhighlight %}
 
-You can see it's very simple, you just need to subclass 
*MCollective::Registration::Base* to ensure they get 
+You can see it's very simple, you just need to subclass 
*MCollective::Registration::Base* to ensure they get
 loaded into the plugin system and provide a _body_ method whose return value 
will be sent to the registration agent(s).
 
 As of version 1.1.2 the registration plugin can decide if a message should be 
sent or not.  If your plugin
 responds with a _nil_ value the message will not be sent.  This can be useful 
if you wish to only send
 registration data when some condition has changed. On large collectives, 
registration messages can be
-quite high-volume. It's worthwhile to sample the size of your registration 
messages and multiply by the number 
-of nodes to determine an appropriate frequency to send them. 
+quite high-volume. It's worthwhile to sample the size of your registration 
messages and multiply by the number
+of nodes to determine an appropriate frequency to send them.
 
 To configure it to be used you just need the following in your config:
 
 {% highlight ini %}
 registerinterval = 300
 registration = Agentlist
+registration_collective = development
 {% endhighlight %}
 
-This will cause the plugin to be called every 300 seconds.
+This will cause the plugin to be called every 300 seconds to the development 
collective, if you do not configure
+a target collective explicitely it will target the main collective for the 
given node.
 
 We do not provide the receiving end of this in the core mcollective. You will 
need to write an agent called
 *registration* and do something useful with the data you receive from all the 
nodes. You can find
-[a simple monitoring system][RegistrationMonitor] built using this method as 
an example. The receiving agent 
-can simply be installed as an extra mcollectived plugin on a node which 
participates in the collective. 
+[a simple monitoring system][RegistrationMonitor] built using this method as 
an example. The receiving agent
+can simply be installed as an extra mcollectived plugin on a node which 
participates in the collective.
 
 You need to note a few things about the receiving agents:
 
@@ -62,6 +64,6 @@ You need to note a few things about the receiving agents:
    an indication that you do not want to send back any reply.  Replying to 
registration requests is almost always undesired.
 
 There's nothing preventing you from running more than one type of receiving 
agent in your collective, you can have one
-on your monitor server as above and another with completely different code on 
a web server feeding a local 
-cache for your web interfaces.  As long as both agents are called 
*registration* you'll be fine. However this 
+on your monitor server as above and another with completely different code on 
a web server feeding a local
+cache for your web interfaces.  As long as both agents are called 
*registration* you'll be fine. However this
 does mean you can't run more than one registration receiver on the same server.
-- 
1.7.1

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to