I fixed the Puppet.warn thingie before posting.

Yeah, hm, I thought about doing all thatinside puppetmasterd, but I'm
not sure how this can integrate with passenger. You know,
puppetmasterd assumes it starts the process and then control the
http server, as opposed to having Apache start up and control/run the 
http server and have Apache/passenger dispatch requests to puppet.

I was thinking that one could have a loader class, which can do "the
right thing" if it is supposed to be a standalone puppetmasterd or
an embedded puppetmasterd. As the support for 0.25.x is a lot more 
than this patch (and config.ru is required so the app is recognized 
as an app), I'd think this could wait 'til 0.25.x.
For 0.25.x I've prepared some stuff already, but nothing that works
for now :-/

What do you think?

Thanks,
Christian

* Luke Kanies <[EMAIL PROTECTED]> [080926 23:01]:
> 
> Hmm, I could have sworn I had commentary on this patch, but I can't  
> seem to find anything I disagree with.  I guess it'd be nice to see  
> direct support in puppetmasterd for this.
> 
> It should be pretty straightforward to add support for it using the -- 
> servertype switch, rather than using this config.ru file.
> 
> Otherwise, +1
> 
> On Sep 25, 2008, at 4:31 PM, Christian Hofstaedtler wrote:
> 
> >
> > Tried mailing this 5 times or so but it didn't show up on the list,
> > now trying with the Google Groups web interface...
> >
> > From 39cad0d23fe87baf3f8a591d7884e15b10004407 Mon Sep 17 00:00:00 2001
> > From: Christian Hofstaedtler <[EMAIL PROTECTED]>
> > Date: Wed, 24 Sep 2008 10:07:38 +0200
> > Subject: [PATCH 1/1] Implement a Puppetmaster inside Passenger
> >
> > This consists of a new Puppet::Network::HTTPServer::Rack,
> > plus configuration details for Passenger.
> >
> > Signed-off-by: Christian Hofstaedtler <[EMAIL PROTECTED]>
> > ---
> > ext/passenger/README                   |   63 ++++++++++++++
> > ext/passenger/apache2.conf             |   29 ++++++
> > ext/passenger/config.ru                |   40 +++++++++
> > lib/puppet/network/http_server/rack.rb |  148 ++++++++++++++++++++++++
> > ++++++++
> > 4 files changed, 280 insertions(+), 0 deletions(-)
> > create mode 100644 ext/passenger/README
> > create mode 100644 ext/passenger/apache2.conf
> > create mode 100644 ext/passenger/config.ru
> > create mode 100644 lib/puppet/network/http_server/rack.rb
> >
> > diff --git a/ext/passenger/README b/ext/passenger/README
> > new file mode 100644
> > index 0000000..fcdcb91
> > --- /dev/null
> > +++ b/ext/passenger/README
> > @@ -0,0 +1,63 @@
> > +
> > +PUPPETMASTER INSIDE APACHE & PASSENGER
> > +======================================
> > +
> > +This is about running a puppetmaster inside Apache.
> > +
> > +Please also see the docs at 
> > http://reductivelabs.com/trac/puppet/wiki/UsingPassenger
> > +for further information.
> > +
> > +
> > +WHAT IS IT?
> > +===========
> > +
> > +Passenger [1] (AKA mod_rails or mod_rack) is an Apache 2.x Extension
> > for
> > +serving Rails or Rack applications.
> > +
> > +This extension allows running a puppetmasterd as a Rack application;
> > +it has only been tested with Passenger.
> > +
> > +
> > +SHORT INSTALLATION INSTRUCTIONS
> > +===============================
> > +
> > +Make sure puppetmasterd ran at least once, so the SSL certificates
> > +got set up.
> > +
> > +Install Rack:
> > +  gem install -v 0.4.0 rack
> > +
> > +Install Apache and Passenger:
> > +  apt-get install apache2
> > +  gem install passenger
> > +  passenger-install-apache2-module
> > +  (See the Passenger installation instructions [2] for details.)
> > +
> > +Enable Apache modules:
> > +  a2enmod ssl
> > +  a2enmod headers
> > +
> > +Configure Apache:
> > +  cp apache2.conf /etc/apache2/conf.d/puppetmasterd
> > +  vim /etc/apache2/conf.d/puppetmasterd (replace the server
> > hostnames)
> > +
> > +Install the rack application [3]:
> > +  mkdir -p /usr/share/puppet/rack/puppetmasterd
> > +  mkdir /usr/share/puppet/rack/puppetmasterd/public /usr/share/ 
> > puppet/
> > rack/puppetmasterd/tmp
> > +  cp config.ru /usr/share/puppet/rack/puppetmasterd
> > +  chown puppet /usr/share/puppet/rack/puppetmasterd/config.ru
> > +
> > +Go:
> > +/etc/init.d/apache2 restart
> > +
> > +
> > +
> > +[1] http://www.modrails.com/
> > +
> > +[2] http://www.modrails.com/install.html
> > +
> > +[3] Passenger will not let applications run as root or the Apache
> > user,
> > +instead an implicit setuid will be done, to the user whom owns
> > +config.ru. Therefore, config.ru shall be owned by the puppet user.
> > +
> > +
> > diff --git a/ext/passenger/apache2.conf b/ext/passenger/apache2.conf
> > new file mode 100644
> > index 0000000..6a8a974
> > --- /dev/null
> > +++ b/ext/passenger/apache2.conf
> > @@ -0,0 +1,29 @@
> > +Listen 8140
> > +<VirtualHost *:8140>
> > +   SSLEngine on
> > +   SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
> > +   SSLCertificateFile      /var/lib/puppet/ssl/certs/puppet-
> > server.inqnet.at.pem
> > +   SSLCertificateKeyFile   /var/lib/puppet/ssl/private_keys/puppet-
> > server.inqnet.at.pem
> > +   SSLCertificateChainFile /var/lib/puppet/ssl/ca/ca_crt.pem
> > +   SSLCACertificateFile    /var/lib/puppet/ssl/ca/ca_crt.pem
> > +   # If Apache complains about invalid signatures on the CRL, you can
> > try disabling
> > +   # CRL checking by commenting the next line.
> > +   SSLCARevocationFile     /var/lib/puppet/ssl/ca/ca_crl.pem
> > +   SSLVerifyClient optional
> > +   SSLVerifyDepth  1
> > +   SSLOptions +StdEnvVars
> > +
> > +   # The following client headers allow the same configuration to work
> > with Pound.
> > +   RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
> > +   RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
> > +   RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
> > +
> > +   RackAutoDetect On
> > +   DocumentRoot /usr/share/puppet/rack/puppetmasterd/public/
> > +   <Directory /usr/share/puppet/rack/puppetmasterd/>
> > +           Options None
> > +           AllowOverride None
> > +           Order allow,deny
> > +           allow from all
> > +   </Directory>
> > +</VirtualHost>
> > diff --git a/ext/passenger/config.ru b/ext/passenger/config.ru
> > new file mode 100644
> > index 0000000..8608292
> > --- /dev/null
> > +++ b/ext/passenger/config.ru
> > @@ -0,0 +1,40 @@
> > +# Author: Christian Hofstaedtler <[EMAIL PROTECTED]>
> > +# Copyright (c) 2007 Luke Kanies, 2008 Christian Hofstaedtler
> > +#
> > +# This file is mostly based on puppetmasterd, which is part of
> > +# the standard puppet distribution.
> > +
> > +require 'rack'
> > +require 'puppet'
> > +require 'puppet/network/http_server/rack'
> > +
> > +# startup code from bin/puppetmasterd
> > +Puppet.parse_config
> > +Puppet::Util::Log.level = :info
> > +Puppet::Util::Log.newdestination(:syslog)
> > +# A temporary solution, to at least make the master work for now.
> > +Puppet::Node::Facts.terminus_class = :yaml
> > +# Cache our nodes in yaml.  Currently not configurable.
> > +Puppet::Node.cache_class = :yaml
> > +
> > +# The list of handlers running inside this puppetmaster
> > +handlers = {
> > +   :Status => {},
> > +   :FileServer => {},
> > +   :Master => {},
> > +   :CA => {},
> > +   :FileBucket => {},
> > +   :Report => {}
> > +}
> > +
> > +# Fire up the Rack-Server instance
> > +server = Puppet::Network::HTTPServer::Rack.new(handlers)
> > +
> > +# prepare the rack app
> > +app = proc do |env|
> > +   server.process(env)
> > +end
> > +
> > +# Go.
> > +run app
> > +
> > diff --git a/lib/puppet/network/http_server/rack.rb b/lib/puppet/
> > network/http_server/rack.rb
> > new file mode 100644
> > index 0000000..801c9d1
> > --- /dev/null
> > +++ b/lib/puppet/network/http_server/rack.rb
> > @@ -0,0 +1,148 @@
> > +# Author: Christian Hofstaedtler <[EMAIL PROTECTED]>
> > +# Copyright (c) 2006 Manuel Holtgrewe, 2007 Luke Kanies,
> > +#               2008 Christian Hofstaedtler
> > +#
> > +# This file is mostly based on the mongrel module, which is part of
> > +# the standard puppet distribution.
> > +#
> > +# puppet/network/http_server/mongrel.rb has the following license,
> > +# and is based heavily on a file retrieved from:
> > +# http://ttt.ggnore.net/2006/11/15/xmlrpc-with-mongrel-and-ruby-off-rails/
> > +#
> > +# Permission is hereby granted, free of charge, to any person
> > obtaining
> > +# a copy of this software and associated documentation files (the
> > +# "Software"), to deal in the Software without restriction, including
> > +# without limitation the rights to use, copy, modify, merge, publish,
> > +# distribute, sublicense, and/or sell copies of the Software, and to
> > +# permit persons to whom the Software is furnished to do so, subject
> > to
> > +# the following conditions:
> > +#
> > +# The above copyright notice and this permission notice shall be
> > +# included in all copies or substantial portions of the Software.
> > +#
> > +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> > +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> > +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> > +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> > +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> > +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> > +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> > +# SOFTWARE.
> > +
> > +
> > +require 'puppet'
> > +require 'puppet/network/handler'
> > +require 'puppet/sslcertificates'
> > +
> > +require 'xmlrpc/server'
> > +require 'puppet/network/xmlrpc/server'
> > +require 'puppet/network/http_server'
> > +require 'puppet/network/client_request'
> > +require 'puppet/network/handler'
> > +
> > +require 'resolv'
> > +require 'rack'
> > +
> > +# A handler for a Rack-style puppet(master)d. For the most part, it
> > works
> > +# exactly the same as HTTPServer::Mongrel:
> > +# After checking whether the request itself is sane, the handler
> > forwards
> > +# it to an internal instance of XMLRPC::BasicServer to process it.
> > +module Puppet::Network
> > +   class HTTPServer::Rack
> > +           attr_reader :xmlrpc_server
> > +
> > +           def initialize(handlers)
> > +                   @debug = false
> > +                   if Puppet[:debug]
> > +                           @debug = true
> > +                   end
> > +
> > +                   Puppet.info "Starting Rack server for puppet version 
> > %s" %
> > Puppet.version
> > +                   if Puppet[:name] != "puppetmasterd" then
> > +                           Puppet.warning 'Rack server is not named 
> > "puppetmasterd", this
> > may be not what you want. ($0 = %s)' % $0
> > +                   end
> > +
> > +                   @xmlrpc_server = Puppet::Network::XMLRPCServer.new
> > +                   handlers.each do |name, args|
> > +                           unless handler = 
> > Puppet::Network::Handler.handler(name)
> > +                                   raise ArgumentError, "Invalid handler 
> > %s" % name
> > +                           end
> > +                           h = handler.new(args)
> > +                           @xmlrpc_server.add_handler(handler.interface, h)
> > +                   end
> > +                   Puppet.info "Rack server is waiting to serve requests."
> > +           end
> > +
> > +           # Validate a rack-style request (in env), and run the requested
> > XMLRPC
> > +           # call.
> > +           def process(env)
> > +                   # time to serve a request
> > +                   req = Rack::Request.new(env)
> > +
> > +                   if @debug then
> > +                           Puppet.info "Handling request, details:"
> > +                           env.each do |name, val|
> > +                                   l = "  env: %s ->" % name
> > +                                   l = l + ' %s' % val
> > +                                   Puppet.info l
> > +                           end
> > +                   end
> > +
> > +                   if not req.post? then
> > +                           return [405, { "Content-Type" => "text/html" }, 
> > "Method Not
> > Allowed"]
> > +                   end
> > +                   if req.media_type() != "text/xml" then
> > +                           return [400, { "Content-Type" => "text/html" }, 
> > "Bad Request"]
> > +                   end
> > +                   if req.content_length().to_i <= 0 then
> > +                           return [411, { "Content-Type" => "text/html" }, 
> > "Length
> > Required"]
> > +                   end
> > +
> > +                   body = ''
> > +                   req.body().each { |line| body = body + line }
> > +                   if @debug then
> > +                           Puppet.info "Request Body: %s" % body
> > +                   end
> > +                   if body.size != req.content_length().to_i then
> > +                           if @debug then
> > +                                   Puppet.info "body length didnt match 
> > %d" % body.size
> > +                                   Puppet.info " vs. -> %d" % 
> > req.content_length().to_i
> > +                           end
> > +                           return [400, { "Content-Type" => "text/html" }, 
> > "Bad Request
> > Length"]
> > +                   end
> > +                   info = client_info(env)
> > +                   begin
> > +                           data = @xmlrpc_server.process(body, info)
> > +                           return [200, { "Content-Type" => "text/xml; 
> > charset=utf-8" },
> > data]
> > +                   rescue => detail
> > +                           Puppet.err "Rack: Internal Server Error: 
> > XMLRPC_Server.process
> > problem. Details follow: "
> > +                           detail.backtrace.each { |line|  Puppet.err " 
> > --> %s" % line }
> > +                           return [500, { "Content-Type" => "text/html" }, 
> > "Internal Server
> > Error"]
> > +                   end
> > +           end
> > +
> > +           private
> > +
> > +           def client_info(request)
> > +                   ip = request["REMOTE_ADDR"]
> > +                   # JJM #906 The following dn.match regular expression is 
> > forgiving
> > +                   # enough to match the two Distinguished Name string 
> > contents
> > +                   # coming from Apache, Pound or other reverse SSL 
> > proxies.
> > +                   if dn = request[Puppet[:ssl_client_header]] and 
> > dn_matchdata =
> > dn.match(/^.*?CN\s*=\s*(.*)/)
> > +                           client = dn_matchdata[1].to_str
> > +                           valid = 
> > (request[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
> > +                   else
> > +                           begin
> > +                                   client = Resolv.getname(ip)
> > +                           rescue => detail
> > +                                   Puppet.err "Could not resolve %s: %s" % 
> > [ip, detail]
> > +                                   client = "unknown"
> > +                           end
> > +                           valid = false
> > +                   end
> > +                   info = Puppet::Network::ClientRequest.new(client, ip, 
> > valid)
> > +                   return info
> > +           end
> > +   end
> > +end
> > +
> > --
> > 1.5.4.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
-~----------~----~----~----~------~----~------~--~---

Reply via email to