Jamis,
Thanks for your quick answer! Your suggestion sounds much simpler
than my instance patch ;)
In your example, the "something" task is actually executed until
there is a call to find_servers. find_severs calls role_list_from
that raises the error when no host is found for one of the roles of
the task. I tried to call find_servers_for_task at the beginning of
the task, but find_servers_for_task calls find_servers, so I get the
exception anyway.
I have patched find_servers and execute_task as follow to follow your
suggestion of a task option:
Index: lib/capistrano/configuration/execution.rb
===================================================================
--- lib/capistrano/configuration/execution.rb (revision 6951)
+++ lib/capistrano/configuration/execution.rb (working copy)
@@ -75,6 +75,7 @@
# Executes the task with the given name, including the before
and after
# hooks.
def execute_task(task)
+ return if find_servers_for_task(task).empty?
logger.debug "executing `#{task.fully_qualified_name}'"
push_task_call_frame(task)
task.namespace.instance_eval(&task.body)
Index: lib/capistrano/configuration/servers.rb
===================================================================
--- lib/capistrano/configuration/servers.rb (revision 6951)
+++ lib/capistrano/configuration/servers.rb (working copy)
@@ -35,7 +35,12 @@
# servers = find_servers :hosts => "[EMAIL PROTECTED]"
def find_servers(options={})
hosts = server_list_from(ENV['HOSTS'] || options[:hosts])
- roles = role_list_from(ENV['ROLES'] || options[:roles] ||
self.roles.keys)
+ begin
+ roles = role_list_from(ENV['ROLES'] || options[:roles] ||
self.roles.keys)
+ rescue ArgumentError => ex
+ return [] if options[:if_no_servers_match] == :skip
+ raise ex
+ end
only = options[:only] || {}
except = options[:except] || {}
What do you think?
Mathieu
On Jun 5, 2007, at 3:48 PM, Jamis Buck wrote:
>
> Just to clarify: it _is_ legal to _declare_ a task for a non-existant
> or empty role. It just currently raises an exception when you try to
> execute that task, if no servers exist in that role at the time.
>
> As for why that is the case, I suppose it's because I couldn't
> envision a use case for a task with empty roles, and figured that
> more often than not it would indicate a typo on the user's part. (The
> current behavior has actually caught errors in my recipe files
> several times.) You've raised an interesting point, but I wonder if
> you could solve it without resorting to hacking Capistrano. Could you
> just add a check at the beginning of those tasks, which just exited
> the task if there were no matching tasks?
>
> task :something, :roles => %(this that) do
> next if find_servers_for_task(current_task).empty?
> # ...
> end
>
> If that becomes a particularly useful idiom, it could maybe be added
> to Capistrano directly, via an option to tasks, something like this:
>
> task :something, :roles => %(this that), :if_no_servers_match
> => :skip do
> # ...
> end
>
> - Jamis
>
> On Jun 5, 2007, at 4:36 PM, Mathieu wrote:
>
>>
>> Hello,
>>
>> We are currently using CfEngine to deploy our complex application
>> (complex because a lot of different components to be installed and
>> configured according to one or more roles for each host). I ran into
>> so many problems with CfEngine (it might be a good tool, but it is
>> definitely not the tool for our needs). I would like to replace it
>> with Capistrano.
>>
>> I am using Capistrano (1.99.1) to deploy a complex application on a
>> set of hosts. Deploying the application means installing RPM and GEM
>> packages, customized configuration (generated previously, customized
>> according to hosts roles), and creating several directories, crontab
>> entries, etc...
>>
>> I wrote a set of tasks for deploying each set of components
>> (installing dependencies, application components, configuration
>> files, system configuration, etc...). Each task handles one or more
>> roles. All that is pretty standard I think.
>>
>> I started facing a problem when I tried to associate tasks with roles
>> that are not necessarily declared. Capistrano raises an error when
>> declaring a task for a role that is not declared or when declaring an
>> empty role.
>>
>> Our application is installed of a platform which size may greatly
>> differ. We can build a test platform on one single host for instance,
>> or on twenty hosts for a production platform. Some roles that run
>> statistic servers, SIP registrar, etc... are mandatory. Because the
>> combinations are numerous, I wanted to handle them in a simple way: a
>> task linked to a role is executed if at least one host belongs to
>> this role, if not it is just discarded.
>>
>> I am currently patching the Capistrano instance to be able to handle
>> this case:
>>
>> def instanciate_capistrano
>> cap = Capistrano::Configuration.new
>> cap.logger.level = Capistrano::Logger::INFO
>> cap.set(:password) { Capistrano::CLI.password_prompt }
>> cap.load(File.dirname(__FILE__) + "/../lib/recipes.rb")
>>
>> # patch role_list_from to allow empty roles
>> cap.instance_eval do
>> alias orig_role_list_from role_list_from
>> def role_list_from(roles)
>> roles = roles.split(/,/) if String === roles
>> Array(roles).map do |role|
>> role = String === role ? role.strip.to_sym : role
>> role
>> end
>> end
>>
>> alias orig_execute_task execute_task
>> def execute_task(task)
>> orig_execute_task(task) unless find_servers_for_task
>> (task).empty?
>> end
>>
>> end
>> return cap
>> end
>>
>> I was wondering if some of you guys had already faced the same
>> problem, and how you did handle it. Why isn't it allowed to declare a
>> task for a role that doesn't exist?
>>
>> Thanks!
>>
>> Mathieu
>>
>>
>>
>>>
>
>
> >
--~--~---------~--~----~------------~-------~--~----~
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/capistrano
-~----------~----~----~----~------~----~------~--~---