Chef each loop for each loop

12,801

Solution 1

How I would tackle the problem:

In attributes/default.rb:

default['services']['service1']['port'] = 11001
default['services']['service2']['port'] = 11002
default['services']['service3']['port'] = 11003

OR (alternative syntax):

default['services'] = {
 "service1" => { "port" => 11001 },
 "service2" => { "port" => 11002 },
 "service3" => { "port" => 11003 }
}

In the recipes/default.rb:

node['services'].each do |serv,properties|
  template "/etc/services/conf.d/service-#{serv}.conf" do
    source "service-#{serv}.conf.erb"
    owner 'serviceaccount'
    group 'serviceaccount'
    mode '0644'
    variables(
      :service => serv,
      :ports => properties['port']
    )
  end
end

When iterating over a hash (what node attributes are based on) you can use the |key,values| syntax of ruby to get the key in the first variable and the value (which could be another hash) in the second variable.

Solution 2

I would instead use a hash with the keys as your service names and values as your port numbers. Then you can increment through your hash with the key and the value.

Using your example code, something like:

services = { 'service1' => 11001, 'service2' => 11002, 'service3' => 11003 }

And then in your recipe:

node['recipe']['services'].each do |serv, port|
  template "/etc/services/conf.d/service-#{serv}.conf" do
    source "service-#{serv}.conf.erb"
    owner 'serviceaccount'
    group 'serviceaccount'
    mode '0644'
    variables(
      :service => serv,
      :ports => port
    )
  end
end

It's not very idiomatic chef though.

Share:
12,801
gbaii
Author by

gbaii

Updated on June 04, 2022

Comments

  • gbaii
    gbaii almost 2 years

    I have these arrays

    services=["service1","service2","service3"]
    ports=[11001,11002,11003]
    

    For each element of services I need to assign the correspondent element of ports in an conf.erb file. What I have until now is:

    node['recipe']['services'].each do |serv|
      template "/etc/services/conf.d/service-#{serv}.conf" do
        source "service-#{serv}.conf.erb"
        owner 'serviceaccount'
        group 'serviceaccount'
        mode '0644'
        variables(
          :service => serv,
          :ports => node['services']['ports']
        )
      end
    end
    

    It sounds bad and the result is bad.

    The result should be 3 conf files:

    service-service1.conf:

    service-service1

    port 11001

    service-service2.conf:

    service-service2

    port 11002

    service-service3.conf:

    service-service3

    port 11003

    Any help is appreciated.

    Thank you, Gabriel