diff --git a/CHANGELOG b/CHANGELOG index e705788f..cf0ac21a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *0.11.0* *SVN* +* Add extension mechanism for custom ST operations + * Make ST rails rake tasks more configurable * Add Actor#current_task and simplify Task#servers diff --git a/lib/switchtower/configuration.rb b/lib/switchtower/configuration.rb index 53dfa0d8..57916123 100644 --- a/lib/switchtower/configuration.rb +++ b/lib/switchtower/configuration.rb @@ -1,6 +1,7 @@ require 'switchtower/actor' require 'switchtower/logger' require 'switchtower/scm/subversion' +require 'switchtower/extensions' module SwitchTower # Represents a specific SwitchTower configuration. A Configuration instance diff --git a/lib/switchtower/extensions.rb b/lib/switchtower/extensions.rb new file mode 100644 index 00000000..e6e0929b --- /dev/null +++ b/lib/switchtower/extensions.rb @@ -0,0 +1,38 @@ +require 'switchtower/actor' + +module SwitchTower + class ExtensionProxy + def initialize(actor, mod) + @actor = actor + extend(mod) + end + + def method_missing(sym, *args, &block) + @actor.send(sym, *args, &block) + end + end + + EXTENSIONS = {} + + def self.plugin(name, mod) + return false if EXTENSIONS.has_key?(name) + + SwitchTower::Actor.class_eval <<-STR, __FILE__, __LINE__+1 + def #{name} + @__#{name}_proxy ||= SwitchTower::ExtensionProxy.new(self, SwitchTower::EXTENSIONS[#{name.inspect}]) + end + STR + + EXTENSIONS[name] = mod + return true + end + + def self.remove_plugin(name) + if EXTENSIONS.delete(name) + SwitchTower::Actor.send(:remove_method, name) + return true + end + + return false + end +end \ No newline at end of file diff --git a/test/actor_test.rb b/test/actor_test.rb index 3cb424d7..371abc80 100644 --- a/test/actor_test.rb +++ b/test/actor_test.rb @@ -84,6 +84,12 @@ class ActorTest < Test::Unit::TestCase end end + module CustomExtension + def do_something_extra(a, b, c) + run "echo '#{a} :: #{b} :: #{c}'" + end + end + def setup TestingCommand.reset! @actor = TestActor.new(MockConfiguration.new) @@ -275,4 +281,14 @@ class ActorTest < Test::Unit::TestCase assert_raises(RuntimeError) { @actor.foo } end + + def test_custom_extension + assert SwitchTower.plugin(:custom, CustomExtension) + @actor.define_task :foo, :roles => :db do + custom.do_something_extra(1, 2, 3) + end + assert_nothing_raised { @actor.foo } + assert TestingCommand.invoked? + assert SwitchTower.remove_plugin(:custom) + end end