DramaLama
DramaLama

Reputation: 45

Creating multiple config files with chef on a Vagrant VM using Dir and File Ruby classes

So I am creating a VM with vagrant and provision it with chef-client. On a certain step it should look through a directory and create files from .erb templates (around 50 of them).

This is the recipe:

puts("Configuring app...")
Dir.glob('/opt/app/conf/**/*.erb').each do |conf_file|
  conf_file_name = File.basename(conf_file, ".erb")
  conf_file_loc = File.dirname(conf_file)
    template "#{conf_file_loc}/#{conf_file_name}" do
      local true
      source "#{conf_file}"
      action :create
  end
end

So what it does is look for each .erb file in conf directory and in it's child directories, cut of .erb from their name and create a file based on the template.

This code works, I've run it on a manually created VirtualBox VM and had no problem, but when using chef-client provisioning on the Vagrant generated VM this recipe seems to just get skipped. No error messages, no warnings, no logs - nothing. All there is are untouched templates in /opt/app/conf. I can't even see "Configuring app..." string in vagrant output.

I can't use chef-solo provisioning since the same recipe is used for generating both QA environment on our cloud server and a local environment for the devs and I want all of them to be provisioned by our chef server.

Is there any way I could fix it or at least some kind of a logging feature that is not debug level logging for chef?

Vagrant and VBox are on Windows7 machine and I am using chef/centos6.5 box.

Upvotes: 0

Views: 526

Answers (2)

DramaLama
DramaLama

Reputation: 45

Tensibai was spot on the problem - putting the recipe inside a ruby_block solved the issue.

Here is how I edited the recipe:

ruby_block "Create configs for #{node['hostname']}" do
  action :create
  block do
    Dir.glob('opt/app/conf/**/*.erb').each do |conf_file|
      conf_file_name = File.basename(conf_file, ".erb")
      conf_file_loc = File.dirname(conf_file)
        t=Chef::Resource::File::Template.new("#{conf_file_loc}/#{conf_file_name}", run_context)
        t.local true
        t.source conf_file
        t.owner 'user'
        t.group 'root'
        t.run_action :create
    end
  end
end

Thank you very much, you just made at least 40 lazy developers and testers very happy.

Upvotes: 0

Tensibai
Tensibai

Reputation: 15784

I think you're hit by the compile/converge problem. See http://docs.getchef.com/essentials_nodes_chef_run.html

But maybe you're just no having the recipe in your runlist.

If its the first case here is an explanation:

Your Dir.Glob() is done at compile time, at this time your remote_directory (or whatever) creating the templates has not run and the dir is empty.

Easy solution: two run of chef, the second would find the files and create the template resources for each.

Another option would be to encapsulate your code inside a ruby_block so your code will be evaluated at converge time and should work.

Upvotes: 0

Related Questions