0

I have two chef recipes I want to run in a defined order. First is the install recipe, then it's the config.

Here is the code invoking the recipes:

  ruby_block "bowbridge_config" do
    block do
      run_context.include_recipe "ids::bowbridge_config"
    end
    action :nothing
  end

  ruby_block "bowbridge_install" do
    block do
      run_context.include_recipe "sap-bowbridge::default"
    end
    notifies :run, 'ruby_block[bowbridge_config]', :delayed
  end

I successfully execute the install recipe before the config recipe but when the config recipe is executing only the prints are being printed.

config recipe code:

  mcaf_lib = find_file "/opt/bowbridge/libAVB*_mcaf.so"
  Chef::Log.info("==> bowbridge_config mcaf_lib is #{mcaf_lib}. Vsi file is #{vsi_file}")
  bb_cfg = File.basename(find_file "/opt/bowbridge/bbvsa*.cfg")
  Chef::Log.info("==> bowbridge_config recipe is triggered")

# Setup bowbridge config file
  directory "/etc/bowbridge" do
  end
  file "/etc/bowbridge/" + bb_cfg do
    owner 'root'
    group 'root'
    mode 0755
    content ::File.open("/opt/bowbridge/" + bb_cfg).read
    action :create
  end
  Chef::Log.info("==> bowbridge_config before link creation")
  link "/lib64/libvsa.so" do
    to "#{mcaf_lib}"
  end

The above code shows this output:

[2017-02-24T11:25:36+00:00] INFO: ruby_block[bowbridge_install] sending run action to ruby_block[bowbridge_config] (delayed) 
[2017-02-24T11:25:36+00:00] INFO: Processing ruby_block[bowbridge_config] action run (ids::default line 82) 
[2017-02-24T11:25:37+00:00] INFO: ==> bowbridge_config recipe is triggered 
[2017-02-24T11:25:37+00:00] INFO: ==> bowbridge_config before link creation 
[2017-02-24T11:25:37+00:00] INFO: ruby_block[bowbridge_config] called

No /etc/bowbridge directory is being created and no link inside /lib64 is created. What could I be doing wrong?

Vladimir
  • 417
  • 5
  • 20
  • If you are not going to add any specific options to a resource, like directory '/etc/bowbridge', you don't have to add the do/end block, just keep something like: `directory '/etc/bowbridge'` – Navarro Feb 24 '17 at 14:59

2 Answers2

1

Move from your actual two ruby block to this:

include_recipe "sap-bowbridge::default"
include_recipe "ids::bowbridge_config"

You'll have the same effect, chef honor the runlist order, and the inclusion order so there's no need for the over complexity of your two ruby_block.

You're actual code will run at converge time, the config recipe running late in the run due to the notification delayed. If that's your need, write a custom_resource instead of tweaking around the runlist.

Tensibai
  • 15,557
  • 1
  • 37
  • 57
  • It honors the runlist order but the compile phase of the bowbridge_config recipe will assign values such as "bb_cfg" which do not exist at the time. This problem is defined here https://coderanger.net/two-pass/ . The code now fails because bb_cfg does not exist and mcaf_lib is empty. – Vladimir Feb 24 '17 at 13:31
  • Of course it doesn't exists in the ruby_block context... As said in the answer, if you need variables from previous recipe, use a custom resource (and maybe lazy on its properties to populate the values). See the link in the answer. – Tensibai Feb 24 '17 at 13:34
  • 1
    (And please, don't do addition of text, text interpolation in double quotes is there for that: `"text #{variable}"`) – Tensibai Feb 24 '17 at 13:35
  • The variables are not part of a previous recipe. They depend on a previous recipe to complete so that they can be assigned correctly. I edited my question to show how I'm assigning them. Thanks for the tip on text interpolation. – Vladimir Feb 24 '17 at 13:42
  • So that's exactly what custom_resource are for. Get a system state/information from the system and act accordingly. Have a llok at the link you'll see it will help you and remove a bunch of hassle. Specially on compile vs converge problems. – Tensibai Feb 24 '17 at 13:45
  • Custom_resource was introduced in Chef at version 12.4 but I'm forced to use 11.18. What are my options? – Vladimir Feb 24 '17 at 13:56
  • @Vladimir using a LWRP (which custom_resource are just an evolution) available since chef 10. Documentation is [here](https://docs-archive.chef.io/release/11-18/custom_resources.html), the main difference being the new syntax is all in one file where the previous was in two different files. You can also have a look at a bunch of cookbooks in https://supermarket.chef.io, there's still a lot of them using LWRP. (and the new syntax is from 12.5 just in case it is not a typo). – Tensibai Feb 24 '17 at 14:30
1

I would not recommend using ruby blocks this way, just add the recipes in the order you want Chef to execute them. In this case:

include_recipe 'sap-bowbridge::default'
include_recipe 'ids::bowbridge_config'

Now, if you need some values to be obtained during execution of the Chef-client, you can use a lazy evaluation. There is plenty of information in Chef website.

As an example, check this:

link '/lib64/libvsa.so' do
    to lazy { find_file '/opt/bowbridge/libAVB*_mcaf.so' }
end

Finally, try to use simple quotes ' ' rather than double " " if there is no need for interpolation or adding variables to the text, also related to this, please use:

"/etc/bowbridge/#{bb_cfg}"

Rather than

"/etc/bowbridge/" + bb_cfg
Navarro
  • 1,284
  • 2
  • 17
  • 40
  • That looks like a neat approach but I need to use #{mcaf_lib} later in a bash template. Can I use "lazy" to assign variables? For example something like, mcaf_lib lazy { find_file '/opt/bowbridge/libAVB*_mcaf.so' } – Vladimir Feb 24 '17 at 15:48
  • It is one of the examples in the link I pasted in my comment. `template '/tmp/canvey_island.txt' do source 'canvey_island.txt.erb' variables( lazy { { :canvey_island => node.run_state['sea_power'] } } ) end` – Navarro Feb 24 '17 at 16:05
  • Thanks @Navarro . Sorry for the bad formatting: `bash 'Extract vsi.properties' do cwd "#{vsi_tmp}" variables( lazy { { :mcaf_lib => Dir['/opt/bowbridge/libAVB*_mcaf.so'][0] } } ) code <<-EOH jar -xvf #{vsi_file} cfg/linux/vsi.properties java -jar #{vsi_file} info -V #{mcaf_lib} -cfg cfg/linux/vsi.properties > /tmp/vsi.out EOH end` The problem I'm now facing is that variables is not a recognized method. I see it's not part of the acceptable bash template. – Vladimir Feb 27 '17 at 08:21
  • Of course it is a non recognized method. There is no '`variables`' option for a `bash resource`, as you can see in [Chef's documentation](https://docs.chef.io/resource_bash.html). Try not to 'bash your way' in Chef and create custom resource/methods for this tasks. – Navarro Feb 27 '17 at 08:31