How does chef keep state to skip the recipe from running multiple time

I tried some chef recipes and found that they are intelligent enough
to skip from running when I have run the recipe before.

What is the trick here?

Thanks.

Are you talking between multiple runs or within the same run?

Jeffrey Hulten
Principal Consultant at Automated Labs
jeffh@automatedlabs.com 206-853-5216
Skype: jeffhulten

On Mar 9, 2013, at 9:56 PM, howard chen howachen@gmail.com wrote:

I tried some chef recipes and found that they are intelligent enough
to skip from running when I have run the recipe before.

What is the trick here?

Thanks.

Hi,

On Sun, Mar 10, 2013 at 2:07 PM, Jeffrey Hulten jeffh@automatedlabs.com wrote:

Are you talking between multiple runs or within the same run?

Good question.

I mean in multiple runs.

Thanks.

On Sun, Mar 10, 2013 at 1:34 AM, howard chen howachen@gmail.com wrote:

Hi,

On Sun, Mar 10, 2013 at 2:07 PM, Jeffrey Hulten jeffh@automatedlabs.com wrote:

Are you talking between multiple runs or within the same run?

Good question.

I mean in multiple runs.

Thanks.

Are you sure they're not running? This sounds more like a case of chef
doing what it's supposed to which is not changing something that
doesn't need to be changed. The recipes are likely being run but Chef
says "file hasn't changed. nothing to do" or "service is already
running. nothing to do".

There are some cases where recipes are coded to actually remove
themselves from the run list after one run but that's a rare case and
certainly not in any opscode official cookbook I've ever seen. I've
only used that sparingly.

Howard,

If indeed you are talking about what Lusis is referring to: a recipe that runs one time and removes itself from the run_list, here's a cookbook with that functionality:
http://community.opscode.com/cookbooks/annoyances

The relevant code is in recipes/default.rb:

ruby_block "remove annoyances from run list" do
block do
node.run_list.remove("recipe[annoyances]")
end
only_if { node.run_list.include("recipe[annoyances]") }
end

I actually found myself using similar logic in a bootstrap recipe that I recently wrote. Probably won't use it often, but nice to know about it when you do. Cheers!

:: toddmichael

On Mar 10, 2013, at 12:52 AM, John E. Vincent (lusis) wrote:

On Sun, Mar 10, 2013 at 1:34 AM, howard chen howachen@gmail.com wrote:

Hi,

On Sun, Mar 10, 2013 at 2:07 PM, Jeffrey Hulten jeffh@automatedlabs.com wrote:

Are you talking between multiple runs or within the same run?

Good question.

I mean in multiple runs.

Thanks.

Are you sure they're not running? This sounds more like a case of chef
doing what it's supposed to which is not changing something that
doesn't need to be changed. The recipes are likely being run but Chef
says "file hasn't changed. nothing to do" or "service is already
running. nothing to do".

There are some cases where recipes are coded to actually remove
themselves from the run list after one run but that's a rare case and
certainly not in any opscode official cookbook I've ever seen. I've
only used that sparingly.

On Sun, Mar 10, 2013 at 6:06 AM, Todd Michael Bushnell
todd@toorsecurity.com wrote:

Howard,

If indeed you are talking about what Lusis is referring to: a recipe that
runs one time and removes itself from the run_list, here's a cookbook with
that functionality:
http://community.opscode.com/cookbooks/annoyances

The relevant code is in recipes/default.rb:

ruby_block "remove annoyances from run list" do
block do
node.run_list.remove("recipe[annoyances]")
end
only_if { node.run_list.include("recipe[annoyances]") }
end

I actually found myself using similar logic in a bootstrap recipe that I
recently wrote. Probably won't use it often, but nice to know about it when
you do. Cheers!

:: toddmichael

That's pretty much the exact use case I've used it for in the past.
When you don't have the luxury of a particular action being reliably
idempotent, removing from the run_list is an acceptable middle ground.
In the cases, I've used it, we used it for "first-time" provision
actions where we needed to run something once local only to that node
(in the past case, it was initializing a lucene index or something
iirc) when we first installed the code base. It's not ideal and the
problem really should have been solved upstream by our code but it is
what it is.

For the record, I HIGHLY advise against this in almost every case.
It's really difficult to reason about and you really should figure out
a way to make the operation truly idempotent. Pragmatism wins out
sometimes though :wink:

The hilarious part is that I'm RIGHT in the middle of writing a recipe
that will do the exact thing I'm warning against....