Reputation: 21406
I am using Chef of AWS OpsWorks. I have a custom attribute JSON like below;
{
"custom_attributes": {
"custom_attribute_1": "default_value"
}
}
and, I can use #{node[:custom_attributes][:custom_attribute_1]}"
to print / use that value anywhere in my recipes. Then, I want to change that value and I can achieve it by mentioning it in default.rb
file inside attributes
directory of my cookbook, like below;
override['custom_attributes']['custom_attribute_1'] = "overridden_value"
Now, if I print / use this attribute, new value will get reflected. This works well.
Lets consider I haven't overridden the value and trying to use a ruby block for this like below;
ruby_block 'test_block' do
block do
node.override['custom_attributes']['custom_attribute_1'] = "overridden_value"
end
action :run
end
log 'message' do
message "attribute value = #{node[:custom_attributes][:custom_attribute_1]}"
level :info
end
Now, if we take a look at log, it will show default_value
instead of overridden_value
. If my understanding is clear, its happening because of compile
and convergence
phases. Can somebody show me how to fix this issue?
Thanks.
EDIT
As per my research, I understand that the attribute assignment is happening at compile phase and ruby block evaluation is happening at converge phase. In that case, can somebody show me how to override / create new attribute using Chef Lazy? Below is a blog I came across;
https://blog.alanthatcher.io/lazy-is-good/
Upvotes: 2
Views: 376
Reputation: 10142
can somebody show me how to override / create new attribute using Chef Lazy?
you can use lazy evaluation
In some cases, the value for a property cannot be known until the execution phase of a Chef Infra Client run. In this situation, using lazy evaluation of property values can be helpful. Instead of a property being assigned a value, it may instead be assigned a code block. The syntax for using lazy evaluation is as follows:
property_name lazy { code_block }
where lazy is used to tell Chef Infra Client to evaluate the contents of the code block later on in the resource evaluation process (instead of immediately) and { code_block } is arbitrary Ruby code that provides the value.
so you might want to use lazy
as follows
log 'message' do
message lazy { "attribute value = #{node[:custom_attributes][:custom_attribute_1]}" }
level :info
end
Upvotes: 1