Adds a new resource type to puppet for web requests and implements a provider of that type using the ruby curl interface provided by the 'curb' rubygem
Signed-off-by: Mo Morsi <[email protected]> --- Local-branch: feature/master/7474 lib/puppet/provider/web_request/curl.rb | 128 +++++++++++++++++++++++++++++++ lib/puppet/type/web_request.rb | 50 ++++++++++++ 2 files changed, 178 insertions(+), 0 deletions(-) create mode 100644 lib/puppet/provider/web_request/curl.rb create mode 100644 lib/puppet/type/web_request.rb diff --git a/lib/puppet/provider/web_request/curl.rb b/lib/puppet/provider/web_request/curl.rb new file mode 100644 index 0000000..479bfd5 --- /dev/null +++ b/lib/puppet/provider/web_request/curl.rb @@ -0,0 +1,128 @@ +require 'curb' +require 'uuid' +require 'fileutils' + +# Helper to invoke the web request w/ curl +def web_request(method, uri, request_params, params = {}) + raise Puppet::Error, "Must specify valid http method and uri" if method.nil? || uri.nil? || method == "" || uri == "" + + curl = Curl::Easy.new + + if params.has_key?(:cookie) + curl.enable_cookies = true + curl.cookiefile = params[:cookie] + curl.cookiejar = params[:cookie] + end + + curl.follow_location = (params.has_key?(:follow) && params[:follow]) + + case(method) + when 'get' + url = uri + url += ";" + request_params.collect { |k,v| "#{k}=#{v}" }.join("&") unless request_params.nil? + curl.url = url + curl.http_get + return curl + + when 'post' + cparams = [] + request_params.each_pair { |k,v| cparams << Curl::PostField.content(k,v) } unless request_params.nil? + curl.url = uri + curl.http_post(cparams) + return curl + + #when 'put' + #when 'delete' + end +end + +# Helper to verify the response +def verify_result(result, verify = {}) + returns = (verify.has_key?(:returns) && !verify[:returns].nil?) ? verify[:returns] : "200" + returns = [returns] unless returns.is_a? Array + unless returns.include?(result.response_code.to_s) + raise Puppet::Error, "Invalid HTTP Return Code: #{result.response_code}, + was expecting one of #{returns.join(", ")}" + end + + if verify.has_key?(:body) && !verify[:body].nil? && !(result.body_str =~ Regexp.new(verify[:body])) + raise Puppet::Error, "Expecting #{verify[:body]} in the result" + end +end + +# Helper to process/parse web parameters +def process_params(request_method, params, uri) + begin + # Set request method and generate a unique session key + session = "/tmp/#{UUID.new.generate}" + + # Invoke a login request if necessary + if params[:login] + login_params = params[:login].reject { |k,v| ['http_method', 'uri'].include?(k) } + web_request(params[:login]['http_method'], params[:login]['uri'], + login_params, :cookie => session, :follow => params[:follow]).close + end + + # Check to see if we should actually run the request + skip_request = !params[:unless].nil? + if params[:unless] + result = web_request(params[:unless]['http_method'], params[:unless]['uri'], + params[:unless]['parameters'], + :cookie => session, :follow => params[:follow]) + begin + verify_result(result, + :returns => params[:unless]['returns'], + :body => params[:unless]['verify']) + rescue Puppet::Error => e + skip_request = false + end + result.close + end + return if skip_request + + # Actually run the request and verify the result + uri = params[:name] if uri.nil? + result = web_request(request_method, uri, params[:parameters], + :cookie => session, :follow => params[:follow]) + verify_result(result, + :returns => params[:returns], + :body => params[:verify]) + result.close + + # Invoke a logout request if necessary + if params[:logout] + logout_params = params[:login].reject { |k,v| ['http_method', 'uri'].include?(k) } + web_request(params[:logout]['http_method'], params[:logout]['uri'], + logout_params, :cookie => session, :follow => params[:follow]).close + end + + rescue Exception => e + raise Puppet::Error, "An exception was raised when invoking web request: #{e}" + + ensure + FileUtils.rm_f(session) if params[:logout] + end +end + +# Puppet provider definition +Puppet::Type.type(:web_request).provide :curl do + desc "Use curl to access web resources" + + def get + @uri + end + + def post + @uri + end + + def get=(uri) + @uri = uri + process_params('get', @resource, uri) + end + + def post=(uri) + @uri = uri + process_params('post', @resource, uri) + end +end diff --git a/lib/puppet/type/web_request.rb b/lib/puppet/type/web_request.rb new file mode 100644 index 0000000..d95e286 --- /dev/null +++ b/lib/puppet/type/web_request.rb @@ -0,0 +1,50 @@ +Puppet::Type.newtype(:web_request) do + @doc = "Issue a request via the world wide web" + + newparam :name + + newproperty(:get) do + desc "Issue get request to the specified uri" + # TODO valid value to be a uri + end + + newproperty(:post) do + desc "Issue get request to the specified uri" + # TODO valid value to be a uri + end + + # TODO implement + #newproperty(:delete) + #newproperty(:put) + + newparam(:parameters) do + desc "Hash of parameters to include in the web request" + end + + newparam(:returns) do + desc "Expected http return codes of the request" + defaultto "200" + # TODO validate value(s) is among possible valid http return codes + end + + newparam(:follow) do + desc "Boolean indicating if redirects should be followed" + newvalues(:true, :false) + end + + newparam(:verify) do + desc "String to verify as being part of the result" + end + + newparam(:login) do + desc "Login parameters to be used if a login is required before making the request" + end + + newparam(:logout) do + desc "Logout parameters to be used if a logout is requred after making the request" + end + + newparam(:unless) do + desc "Do not run request if the request specified here succeeds" + end +end -- 1.7.2.3 -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.
