Include recipe if file exists

All,

Trying to do a conditional include_recipe based on a file existing. Doesn’t
work due to compile/converge stage stuff.

A workaround was suggested here by the folks that should know:
https://tickets.opscode.com/browse/CHEF-5342

However, it doesn’t work, just as someone else responded to the ticket
with. They did not get a reply.

So, just to be clear, as suggested, this does not work:

unless ::File.exists?("/etc/foo/bar")
include_recipe "foo::bar"
end

Doug

Perhaps you misspoke, but you said you want to run a recipe only if a file
exists, right?
Why use unless, then? Of course those three lines wouldn't work since it's
doing "IF /etc/foo/bar NOT exist THEN include_recipe".

On Thu, Oct 8, 2015 at 12:17 PM, Doug Garstang doug@slice.com wrote:

All,

Trying to do a conditional include_recipe based on a file existing.
Doesn't work due to compile/converge stage stuff.

A workaround was suggested here by the folks that should know:
https://tickets.opscode.com/browse/CHEF-5342

However, it doesn't work, just as someone else responded to the ticket
with. They did not get a reply.

So, just to be clear, as suggested, this does not work:

unless ::File.exists?("/etc/foo/bar")
include_recipe "foo::bar"
end

Doug

I was certain the syntax should work since I believe I've used it before,
but I tested it anyway before sending this. Here's what I did:

  1. Set up a blank cookbook
  2. Loaded it up in Vagrant (still empty recipe)
  3. Added a dependency on the git cookbook
    https://supermarket.chef.io/cookbooks/git and reprovisioned the VM (still
    with an empty recipe) -- nothing happened, as expected
  4. Added the following bit to the recipe:

if ::File.exists?('/tmp/gitexists')
include_recipe "git"
end

Then re-ran Vagrant -- again, nothing happened as expected.
5. Logged in to the VM and did a touch /tmp/gitexists
6. Logged out, reprovisioned the VM, this time git did get installed.

So that seems to work.

On Thu, Oct 8, 2015 at 12:39 PM, Fabien Delpierre <
fabien.delpierre@gmail.com> wrote:

Perhaps you misspoke, but you said you want to run a recipe only if a file
exists, right?
Why use unless, then? Of course those three lines wouldn't work since
it's doing "IF /etc/foo/bar NOT exist THEN include_recipe".

On Thu, Oct 8, 2015 at 12:17 PM, Doug Garstang doug@slice.com wrote:

All,

Trying to do a conditional include_recipe based on a file existing.
Doesn't work due to compile/converge stage stuff.

A workaround was suggested here by the folks that should know:
https://tickets.opscode.com/browse/CHEF-5342

However, it doesn't work, just as someone else responded to the ticket
with. They did not get a reply.

So, just to be clear, as suggested, this does not work:

unless ::File.exists?("/etc/foo/bar")
include_recipe "foo::bar"
end

Doug

Similarly, you probably want to package your recipe as an LWRP and then
you can:

unless File::exist?("/etc/foo/bar")
foo "bar" do
action :run
end
end

Or use a not_if, or just bake the File.exist? check into the LWRP.

Since you mention you've had compile/converge issues its probably better
to bake the File.exist? check into the idempotency check of an LWRP and
then you always call the LWRP and the provider code simply does
"return if File.exist?("/etc/foo/bar")" and then the calling code is not
responsible for that check and just calls the LWRP.

On 10/08/2015 09:17 AM, Doug Garstang wrote:

All,

Trying to do a conditional include_recipe based on a file existing.
Doesn't work due to compile/converge stage stuff.

A workaround was suggested here by the folks that should know:
https://tickets.opscode.com/browse/CHEF-5342

However, it doesn't work, just as someone else responded to the ticket
with. They did not get a reply.

So, just to be clear, as suggested, this does not work:

unless ::File.exists?("/etc/foo/bar")
include_recipe "foo::bar"
end

Doug

Classic compile time/run time problems. I am using a ruby_block like this to solve this issue:

ruby_block 'Include at run time' do
  block do
    run_context.include_recipe 'cookbook::recipe'
  end
  only_if { ::File.exist?("/some/file") }
end

I use the following approach in my cookbooks:

include_recipe 'cookbook::recipe' unless ::File.exist?("/some/file")

this can fail the chef run, as the cookbook/recipe inclusion is happening during convergence phase, and chef has no way to ensure that this cookbook is synced (i.e. downloaded from chef server). a safer way will be to also declare the same cookbook as dependency in metadata of the cookbook where this resource is declared.

i still feel this is bit hacky, and and if this is a common requirement (i.e. conditionally include recipe based on the information available during converge time) , debate it and get a public API in place for doing this

hth
ranjib