0

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.

Sam2022
  • 9
  • 2

1 Answers1

0

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:

  • Compile
  • Converge

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.

seshadri_c
  • 6,906
  • 2
  • 10
  • 24
  • Hi @seshadri_c, unfortunately I run to the same error. I tried to workaround the issue to use ruby_block resource instead of http_request resource and use rest-client library, I could install it successfully using the following commands: ´gem install rest-client` and `chef gem install rest-client` but when I run kitchen converge to test it, I got this error: ``` – Sam2022 May 19 '22 at 08:57
  • `` # chef -vChef Workstation version: 21.5.462 Chef Infra Client version: 17.1.35 Chef InSpec version: 4.37.20 Chef CLI version: 5.1.0 Chef Habitat version: 1.6.319 Test Kitchen version: 2.11.2 Cookstyle version: 7.13.0 * chef_gem[rest-client] action install ====== Error executing action install on resource 'chef_gem[rest-client]' =============== NameError: uninitialized constant Custom resource variable from cookbook work::RestClient ``` – Sam2022 May 19 '22 at 10:34
  • You don't need any `ruby_block` to run Ruby code in the cookbooks. You can put it directly outside any resource like I've done. In my test with the above example, I'm able to access the `var`. – seshadri_c May 19 '22 at 11:42
  • Thank you so much @seshadri_c, I coded them directly without `ruby_block`, but as I see the variable `var` value did not pass to `http_request` and I got the same error `NameError: uninitialized constant #>::var ` – Sam2022 May 19 '22 at 12:52
  • Variables that start with capitals are [Ruby constants](https://www.rubyguides.com/2017/07/ruby-constants/#:~:text=What%20is%20a%20constant%20in,prevent%20you%20from%20changing%20them.). Please try with lower case `v` as I have in my example. – seshadri_c May 19 '22 at 16:24