Search code examples
chef-infrachef-recipe

How does chef know how to install a package from its package name?


I am new to Chef. I have learnt that Chef provides a declarative interface to resources. Let's say:

I have simple recipe.rb file with the follo line:

package 'foo'

This line is enough for Chef to know how to install the package foo on whichever environment the recipe is running on.

So I run:

chef-apply recipe.rb

My question is..
What does chef do internally to translate the "declarative" recipe into a "procedural" one in context of the package resource? (i.e. what are the steps it takes to convert the declarative recipe command to a series of actions to fetch and install the package)

P.S: The details regarding how Chef solves this problem are interesting because package names across different OS package managers need not be same. What exists in apt index as package foo might exist in yum index as package bar or might not exist at all. And Chef does not impose recipes to be tied to specific OS or package managers. So I am curious how Chef handles translating such declarative statements to apt-get, yum or brew, etc commands when chef-apply is used.


Solution

  • From the Chef documentation on the package resource

    This resource is the base resource for several other resources used for package management on specific platforms. While it is possible to use each of these specific resources, it is recommended to use the package resource as often as possible. For more information about specific resources for specific platforms, see the following topics:

    • apt_package
    • bff_package
    • chef_gem
    • dpkg_package
    • easy_install_package
    • freebsd_package
    • ...

    The package resource delegates to the appropriate OS level package as needed. If the package name is the same between the various OSes, then you're in luck. Chef will figure out which package manager to use and install that package.

    In the case you mentioned, where the package is named foo for apt and bar for yum, you have to add some additional logic.

    case node[:platform]
    when "ubuntu", "debian"
      package "foo" do
        action :install
      end
    when "centos"
      package "bar" do
        action :install
      end
    end
    

    Chef will still handle figuring out which underlying package manager to use, so you don't have to specify apt_package or yum_package resources, but you have to provide the correct name for each platform.