Search code examples
rubyhttppuppet

Puppet exceptions handling in custom functions (Puppet+Ruby)


I created a puppet function (module Puppet::Parser::Functions newfunction() ) getfromdb it tries to fetch url data from db.net host, updates local cache file and return content of the url.body. In case of failure of http request to the server it uses local cache data file.

In order to implement this I want to catch exceptions in the function:

require "net/http"
require "uri"
    
uri = URI("http://db.net:3013/api/nagios/sets.cfg")
    begin
      puts "here"
      res = Net::HTTP.get_response(uri)
      puts "No here"
    rescue Errno::ECONNREFUSED => e
      puts "http://db.net:3013/api/nagios/sets.cfg " + e
    else
      puts "Fetching: http://db.net:3013/api/nagios/sets.cfg"
    end

Server on the port 3013 is not running. And here what I got in the puppet output:

Info: Scope(Class[ZSX::Service::Monitor]): ------------------ Applying service class z::service::monitor
Info: Scope(Class[Nagios::Server2]): Applying class nagios::server2
here
Error: Evaluation Error: Error while evaluating a Function Call, no implicit conversion of Errno::ECONNREFUSED into String (file: /modules/nagios/manifests/server2.pp, line: 115, column: 13) on node puppet-node.net

While in irb console It behaves different:

irb(main):018:0>     begin
irb(main):019:1*       puts "here"
irb(main):020:1>       res = Net::HTTP.get_response(uri)
irb(main):021:1>       puts "No here"
irb(main):022:1>     rescue Errno::ECONNREFUSED => e
irb(main):023:1>       puts "Could not fetch: http://db.net:3013/api/nagios/sets.cfg " + e
irb(main):024:1>     else
irb(main):025:1*       puts "Fetching: http://db.net:3013/api/nagios/sets.cfg"
irb(main):026:1>     end
here
Could not fetch: http://db.net:3013/api/nagios/sets.cfg Connection refused - connect(2)
=> nil

Why I could not rescue HTTP exceptions in puppet Ruby function?


Solution

  • I will assume that when you test this function in IRB you are using Ruby's MRI (Matz's Ruby Interpreter aka CRuby). When you execute a non-deferred custom Puppet function, it will execute on the Puppet master within a different interpreter: JRuby. In JRuby, exceptions are an object that do not have an overloaded member method for casting into a string like in MRI. Therefore, you see the error message that you cannot implicitly cast the object as a string when executing the code as custom Puppet function.

    However, the exception class object does have a member which allows accessing the error message. This member is the message member. Therefore, you can make a quick update to the code in your custom Puppet function:

    puts "http://db.net:3013/api/nagios/sets.cfg " + e.message
    

    and it should work as per your original intent. Note also that if you defer the function during the Puppet catalog compilation, it will execute with the MRI on all of your clients. This is an alternate fix, but of obviously poor cost/benefit.