user3481957 user3481957 - 7 months ago 24
Ruby Question

Chef update certain user's .bashrc

I'm trying to update certain users .bashrc JAVA_HOME environment variable after installing JDK. I get this strange error that I don't understand. Here's the block of code in question.

node['etc']['passwd'].each do |user, data|
only_if {data['uid'] > 9000}
jdk_dir_array = Dir.entries('/usr/java/').select {|entry| File.directory? File.join('/usr/java/',entry) and !(entry =='.' || entry == '..') }
jdk_dir_name = jdk_dir_array.shift
file = Chef::Util::FileEdit.new("#{data['dir']}/.bashrc")
file.search_file_replace( /JAVA_HOME=.*/,"JAVA_HOME=/usr/java/#{jdk_dir_name}")
file.write_file
end


The error I'm getting is this:

NoMethodError
-------------
No resource or method named `only_if' for `Chef::Recipe "install_jdk"'


I don't understand why it thinks "only_if" is a method of the recipe when I declare it inside of the node.each block.

i should point out that if I put this in a ruby_block and hardcode the path to a single user's home directory the code works as expected. I'm trying to update multiple users and that's where I'm stumped.

Answer

only_if is a method you use on a resource, not in either a recipe or inside the block of a ruby_block. What you want is something more like like:

node['etc']['passwd'].each do |user, data|
  ruby_block "edit #{user} bashrc" do
  only_if { data['uid'] > 9000 }
  block do
    jdk_dir_array = Dir.entries('/usr/java/').select {|entry| File.directory? File.join('/usr/java/',entry) and !(entry =='.' || entry == '..') }
    jdk_dir_name = jdk_dir_array.shift
    file = Chef::Util::FileEdit.new("#{data['dir']}/.bashrc")
    file.search_file_replace( /JAVA_HOME=.*/,"JAVA_HOME=/usr/java/#{jdk_dir_name}")
    file.write_file
  end
end

I really recommend not doing this though. Check out the line cookbook for a more refined way to approach this, or consider having Chef manage the whole file via a template resource.