Chef node attribute definition: define a field by reference other field

225 Views Asked by At

How can I define a ruby Hash by this way?

default['mgmt']['query'] = {
    'default_interval' => {'diff' => 3600, 'snapshot' => 86400 * 7},
    'tables' => {
        'deb_packages' => default_interval,
        'rpm_packages' => default_interval,
        ...
    }
}

EDIT: above code is for Chef recipe's attributes/default.rb

I am looking for a way to define default_interval inside the Hash yet be able to referenced by other field so that the default_interval can be overwritten by other Chef means such as environment json.

That is the reason why I do not choose simply define a global default_interval var.

Currently, I use following definition to represent default_interval

default['mgmt']['query'] = {
    'default_interval' => {'diff' => 3600, 'snapshot' => 86400 * 7},
    'tables' => {
        'deb_packages' => {} # default_interval,
        'rpm_packages' => {} # default_interval,
        ...
    }
}

The empty {} can be overwritten by other chef means such as environment json to change to {diff: 600, snapshot:86400}

Any better cool way?

2

There are 2 best solutions below

4
On BEST ANSWER

That is the reason why I do not choose simply define a global default_interval var.

No need, you can define a local variable.

default['mgmt']['query'] = {
    'default_interval' => (default_interval = {'diff' => 3600, 'snapshot' => 86400 * 7}),
    'tables' => {
        'deb_packages' => default_interval,
        'rpm_packages' => default_interval,
    }
}

This style is not very common in ruby and is guaranteed to raise a few eyebrows, but it does what you want.

6
On

Declare node as

node = Hash.new { |h, k| h[k] = {} }

and your code will just be executed as is, producing a structure you need. The latter is named “hash” in ruby btw.

More info on Hash#new accepting a block.