I'm new to Chef and Ruby, I'm very confused how to handle variables in Chef, and I am trying to pass a variable [Var] from ruby_block resource to http_request resource and assign the [Var] value to the value in "value":"#{Var}"
in the chef recipe [customer.rb] as shown in the code below and I got an error.
[Var.js] is a json file and contains a round 100 lines of code. I want to pass the content of this file to a variable [Var] and call this variable to update some configuration of the website [http://localhost:6000/Master/endpoint_1_in/set]
directory 'work' do
owner 'root'
group 'root'
mode '0775'
recursive true
action :create
end
bash 'Extract customer Package' do
cwd '/work'
code <<-EOH
curl -L --header "PRIVATE-TOKEN: XXXXXXXXXXXXXX" "https://www.company.sm/api/v4/projects/44/packages/generic/customer/1.0.0-customer/customer.tar.gz" > /work/customer.tar.gz
tar xzf customer.tar.gz
EOH
end
ruby_block 'Read customer file into Var variable' do
block do
if File.exists?("/work/customer/Var.js")
Var = IO.read("/work/customer/Var.js")
end
end
end
http_request 'cusromer update' do
action :put
url 'http://localhost:6000/Master/endpoint_1_in/set'
message ({
"moduleId" => "endpoint_1_in",
"moduleType" => "ENDPOINT_1_IN",
"options" => [
{
"key": "somename.text",
"value":"#{Var}"
}
],
}.to_json)
headers({'Authorization' => "Basic #{basicauth}", 'Content-Type' => 'application/json;charset=utf-8' })
retries 10
retry_delay 30
end
and the error I got is
Installing cookbook gem dependencies:
Compiling cookbooks...
Loading Chef InSpec profile files:
Loading Chef InSpec input files:
Loading Chef InSpec waiver files:
================================================================================
Recipe Compile Error in /tmp/kitchen/cache/cookbooks/clinic/recipes/customer.rb
================================================================================
NameError
---------
uninitialized constant #<Class:#<Chef::Recipe:0x0000000002bac870>>::Var
Cookbook Trace: (most recent call first)
----------------------------------------
Relevant File Content:
----------------------
/tmp/kitchen/cache/cookbooks/clinic/recipes/customer.rb:
64: url 'http://localhost:6000/Master/endpoint_1_in/set'
65: message ({
66: "moduleId" => "endpoint_1_in",
67: "moduleType" => "ENDPOINT_1_IN",
68: "options" => [
69: {
70: "key": "somename.text",
71>> "value":"#{Var}"
72: }
73: ],
74:
75: }.to_json)
System Info:
------------
chef_version=17.10.3
platform=ubuntu
platform_version=20.04
ruby=ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux]
program_name=/opt/chef/bin/chef-client
executable=/opt/chef/bin/chef-client
Running handlers:
[2022-05-13T16:25:57+00:00] ERROR: Running exception handlers
Running handlers complete
[2022-05-13T16:25:57+00:00] ERROR: Exception handlers complete
Infra Phase failed. 0 resources updated in 02 seconds
[2022-05-13T16:25:57+00:00] FATAL: Stacktrace dumped to /tmp/kitchen/cache/chef-stacktrace.out
[2022-05-13T16:25:57+00:00] FATAL: ---------------------------------------------------------------------------------------
[2022-05-13T16:25:57+00:00] FATAL: PLEASE PROVIDE THE CONTENTS OF THE stacktrace.out FILE (above) IF YOU FILE A BUG REPORT
[2022-05-13T16:25:57+00:00] FATAL: ---------------------------------------------------------------------------------------
[2022-05-13T16:25:57+00:00] FATAL: NameError: uninitialized constant #<Class:#<Chef::Recipe:0x0000000002bac870>>::Var
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>> Converge failed on instance <default-ubuntu-2004>. Please see .kitchen/logs/default-ubuntu-2004.log for more details
>>>>>> ----------------------
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try runn
I spent 2 weeks to solve it I could not. If there is workaround to do it, please help me.
Since you are running some Ruby code to get the file contents, you can even do it outside Chef resources. Something like:
if File.exists?("/work/customer/Var.js")
var = File.read("/work/customer/Var.js")
end
http_request 'cusromer update' do
action :put
# rest of code
end
Note that I've used var
with lower case v
.
Explanation:
The chef-client goes through several phases during the run. The two relevant for this answer are:
All variable and resources are compiled and assignments happen in the compile phase. So var
remains unassigned as there is no definition in for it in compile phase. Whereas ruby_block
and http_request
run in the converge phase.