On Tue, May 17, 2011 at 5:40 AM, Luke Kanies <[email protected]> wrote: > Thanks for the patches. > > How do you expect to use this type? Can you provide some example use cases?
I also wanted the community to give feedback on the name in particular. I'm not convinced 'web' is the best name for this type, but I can see a bunch of utility here. I like the idea of being able to treat REST API calls as Puppet resources... > > I've got a comment below, too. > > On May 16, 2011, at 8:22 PM, Mo Morsi wrote: > >> 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 = {}) > > These methods should really all be in the provider, rather than at the global > level. > >> + 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. >> > > > -- > The trouble with the rat race is that even if you win, you're still a > rat. -- Lily Tomlin > --------------------------------------------------------------------- > Luke Kanies -|- http://puppetlabs.com -|- http://about.me/lak > > > > > -- > 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. > > -- Nigel Kersten Product, Puppet Labs @nigelkersten -- 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.
