Controlling ruby_block update status

Hi all,

I just found out that “ruby_block” resource is updated every time and this can’t be controlled. I think this resource type could benefit from ability to control it’s update status from inside block. Use case:

ruby_block “Remove unwanted entries” do
block {
entries = Dir["/foo/bar/*"]
entries.reject! { |e| PRECIOUS_ENTRIES.include?(File.basename(e)) }
entries.each { |e| FileUtils.rm_rf(e) }

  updated_by_last_action !entries.empty?
}

notifies :restart, 'service[foo]'

end

This way notifications will trigger only if there were actual changes.

To implement this, a simple change is required: inside “chef/provider/ruby_block.rb” method #action_create should set updated_by_last_action attribute before running resource block:

  def action_create
    @new_resource.updated_by_last_action(true)
    @new_resource.block.call
Chef::Log.info("#{@new_resource} called, update status is set to #{@new_resource.updated_by_last_action?}")
  end

What do you think?

On Thursday, December 8, 2011 at 9:04 AM, Maxim Kulkin wrote:

Hi all,

I just found out that "ruby_block" resource is updated every time and this can't be controlled. I think this resource type could benefit from ability to control it's update status from inside block. Use case:

...

def action_create
@new_resource.updated_by_last_action(true)
@new_resource.block.call
Chef::Log.info (http://Log.info)("#{@new_resource} called, update status is set to #{@new_resource.updated_by_last_action?}")
end

What do you think?
In a super-pedantic sense, calling Resource#updated_by_last_action more than once is incorrect. The reason this was changed from a simple boolean is so that you can check which resources have been updated at all (say, in a report handler), whereas the notification system decides to fire notifications when the last action updated the resource.

For right now, it's not such a big deal, but when we add more support for storing and querying this info in Chef 11, it could be a problem.

On the other hand, if we forced the user to set Resource#updated_by_last_action, then we're adding more complexity to what's a relatively simple thing right now.

At the moment your use case is probably better served by a LWRP. Thinking out loud, I wonder if something like an "inline LWRP" would be a good balance between the simplicity of ruby_block and the extra effort required for LWRPs--and might also be a nicer way to support the dynamic resource use case.

--
Dan DeLeo

On Dec 8, 2011, at 21:17, Daniel DeLeo wrote:

On Thursday, December 8, 2011 at 9:04 AM, Maxim Kulkin wrote:

Hi all,

I just found out that "ruby_block" resource is updated every time and this can't be controlled. I think this resource type could benefit from ability to control it's update status from inside block. Use case:

...

def action_create
@new_resource.updated_by_last_action(true)
@new_resource.block.call
Chef::Log.info (http://Log.info)("#{@new_resource} called, update status is set to #{@new_resource.updated_by_last_action?}")
end

What do you think?
In a super-pedantic sense, calling Resource#updated_by_last_action more than once is incorrect. The reason this was changed from a simple boolean is so that you can check which resources have been updated at all (say, in a report handler), whereas the notification system decides to fire notifications when the last action updated the resource.

Do not understand the problem and concern on calling updated_by_last_action more than once. I don't see why manipulating this flag from insider resource (or it's provider) is a bad thing? The semantics of "updated_by_last_action" is also still applicable. It's like having a provider action just inside resource itself (as you have mentioned below). I just think that the ruby_block could become such "inline" resource instead of creating another one.

Also, I have another use case: test some condition and fire notifications. E.g. you need to compare timestamp of some file against timestamp of another file and trigger restart of some service. For that I have used "ruby_block" with "only_if" condition and empty block:

ruby_block "Test my file is updated" do
block {}
notifies :restart, 'service[foo]'
only_if "test '/foo/bar' -nt '/var/run/foo.pid'"
end

I don't like the "ruby_block" naming for this, but I do not want to create just another resource for such simple task. But I would like to have ability to skip defining block code:

ruby_block "Test my file is updated" do
notifies :restart, 'service[foo]'
only_if "test '/foo/bar' -nt '/var/run/foo.pid'"
end

For right now, it's not such a big deal, but when we add more support for storing and querying this info in Chef 11, it could be a problem.

On the other hand, if we forced the user to set Resource#updated_by_last_action, then we're adding more complexity to what's a relatively simple thing right now.

The users are not forced to do any extra stuff. If users do not need to control that attribute, it'll work the same way as before.

At the moment your use case is probably better served by a LWRP. Thinking out loud, I wonder if something like an "inline LWRP" would be a good balance between the simplicity of ruby_block and the extra effort required for LWRPs--and might also be a nicer way to support the dynamic resource use case.

My perception is that ruby_block should be expanded to become such "inline LWRP".