Check version using Chef

Solution 1:

Save the version number as a node attribute. This way you have a central store of the versions and you can use the node attribute elsewhere in Chef easily.

Something like:

ruby_block "myapp installed version check" do
  block do
    # file setup
    file = "/var/lib/myapp/node_modules/myapp/package.json"
    raise "File doesn't exist [#{file}]" unless File.exists?( file )

    # get the version line
    versions = open( file ).grep(/version/)
    raise "No versions in file [#{file}]" unless versions.length > 0
    Chef::Log.warn "Too many versions [#{versions.length}] in file [#{file}]" unless versions.length == 1

    # some regex to match your version number
    version = versions[0].match(/\d+\.\d+/).to_s

    # set the attribute
    node.set[:installed][:myapp][:version] = version

    # optionally reload node so attribute is available during this chef-client run
    node.from_file( run_context.resolve_attribute('myapp-cookbook', 'default') )

    # and log it. 
    Chef::Log.info( "myapp version is [#{node[:installed][:myapp][:version]}]" )
  end
end

raise will fail the Chef run with an exception. Use Chef::Log and return instead for the errors that aren't critical and you want to continue on processing recipes.

You can remove the node attribute bits and just log the information so it appears in the chef-client log. This is a bit better than relying on stdout/stderr which disappears when chef-client is not running interactively (i.e as a service). But why just log it when you can have it stored in a central location and query the value across your infra??

note it's generally better to implement the ruby in a library and use it via a custom lightweight resource if you ever think you'll re use the feature for myapp-b.