Manak Wadhwa
Manak Wadhwa

Reputation: 49

How to store array in node object chef?

I am reading a file inside a ruby_block in chef. I am storing each line in an array. I want them to be accessible anywhere within my chef recipe, so i did a bit of research and found out that i can use node object.

The problem is whenever i am using the node object its storing the last line only and not each line.

This is my code. Any suggestions?

ruby_block "name" do
  block do
    CSV.foreach('/tmp/users.txt') do |row|
    node['username']=row
    end
  end
  action :run # see actions section below
end

Okay so this is my code now.

ruby_block 'name' do
  block do
    CSV.foreach('/tmp/users.txt'){ |row| node.run_state['username123'] |= [row] }
  end
end 

directory "/sftp/#{node.run_state['username123']}/incoming" do
  action :create
  recursive true
end

and my outputs of chef-run comes up to be.

directory[/sftp//incoming] action create 
- create new directory /sftp//incoming

Upvotes: 0

Views: 1073

Answers (2)

Tejay Cardon
Tejay Cardon

Reputation: 4223

OK, so your problem is due to the two-stage nature of Chef. You are declaring your directories in the "compile" stage, but you try to do so with data from the inside of your ruby_block, which doesn't execute until the second stage. If your CSV file is not put into place by chef, you could do this:

# notice this is not in a ruby block
CSV.foreach('/tmp/users.txt'){ |row| node.run_state['username123'] |= [row] }

node.run_state['username123'].each do |next_file|
  directory "/sftp/next_file/incoming" do
    action :create
    recursive true
  end
end

If the CSV file is put into place by chef, you'll need to force it to be there before the CSV parsing runs. You MIGHT be able to do this:

cookbook_file 'mycsv file' do
  ...
end.run_action(:create)

at some point prior to your CSV parsing. If that's not an option (for any of several reasons) then you would need to get fancier. At this point you would probably be best-off creating an LWRP.

Upvotes: 1

Tejay Cardon
Tejay Cardon

Reputation: 4223

SEE new answer (didn't want to confuse anyone with the comments)

Two choices. If you really want to use the node, the you need to use an array, which you are not.

ruby_block 'name' do
  block do
    CSV.foreach('/tmp/users.txt'){ |row| node['username'] |= [row] }
  end
end

But, unless you want that info to be stored in the node object on the server, I'd suggest you actually store it in the run_state

ruby_block 'name' do
  block do
    CSV.foreach('/tmp/users.txt'){ |row| node.run_state['username'] |= [row] }
  end
end

This still makes it accessible to the rest of your recipes, but it keeps it out of the node object which will be sent to the chef server at the end of you run.

Upvotes: 2

Related Questions