[chef] Re: chef resources inherit not_if and only_if from previous copies


Chronological Thread 
  • From: Adam Jacob < >
  • To:
  • Subject: [chef] Re: chef resources inherit not_if and only_if from previous copies
  • Date: Fri, 19 Feb 2010 14:14:42 -0800

On Thu, Feb 11, 2010 at 4:22 PM, Jeremy Deininger 
< >
 wrote:
> Greetings fellow chefs,
>
> I believe I've found a bug in the way that resources are copied from one to
> the next during a recipe run.  This bug only manifests itself when you are
> re-using a resource with the same name.  My opinion is that only_if and
> not_if should be used to control the flow of actions that you use on the
> current_resource, not inherited from previous resources.  The primary
> example I use is the service "mysql" resource.  Since this service is likely
> to be called multiple times in a recipe with different actions it can be
> confusing when it inherits a conditional from a prior action ..  I've filed
> a bug here: http://tickets.opscode.com/browse/CHEF-894 and I'm pasting an
> example below that's taken from the Rightscale public cookbooks for
> db_mysql.
>
> Do the maintainers approve this change?  Any alternatives or suggestions?
> Right now I have to be really careful with my not/only_ifs and override the
> un-wanted copies to get the behavior I need..
>
> === SNIP from
> http://github.com/rightscale/cookbooks_public/blob/master/cookbooks/db_mysql/recipes/install_mysql.rb#L125
> ===>
>
> service "mysql" do
>   only_if do
>     right_platform = node[:platform] == "ubuntu" &&
>                     (node[:platform_version] == "8.04" ||
>                      node[:platform_version] == "8.10")
>
>     right_platform && node[:db_mysql][:kill_bug_mysqld_safe]
>   end
>
>   action :stop
> end
>
> ruby_block "fix buggy mysqld_safe" do
>   only_if do
>     right_platform = node[:platform] == "ubuntu" &&
>                     (node[:platform_version] == "8.04" ||
>                      node[:platform_version] == "8.10")
>
>     right_platform && node[:db_mysql][:kill_bug_mysqld_safe]
>   end
>   block do
>
>     ...
>     node[:db_mysql][:kill_bug_mysqld_safe] = false
>   end
> end
>
> service "mysql" do
>
>   # override this back to the default for future copies of the resource
>   only_if do true end
>   not_if do ::File.symlink?(node[:db_mysql][:datadir]) end
>   action :stop
> end
>
> ... more recipe code ...
>
> service "mysql" do
>   # override this back to the default for future copies of the resource
>   not_if do false end
>   Chef::Log.info "Attempting to start mysql service"
>   action :start
> end

Hrm - in general, I think of not_if and only_if less as conditional
controls (although they absolutely are that) and more as idempotency
controls.  For example:

service "mysql" do
  only_if do
    right_platform = node[:platform] == "ubuntu" &&

                    (node[:platform_version] == "8.04" ||

                     node[:platform_version] == "8.10")
    right_platform && node[:db_mysql][:kill_bug_mysqld_safe
  end
  action :stop
end

Always creates an entry in the resource collection that wants to stop
service[mysql], regardless of platform.  You could achieve the same
thing with:

if platform?("ubuntu") && (node[:platform_version] == "8.04" ||
node[:platform_version] == "8.10") &&
node[:db_mysql][:kill_bug_mysqld_safe]
  service "mysql" do
    action :stop
  end
end

Which will result in no resource with a stop action being added to the
resource collection at all.

In general that's going to work, assuming your guard is not reliant on
the system state being altered by actually executing the resource
collection.

When not_if/only_if are used to control idempotence, inheritance is
the right thing to do - because the assumption is that the provider in
question isn't smart enough to figure out whether or not the action
should be taken.

So in general, I think it's better to move the guard statement outside
of the not_if/only_if block, and up into a legitimate guard statement,
and have the resource note even appear in the collection.

Adam

-- 
Opscode, Inc.
Adam Jacob, CTO
T: (206) 508-7449 E: 




Archive powered by MHonArc 2.6.16.

§