Create ruby variable at chef runtime at specific position in a recipe


#1

I have a recipe in which one resource creates a file. After that I want to use my self written object from libraries to parse this file and extract some values. This values then I want to use in the coming resources. But when I use a ruby_block at the specific position in the recipe to create my object that holds simply the values as a hash, the hash is empty in the next resource. Here is a short example to explain.

package “some_special_package” # Produce the file “key_value_fil” in “/path/to/the/file/i/want/to/parse”

ruby_block “Create my object” do
block do
my_hash_obj_with_the_key_value_pairs = (MyObj.new("/path/to/the/file/i/want/to/parse/key_value_file")).parse_file # returns a hash like: {:mypath => “/etc/some_other_dir”}
end
end

file “touch some other file” do
path "#{my_hash_obj_with_the_key_value_pairs[:mypath]}/file_to_touch"
action :touch
end

I know what is the reason for that. Chef runs in two phases and in the first phase the object “MyObj” is created, but at this point the file does not exist. So the generated hash is empty. In the second phase the access to “my_hash_obj_with_the_key_value_pairs[:mypath]” returns nil and so on. In my last try I used the “node.run_state” variable, but there is the same problem.

So someone how can help me?

Oleg


#2

Yeah that won’t work. You could write the data to the node object which
would be accessible from the later resource but then you have crap in your
node object you probably don’t need. Instead you could write an LWRP that
reads the data and creates the file resource.

KC
On Nov 3, 2012 7:22 AM, oleg.volotov@gmx.de wrote:

I have a recipe in which one resource creates a file. After that I want to
use my self written object from libraries to parse this file and extract
some values. This values then I want to use in the coming resources. But
when I use a ruby_block at the specific position in the recipe to create my
object that holds simply the values as a hash, the hash is empty in the
next resource. Here is a short example to explain.

package “some_special_package” # Produce the file “key_value_fil” in
"/path/to/the/file/i/want/to/parse"

ruby_block “Create my object” do
block do
my_hash_obj_with_the_key_value_pairs =
(MyObj.new("/path/to/the/file/i/want/to/parse/key_value_file")).parse_file

returns a hash like: {:mypath => “/etc/some_other_dir”}

end
end

file “touch some other file” do
path "#{my_hash_obj_with_the_key_value_pairs[:mypath]}/file_to_touch"
action :touch
end

I know what is the reason for that. Chef runs in two phases and in the
first phase the object “MyObj” is created, but at this point the file does
not exist. So the generated hash is empty. In the second phase the access
to “my_hash_obj_with_the_key_value_pairs[:mypath]” returns nil and so on.
In my last try I used the “node.run_state” variable, but there is the same
problem.

So someone how can help me?

Oleg


#3

Create a provider for your file parsing that gets notified by the
package/file that is creating the data. Keep your parsing Class in
libraries. The provider can parse your new files data, setup your
other resources, and run them. This can also setup either a new
namespace or tuck the parsed data into the node object or in run_state
for future access. Depending on the needs you can use LWRP or native
resource/provider. I think you should be able to get away with an
LWRP+Libraries for this tho.

On Sat, Nov 3, 2012 at 7:21 AM, oleg.volotov@gmx.de wrote:

I have a recipe in which one resource creates a file. After that I want to use my self written object from libraries to parse this file and extract some values. This values then I want to use in the coming resources. But when I use a ruby_block at the specific position in the recipe to create my object that holds simply the values as a hash, the hash is empty in the next resource. Here is a short example to explain.

package “some_special_package” # Produce the file “key_value_fil” in “/path/to/the/file/i/want/to/parse”

ruby_block “Create my object” do
block do
my_hash_obj_with_the_key_value_pairs = (MyObj.new("/path/to/the/file/i/want/to/parse/key_value_file")).parse_file # returns a hash like: {:mypath => “/etc/some_other_dir”}
end
end

file “touch some other file” do
path "#{my_hash_obj_with_the_key_value_pairs[:mypath]}/file_to_touch"
action :touch
end

I know what is the reason for that. Chef runs in two phases and in the first phase the object “MyObj” is created, but at this point the file does not exist. So the generated hash is empty. In the second phase the access to “my_hash_obj_with_the_key_value_pairs[:mypath]” returns nil and so on. In my last try I used the “node.run_state” variable, but there is the same problem.

So someone how can help me?

Oleg


#4

Ok I tried it and it works if you write all coming resources in the lwrp.

But I can not use this unfortunately because there still get a lot more resouces that not logically fit together, but still need the same variable (‘my_hash_obj_with_the_key_value_pairs’).
Aktuell habe ich es wie folgt geschrieben:

/recipe/default.rb

Produce the file “key_value_file” in “/path/to/the/file/i/want/to/parse”

package “some_special_package”

mycb_file_parser “extract the key value pairs” do
file "/path/to/the/file/i/want/to/parse/key_value_file"
provider "mycb_extractor"
action :extract
end

/resources/file_parser.rb

actions :extract, :nothing

default_action :nothing

def initialize(*args)
super
@action = :nothing
end

attribute :file, :kind_of => String, :name_attribute => true, :required => true

/providers/extractor.rb

action :extract do
my_hash_obj_with_the_key_value_pairs = (MyObj.new(["#{new_resource.file}"])).parse_file

file “touch some other file” do
path "#{my_hash_obj_with_the_key_value_pairs[:mypath]}/file_to_touch"
action :touch
end
end

But what I want is the variable ‘my_hash_obj_with_the_key_value_pairs’ outside of the provider. If must store them in a data bag or in the node object makes no matter the main thing is I can access to run-time the correct variable. Is it possible to get it like this?:

package “some_special_package”

filled the variable with the hash

mycb_file_parser “extract the key value pairs” do
file "/path/to/the/file/i/want/to/parse/key_value_file"
provider "mycb_extractor"
action :extract
end

file “touch some other file1” do
path "#{[:mypath1]}/file_to_touch1"
action :touch
end

file “touch some other file2” do
path "#{[:mypath2]}/file_to_touch2"
action :touch
end

file “touch some other fileX” do
path "#{[:mypathX]}/file_to_touchX"
action :touch
end

Oleg

-------- Original-Nachricht --------

Datum: Sat, 3 Nov 2012 20:27:57 -0700
Von: Jesse Nelson spheromak@gmail.com
An: chef@lists.opscode.com
Betreff: [chef] Re: Create ruby variable at chef runtime at specific position in a recipe

Create a provider for your file parsing that gets notified by the
package/file that is creating the data. Keep your parsing Class in
libraries. The provider can parse your new files data, setup your
other resources, and run them. This can also setup either a new
namespace or tuck the parsed data into the node object or in run_state
for future access. Depending on the needs you can use LWRP or native
resource/provider. I think you should be able to get away with an
LWRP+Libraries for this tho.

On Sat, Nov 3, 2012 at 7:21 AM, oleg.volotov@gmx.de wrote:

I have a recipe in which one resource creates a file. After that I want
to use my self written object from libraries to parse this file and extract
some values. This values then I want to use in the coming resources. But
when I use a ruby_block at the specific position in the recipe to create my
object that holds simply the values as a hash, the hash is empty in the
next resource. Here is a short example to explain.

package “some_special_package” # Produce the file “key_value_fil” in
"/path/to/the/file/i/want/to/parse"

ruby_block “Create my object” do
block do
my_hash_obj_with_the_key_value_pairs =
(MyObj.new("/path/to/the/file/i/want/to/parse/key_value_file")).parse_file # returns a hash like:
{:mypath => “/etc/some_other_dir”}
end
end

file “touch some other file” do
path "#{my_hash_obj_with_the_key_value_pairs[:mypath]}/file_to_touch"
action :touch
end

I know what is the reason for that. Chef runs in two phases and in the
first phase the object “MyObj” is created, but at this point the file does
not exist. So the generated hash is empty. In the second phase the access to
"my_hash_obj_with_the_key_value_pairs[:mypath]" returns nil and so on. In
my last try I used the “node.run_state” variable, but there is the same
problem.

So someone how can help me?

Oleg