Search code examples
chef-infracookbook

Chef recipe compilation failure


I am trying to create a chef recipe which depends on tomcat cookbook such as

tomcat_user = node[:tomcat][:user]
tomcat_user_home_folder = node[:etc][:passwd][tomcat_user][:dir]
execute "Install jasper license" do
    command "cp jasperserver.license #{tomcat_user_home_folder}/"
    cwd "#{node["install-jasper-license"]["license-location"]}"
end

When I run sudo chef-client on a node, I get the following error:

================================================================================
Recipe Compile Error in /var/chef/cache/cookbooks/install-jasper-license/recipes/default.rb
================================================================================

NoMethodError
-------------
undefined method `[]' for nil:NilClass

In my opinion this recipe is unable to find node[:etc][:passwd][tomcat_user]. A tomcat user will be installed when tomcat recipe runs. I have also added depends 'tomcat' in metadata.rb of this cookbook. My intent here is to install a file at the home location of the user running tomcat. How do I go about it?


Solution

  • The source of your issue is that the tomcat user is created after you read the value for it which would be set by OHAI.

    To solve this issue, you have to perform 2 steps:

    1. You have to reload the OHAI data after the user was created so that you have access to the data. Normally, the OHAI data (in node["etc"]) is only updated once during one of the first phases of a Chef run.
    2. You have to adapt your recipe so that the account data is only read after it was updated

    You could refactor your code similar to this:

    ########################################################################
    # 1. Reload OHAI data if required
    ohai "reload_passwd" do
      action :nothing
      plugin "passwd"
    end
    
    # Make the installation of the tomcat package notify the reload of the OHAI data
    # This works for all the Linux's but not SmartOS
    tomcat_package = resources(:package => "tomcat#{node["tomcat"]["base_version"]}")
    tomcat_package.notifies :reload, "ohai[reload_passwd]", :immediately
    
    ########################################################################
    # 2. Install license file
    
    ruby_block "Install jasper license" do
      block do
        tomcat_user = node["tomcat"]["user"]
        tomcat_user_home_folder = node["etc"]["passwd"][tomcat_user]["dir"]
    
        File.copy File.join(node["install-jasper-license"]["license-location"], "jasperserver.license"), File.join(tomcat_user_home_folder, "jasperserver.license")
      end
      not_if{ File.exist? File.join(tomcat_user_home_folder, "jasperserver.license") }
    end
    

    The ruby_block ensures that you read the data only during conversion phase after the OHAI data was updated.