0
votes

I'm writing a library cookbook that contains an LWRP which is supposed to install a tarball and run it as a daemon (the teamcity agent software). As part of this cookbook I want to write a helper method that checks if the software is installed. So I have a helper library with this structure:

    module TeamCity
     module Agent_helper
       def tc_agent_installed?(install_path, archive, version)
         return false unless File.symlink?(install_path)
         return false unless File.basename(File.readlink(install_path)) == "#{archive.match(/^[^\.]*/).to_s}-#{version}"
         return false unless ::File.exist?(::File.join(install_path,'lib','agent.jar'))
         true
       end
     end
    end

My resource looks like this:

    actions :install, :configure
    default_action :install

    attribute :install_path, :kind_of => String, default: '/opt/tcbuild'
...
...
    attribute :version, :kind_of => String, default: '8.1.4'

Here's an example on how my helper method is being called from within the provider

    link target do
      to source
      owner new_resource.user
      group new_resource.group
      not_if { tc_agent_installed?(new_resource.install_path, new_resource.install_archive, new_resource.version) }
    end

Ideally that method should not be getting input parameters but instead be able to pull the attributes from the resource, since the method only serves one purpose. On the above link resource, I want to be able to write a library that can load the current resource's attributes (e.g new_resource.version in the above example). That way I can simply write the guard like this:

not_if { tc_agent_installed? }

I've tried multiple ways of passing the 'version' attribute to that module but haven't gotten it to work.

Passing a node attribute to a helper library is easily achieved, but it's not something that I want to do, since some resource attributes are using default values and aren't getting overriden by a node attribute.

Any ideas? What's the optimal way of passing resource attributes (not node attributes) to a library?

2
Would you mind sharing the part of your provider code which call this library ? I don't get the point where you're stuck - Tensibai
I've added an example of one of the resources in my provider. The purpose of my helper method is to get used in a guard and control the execution of the provider's internal resources. - keftes
I really don't see the need of this guard there... unless your source could be different from the installed version (which would be a non-sense to me). I pretty feel you should split your provider actions to skip the install resources based ont his call instead of guarding each resource one by one. - Tensibai
All in all, I'm pretty sure you're not looking for the proper solution here and more need a refactor of your provider code to call this method only once in it., and so passing the args is less a problem. (For the root case, I don't know any way to avoid passing args, you may just pass the new_resource and access its properties in your helper, but it will be more memory consuming I think) - Tensibai

2 Answers

1
votes

I would put this method in resource itself as a private method. If you don't want to pass attributes inside that method, then it has to know private variables inside resource, so it has to be inside that resource.

0
votes

Just pass the resource object

module TeamCity
  module Agent_helper
    def tc_agent_installed?(resource)
      return false unless File.symlink?(resource.install_path)
      return false unless File.basename(File.readlink(resource.install_path)) == "#{resource.archive.match(/^[^\.]*/).to_s}-#{resource.version}"
      return false unless ::File.exist?(::File.join(resource.install_path,'lib','agent.jar'))
      true
    end
  end
end

link target do
  to source
  owner new_resource.user
  group new_resource.group
  not_if { tc_agent_installed?(new_resource) }
end