Hello Lamont Granquist,
I will try to answer all your questions. Please, let me know if
anything is not clear or I'm wrong. I'm far from being a Chef
expert
Before we begin: I know my solution may not be perfect and certainly
can be improved. But I also think it's not a bad starting point.
On Tue, 26 Nov 2013 11:49:59 -0800
Lamont Granquist lamont@opscode.com wrote:
[...]
Comparing chef:main...zuazo-forks:CHEF-2421-3 · chef/chef · GitHub
[...]
What is your feature supposed to do now? The thing that you wanted
to do was to be able to use the old behavior of why-run mode in order
to be able to figure out if there were any queue'd up converge_by
blocks, but before the blocks were executed, in order to get a kind
of "would_modify_by_action?" check.
My patch does not work exactly like that.
I'll try to explain more or less how it works (linking some code
snippets).
In summary:
-
If resource supports why-run, updated_by_last_action will be
predicted and :befores executed.
-
If resource does not support why-run, it will try to use not_if &
only_if conditionals to know whether to run :before notifications,
printing a warning about it, because may not be the expected
behavior.
I think this sounds simple enough.
To predict updated_by_last_action with why-run (1.), Chef will
run :before notifications inside the #converge_by method, but before
running the converge_by &block.
WhyRun::ConvergeActions#add_action patch: [CHEF-2421(3)] execute other resources BEFORE main resource by zuazo · Pull Request #1145 · chef/chef · GitHub
This works because whenever we call #converge_by,
updated_by_last_action will become true, so, the resource will be run
and all notifications called.
Provider methods that establish this behavior: http://git.io/KFih4w
My solution predicts updated_by_last_action because the logic that
determines its value is outside #converge_by. It is inside each
provider logic, before calling #converge_by. So, if #converge_by is
called, updated_by_last_action will always be true.
You can check the code of any provider to verify this behavior.
If why-run is not supported by the resource (2.), it will run
the :before notifications only if it has only_if/not_if conditions and
they are met.
Provider#run_action patch: [CHEF-2421(3)] execute other resources BEFORE main resource by zuazo · Pull Request #1145 · chef/chef · GitHub
Provider#run_before_notifications: [CHEF-2421(3)] execute other resources BEFORE main resource by zuazo · Pull Request #1145 · chef/chef · GitHub
The latter can be considered as an incomplete imitation of the :before
notifications. But without why-run, I think it's impossible to predict
updated_by_last_action without changing all the providers in the
space and part of the void.
We completely broke the ability
to do that, and as its noted in the ticket its difficult to even
predict in the general case that a resource will be updated before
you call the action.
I know you advised me to use why-run to predict updated_by_last_action,
insinuating that I could use something like the
Provider#resource_updated? or the ConvergeActions#empty? method,
and I started to implement this way. But at the time, I
could not find a clean way to implement that without adding tricky
code, so I finally used a similar but slightly different approach (it
was long ago, so I do not remember in detail).
I think it was a mistake on my part not clarify this. I hope it is
already clear how it works.
So what are the conditions under which you
expect these before notifications to fire?
When why-run is supported, before notifications are fired when the
resource will be updated, and just before calling the converge_by
block.
And why can't you
restructure your run_list so that those resources simply come first
and are idempotent?
Because sometimes you require to change the status of the same
resource multiple times during a chef run.
Some simple examples are mainly related with stopping services, perhaps
before updates, and then starting them again. Something like:
execute "install/update database" do
command " ... "
notifies :stop, "service[database]", :before
notifies :start, "service[database]", :immediately
only_if { ... }
end
execute "install my-webapp" do
command " ... "
notifies :stop, "service[tomcat]", :before
notifies :start, "service[tomcat]", :immediately
only_if { ... }
end
There are some more examples in the ticket.
Why can't you restructure your run_list to use
an after notification?
I think the following comment in the ticket answers this question:
https://tickets.opscode.com/browse/CHEF-2421?focusedCommentId=27014&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-27014
Implementing some :before notifications using :after surely is not
impossible. But IMHO the code can become weird and difficult to
understand in some cases.
This smells like its become a feature-for-the-sake-of-a-feature where
there's other, better, clearer ways to get the job done.
Maybe, but this seems to be a requested feature by some people. This is
not the first time the topic comes out on the list/IRC.
From Sign in to GitHub · GitHub
Generally the code seems overly complicated and i think it still has
vestigial code that was meant to deal with the old approach of trying
to only trigger when the resource would be updated, but before the
converge blocks were invoked. since you simply cannot do that any
more, the replacement feature must be to just hit the before notify
every time the provider is invoked, which is a simpler problem, and i
don't understand the complexity here.
Some of these things are already answered above.
AFAIK, using this solution the provider does NOT call the before
notification every time the provider is invoked. It calls it whenever
the provider will be run, i.e. whenever updated_by_last_action will be
true.
i'm also less sure of the value
of this feature, since you can just structure your run list so that
the resource you are 'notifying' comes first.
You maybe right, but I think it's not so obvious how to implement this
without :before.
is there a compelling
use case where you want to have a recipe follow in the run list but
have a prior recipe's resource notify a resource that comes later?
I think this feature is useful for calling both resources that comes
later and resources that has come before. Some examples are in this
email and in the ticket.
Either way, and above all, thanks for taking time to review this
ticket. The decision on the importance of this feature and whether to
do it my way or not is in your hands. My opinions are clearly
debatable
Regards,
--
Xabier de Zuazo Oteiza
IT System Administrator - Onddo Labs S.L.
www.onddo.com
Public Key = http://www.onddo.com/xabier_zuazo.pub
Key Fingerprint = 8EFA 5B17 7275 5F1F 42B2 26B4 8E18 8B67 9DE1 9468