2

I am writing a chef recipe using the below logic:

if grep -q -i "release 6" /etc/redhat-release  
then       
  upload **file1** using cookbook_file resource  
else if grep -q -i "release 7" /etc/redhat-release  
then    
  upload **file2** using cookbook_file resource  
fi

Please let me know how a chef recipe with above logic will look like??
What chef resources can I leverage?

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
meallhour
  • 13,921
  • 21
  • 60
  • 117

3 Answers3

2

Using a cookbook_file resource you're not uploading a file, you're copying it locally as it has benn downloaded with the cookbook on the node (or it can be downloaded 'on-demand', depending on your client.rb configuration.

The files directory in cookbook_file allow to use file_specificity for this exact use case so in your context your recipe would be only:

cookbook_file '/path/to/target' do
   source 'my_source_file'
   action :create
end

And your cookbook files directory would look like this (the file in default will be used when there's no other matching directory, see the full doc in link above):

cookbook/
├── files
│   └── default
│       └── my_source_file
│   └── redhat_6.4
│       └── my_source_file
│   └── redhat_7.1
│       └── my_source_file

If you really want to use only the major version then you can remove the minor in the directory structure and use the Ohai attributes in the source property like this (use double quotes for interpolation of variables):

cookbook_file '/path/to/target' do
   source "#{node[platform]}-#{node[platform_version][/(\d).\d/,1]}/my_source_file"
   action :create
end
Tensibai
  • 15,557
  • 1
  • 37
  • 57
  • additionally you can also pass an array to the source attribute and override chef's file specificity with whatever 'search' algorithm you like. see https://github.com/chef/chef-rfc/blob/master/rfc017-file-specificity.md for more info. – lamont Jan 05 '16 at 22:19
  • @lamont it's covered in the doc, I hope I did give just enough information to drive readers in clicking the link and read the full doc ;) (I.e. I did not said it intentionally ;)) – Tensibai Jan 05 '16 at 22:24
1

I recommend you to use the Ohai automatic attributes to get information of the underlying operating system.

# On all Fedora and RedHat based platforms
if ['fedora', 'rhel'].include?(node['platform_family'])

  if node['platform_version'].to_i == 6
    cookbook_file '/path/to/file1' do
      source 'file1'
    end
    # ...
  elsif node['platform_version'].to_i == 7
    cookbook_file '/path/to/file2' do
      source 'file2'
    end
  end

end

You can also use the Ruby case statement if you prefer:

case node['platform_family']
# On all Fedora and RedHat based platforms
when 'fedora', 'rhel'

  case node['platform_version'].to_i
  when 6
    cookbook_file '/path/to/file1' do
      source 'file1'
    end
    # ...
  when 7
    cookbook_file '/path/to/file2' do
      source 'file2'
    end
  end

end

You can also use a variable to save the file to upload as Vineeth Guna said:

myfile =
  if ['fedora', 'rhel'].include?(node['platform_family']) && node['platform_version'].to_i == 6
    'file1'
  else
    'file2'
  end

cookbook_file "/path/to/#{myfile}" do
  source myfile
end

See the recipe DSL documentation for more information and examples.

Community
  • 1
  • 1
zuazo
  • 5,398
  • 2
  • 23
  • 22
  • 1
    This is a bad pattern, the [`cookbook_file`](https://docs.chef.io/resource_cookbook_file.html#file-specificity) resource already allow to use specific directory for files depending on the platform and platform_version attribute. – Tensibai Jan 05 '16 at 08:55
  • Complement to previous comment not a complete bad pattern as the use of ohai is better than relying on system calls, but defining resources multiples times is usually error prone. – Tensibai Jan 05 '16 at 09:14
  • But you cannot cover this particular use case using the files directory structure because you need to use the full platform version there. I tried to translate the bash example in the question to Chef to show how to make conditional statements without complicating things. – zuazo Jan 05 '16 at 09:34
  • 2
    You can use custom search paths by passing an array to the `source` property, – coderanger Jan 05 '16 at 21:59
-1

As we can use ruby in chef recipes we can leverage it and upload the files as shown in below code

Make sure you have file1, file2 in files directory of your cookbook

file_to_upload = nil
if system("grep -q -i \"release 6\" /etc/redhat-release")
  file_to_upload = <file1_name>
elsif  system("grep -q -i \"release 7\" /etc/redhat-release")
  file_to_upload = <file2_name>
fi

cookbook_file "<directory_where_file_needs_to_be_uploaded>/#{file_to_upload}"
  source file_to_upload
  action :create
end
Vineeth Guna
  • 388
  • 4
  • 10
  • This is a bad pattern, the [`cookbook_file`](https://docs.chef.io/resource_cookbook_file.html#file-specificity) resource already allow to use specific directory for files depending on the platform and platform_version attribute. – Tensibai Jan 05 '16 at 08:54