bartavelle / language-puppet

A library to work with Puppet manifests, test them and eventually replace everything ruby.
BSD 3-Clause "New" or "Revised" License
51 stars 8 forks source link

Support for custom ruby functions #52

Open PierreR opened 10 years ago

PierreR commented 10 years ago

I am wondering how language-puppet is going to deal with custom ruby functions when there are integrated within a module.

Recently puppetlabs-concat for instance has started to replace a bunch of stdlib function with their own version (in order to remove stdlib v4 dependencies). This sounds quite strange to me but well what can we do ;-)

Here is a couple of examples: https://github.com/puppetlabs/puppetlabs-concat/blob/master/manifests/init.pp#L78 https://github.com/puppetlabs/puppetlabs-concat/blob/master/manifests/fragment.pp#L59

puppetlabs-concat is used everywhere so I will end up ignoring many modules (which is quite annoying you can imagine).

Cheers

bartavelle commented 10 years ago

One solution is to rewrite the ruby functions in lua, and put them at the adequate place in the module. It will not work properly with language-puppet in this particular case, as the stdlib functions are built-in, and will take priority over those in the module.

Moreover, what is vanilla puppet supposed to do when there are several custom functions with the same name ?

PierreR commented 10 years ago

They don't have the same name. For instance is_bool is called concat_is_bool.

Isn't possible for language-puppet to find these ruby functions and eval them as ruby code in haskell ? Rewritting all these functions might be tedious.

bartavelle commented 10 years ago

It's entirely possible to have this done. This is however a major undertaking : it would be necessary to write quite a bit of support code in Ruby and write also quite a bit of Haskell ... I thought about it for a while, but never had time to tackle this problem.

jfroche commented 9 years ago

With the current ruby thread would it be possible to evaluate simple ruby function present in a puppet module. Such as this one:

module Puppet::Parser::Functions                                                                                       
  newfunction(:prefix_hash_keys, :type => :rvalue, :doc => <<-EOS                                                      
Take a hash and prefix the hash key with a give value                                                                  
    EOS                                                                                                                
  ) do |args|

    if (args.size != 2) then
      raise(ArgumentError, "prefix_hash_keys(): Wrong number of arguments "+                                           
        "given #{args.size} for 1 or 2.")                                                                              
    end

    collection, prefix = args
    newcollection = Hash.new                                                                                           
    collection.each do |key, item|                                                                                     
      newkey = "#{prefix}-#{key}"
      newitem = item.clone
      newitem["basename"] = key 
      newcollection[newkey] = newitem                                                                                  
    end                                                                                                                
    newcollection
  end
end
bartavelle commented 9 years ago

It is clearly not trivial, as it requires that language-puppet implements a newfunction function that would register this function properly in the interpreter. This is by no means impossible, just tricky.

PierreR commented 9 years ago

I don't know how much work this is and how I could help but it would be quite handy for me too.

For instance I am currently trying to use the puppetdb module from puppetlabs which depends on postgresql where this function is defined.

Of course I can always ignore the module (or rewrite the function in lua I guess) but that's not ideal.

bartavelle commented 9 years ago

There already is a system for external functions that was made for LUA. Note that this doesn't let you encode functions such as ensure_packages as it can't return Resources.

Now the hard part is to write a Ruby stub that will provide all the resources that these functions will require for running. I am unsure on how to start with that as I am not too good with Ruby though. If you can sketch something that works in pure ruby (ie. have a .rb that can load one of the function's file, register this function in some dictionary and run it), it wouldn't be hard for me to interface it with Haskell.

bartavelle commented 9 years ago

The hard part is that all the things that the functions can call must be mocked in advance, or it won't work !