Search code examples
chef-infrachef-attributes

pass variables from a chef resouce to other resources in the same chef recipe


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.


Solution

  • 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.