2

I'm trying to manage a chef role as below.
In this case the attribute node["customer"]["name"] is an array.
In the recipe I need to get the value of the first element of the array node["customer"]["name"] as "foo".

"customer" => {
    "name" => {
        ["foo"] => {
            "prod" => {
                "apache" => {
                    "listening" => 81
                },
                "database" => {
                    "type" => "postgres"
                }
            },
            "dev" => {
                "apache" => {
                    "listening" => 81
                },
                "database" => {
                    "type" => "postgres"
                }
            }
        }
    }
}

What I have done:

node[:customer][:name].each do |customer|
Chef::Log.info("CONFIGURING --- #{customer}")
end

But unexpectly, the variable "customer" contain the value

INFO: CONFIGURING --- ["[\"foo\"]", {"prod"=>{"apache"=>{"listening"=>81}, "database"=>{"type"=>"postgres"}}, "dev"=>{"apache"=>{"listening"=>81}, "database"=>{"type"=>"postgres"}}}]

instead of just simple value "foo"

How can i get the simple value "foo" instead of the whole recursive hash?

Thanks

Marco Giusti
  • 47
  • 1
  • 9
  • possible duplicate of [How to iterate over a hash in Ruby?](http://stackoverflow.com/questions/1227571/how-to-iterate-over-a-hash-in-ruby) – Tensibai Jun 03 '15 at 09:42

2 Answers2

0
node[:customer][:name].each do |customer,properties|
  Chef::Log.info("CONFIGURING --- #{customer}")
end

You're just using ruby there to iterate over a hash, you have to tell ruby you don't wish to get the full object but just the key and something else to get the rest of the properties.

Tensibai
  • 15,557
  • 1
  • 37
  • 57
  • This seems to be the solution, even if the variable need to be cleaned from " and [] chars – Marco Giusti Jun 03 '15 at 09:56
  • @marcogiusti the values are what the one you provided, if you want to get `["Foo"]` or only `FOO` is your responsibility – Tensibai Jun 03 '15 at 10:59
  • I mean, remove the [] if you don't want it to be taken as an array and you'll get FOO – Tensibai Jun 03 '15 at 11:01
  • in my case i need to manage it as array coz multiple roles binded to the node need to not overwrite themself as "customer" – Marco Giusti Jun 03 '15 at 12:07
  • And ? a hash is just a associative array. here you're not creating an array, you're just saying this entry is `["FOO"]` litteraly as the key. `"names" => {"foo" => {} }; names << {"toto" => {}}` will give you the same as `"names" => { "foo" => {}, "toto" => {}}`. I highly advise you reading about hashes (as the deep-merge done by chef is more or less calls to the `<<` operator at end.). What denotes a hash, is the `{}` for it's value, what denotes an array is the `[]` in it's value. `"name" => { ["toto"] => {}}`is just telling that the first key of names is ["toto"]. – Tensibai Jun 03 '15 at 12:13
  • If you want `name` to be an array it should be `"name" => ["foo" => {}, "toto" => {}]`. and in this case `name[0]`would return "foo" hash, and you'll still have to derive it if you want to get it's name as a key. (kind of nonsense IMHO) – Tensibai Jun 03 '15 at 12:15
  • Using this method, the problem, I assume right now, is impossible to retrieve other attributes as "node[customer][name][foo][prod][apache][listening]" chef give me error as null attribute – Marco Giusti Jun 03 '15 at 12:21
  • @MarcoGiusti Indeed, it will become `node['customer']['name'][0]['prod']['apache']....`. That's why I said you're going the wrong path wishing an array. Please open a new question if there's another problem, but take time to understand hashes and how to iterate over them in ruby. Many community cookbooks already use this syntax, that's a correct starting point to understand how they're accessed and populated. – Tensibai Jun 03 '15 at 12:25
  • Thanks Tensibai for all the help here, I will go deeper as you mentioned. – Marco Giusti Jun 03 '15 at 12:27
-1

One cannot have an array implemented in Chef roles. Chef roles can have only attributes set to some value. For example below should work fine.

"customer" => {
    "name" => "foo"
}
dextren
  • 193
  • 1
  • 1
  • 5