summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ext/rack/README70
-rw-r--r--ext/rack/files/apache2.conf36
-rw-r--r--ext/rack/files/config.ru18
-rw-r--r--ext/rack/manifest.pp59
-rw-r--r--lib/puppet/application/puppetmasterd.rb22
-rw-r--r--spec/unit/application/puppetmasterd.rb41
6 files changed, 241 insertions, 5 deletions
diff --git a/ext/rack/README b/ext/rack/README
new file mode 100644
index 000000000..33f958e36
--- /dev/null
+++ b/ext/rack/README
@@ -0,0 +1,70 @@
+
+PUPPETMASTER AS A RACK APPLICATION
+==================================
+
+puppetmaster can now be hosted as a standard Rack application. A proper
+config.ru is provided for this.
+
+For more details about rack, see http://rack.rubyforge.org/ .
+
+Getting started
+===============
+
+You'll need rack installed, version 1.0.0. Older versions are known not
+to work.
+
+
+WEBrick
+-------
+
+WEBrick is currently not supported as a Rack host. You'll be better off
+just running puppetmasterd directly.
+
+
+Mongrel
+-------
+
+If you like Mongrel, and want to replicate wiki:UsingMongrel, you could
+probably start your backend mongrels this way:
+
+cd ext/rack
+for port in `seq 18140 18150`; do
+ rackup --server mongrel --port $port &
+done
+
+rackup is part of the rack gem. Make sure it's in your path.
+
+
+
+Apache with Passenger (aka mod_rails)
+-------------------------------------
+
+Make sure puppetmasterd ran at least once, so the SSL certificates
+got set up.
+
+Requirements:
+ Passenger version 2.2.2 or newer [1]
+ Rack version 1.0.0
+ Apache 2.x
+ SSL Module loaded
+
+Apache configuration snippet is in files/apache2.conf. You need to
+edit it to reflect your servername.
+
+Required puppet.conf settings:
+ [puppetmasterd]
+ ssl_client_header = SSL_CLIENT_S_DN
+ ssl_client_verify_header = SSL_CLIENT_VERIFY
+
+To set up most of the boring stuff, you can use this command:
+ puppet --verbose --modulepath ./ext ext/rack/manifest.pp
+Or use manifest.pp as a starting point for your own module.
+
+Note: 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.
+
+
+[1] http://www.modrails.com/install.html
+
+
diff --git a/ext/rack/files/apache2.conf b/ext/rack/files/apache2.conf
new file mode 100644
index 000000000..88c0f052d
--- /dev/null
+++ b/ext/rack/files/apache2.conf
@@ -0,0 +1,36 @@
+Listen 8140
+<VirtualHost *:8140>
+ SSLEngine on
+ SSLProtocol -ALL +SSLv3 +TLSv1
+ SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP
+
+ SSLCertificateFile /etc/puppet/ssl/certs/squigley.namespace.at.pem
+ SSLCertificateKeyFile /etc/puppet/ssl/private_keys/squigley.namespace.at.pem
+ SSLCertificateChainFile /etc/puppet/ssl/ca/ca_crt.pem
+ SSLCACertificateFile /etc/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, but this is not recommended.
+ SSLCARevocationFile /etc/puppet/ssl/ca/ca_crl.pem
+ SSLVerifyClient optional
+ SSLVerifyDepth 1
+ SSLOptions +StdEnvVars
+
+ # you probably want to tune these settings
+ PassengerHighPerformance on
+ PassengerMaxPoolSize 12
+ PassengerPoolIdleTime 1500
+ # PassengerMaxRequests 1000
+ PassengerStatThrottleRate 120
+ RackAutoDetect Off
+ RailsAutoDetect Off
+
+ DocumentRoot /etc/puppet/rack/public/
+ RackBaseURI /
+ <Directory /etc/puppet/rack/>
+ Options None
+ AllowOverride None
+ Order allow,deny
+ allow from all
+ </Directory>
+</VirtualHost>
+
diff --git a/ext/rack/files/config.ru b/ext/rack/files/config.ru
new file mode 100644
index 000000000..5607bab72
--- /dev/null
+++ b/ext/rack/files/config.ru
@@ -0,0 +1,18 @@
+# a config.ru, for use with every rack-compatible webserver.
+# SSL needs to be handled outside this, though.
+
+# if puppet is not in your RUBYLIB:
+# $:.push('/opt/puppet/lib')
+
+$0 = "puppetmasterd"
+require 'puppet'
+
+# if you want debugging:
+# ARGV << "--debug"
+
+ARGV << "--rack"
+require 'puppet/application/puppetmasterd'
+# we're usually running inside a Rack::Builder.new {} block,
+# therefore we need to call run *here*.
+run Puppet::Application[:puppetmasterd].run
+
diff --git a/ext/rack/manifest.pp b/ext/rack/manifest.pp
new file mode 100644
index 000000000..5145e05c8
--- /dev/null
+++ b/ext/rack/manifest.pp
@@ -0,0 +1,59 @@
+
+file { ["/etc/puppet/rack", "/etc/puppet/rack/public"]:
+ ensure => directory,
+ mode => 0755,
+ owner => root,
+ group => root,
+}
+file { "/etc/puppet/rack/config.ru":
+ ensure => present,
+ source => "puppet:///modules/rack/config.ru",
+ mode => 0644,
+ owner => puppet,
+ group => root,
+}
+file { "/etc/apache2/conf.d/puppetmasterd":
+ ensure => present,
+ source => "puppet:///modules/rack/apache2.conf",
+ mode => 0644,
+ owner => root,
+ group => root,
+ require => [File["/etc/puppet/rack/config.ru"], File["/etc/puppet/rack/public"], Package["apache2"], Package["passenger"]],
+ notify => Service["apache2"],
+}
+
+package { ["rack", "passenger"]:
+ ensure => installed,
+ provider => "gem",
+}
+
+service { "apache2":
+}
+
+case $lsbdistid {
+ "Debian": {
+ package { ["apache2-mpm-worker", "apache2-threaded-dev", "apache2"]:
+ ensure => installed,
+ }
+ file { "/etc/apache2/mods-enabled/ssl.load":
+ ensure => "../mods-available/ssl.load",
+ notify => Service["apache2"],
+ require => Package["apache2"],
+ }
+ Service["apache2"] {
+ require => Package["apache2"],
+ }
+ exec { "/var/lib/gems/1.8/bin/passenger-install-apache2-module --auto":
+ subscribe => Package["passenger"],
+ before => Service["apache2"],
+ require => Package[["passenger", "apache2-threaded-dev"]],
+ }
+ }
+}
+
+notice("You need to manually enable mod_passenger.so for Apache.")
+notice("Usually, you put these config stanzas into httpd.conf:")
+notice(" LoadModule passenger_module /var/lib/gems/1.8/gems/passenger-2.2.2/ext/apache2/mod_passenger.so")
+notice(" PassengerRoot /var/lib/gems/1.8/gems/passenger-2.2.2")
+notice(" PassengerRuby /usr/bin/ruby1.8")
+notice("--------------------------------------------------------")
diff --git a/lib/puppet/application/puppetmasterd.rb b/lib/puppet/application/puppetmasterd.rb
index fe92bca7a..52f33cba9 100644
--- a/lib/puppet/application/puppetmasterd.rb
+++ b/lib/puppet/application/puppetmasterd.rb
@@ -2,6 +2,7 @@ require 'puppet'
require 'puppet/application'
require 'puppet/daemon'
require 'puppet/network/server'
+require 'puppet/network/http/rack' if Puppet.features.rack?
Puppet::Application.new(:puppetmasterd) do
@@ -10,6 +11,9 @@ Puppet::Application.new(:puppetmasterd) do
option("--debug", "-d")
option("--verbose", "-v")
+ # internal option, only to be used by ext/rack/config.ru
+ option("--rack")
+
option("--logdest", "-l") do |arg|
begin
Puppet::Util::Log.newdestination(arg)
@@ -59,8 +63,6 @@ Puppet::Application.new(:puppetmasterd) do
xmlrpc_handlers << :CA
end
- @daemon.server = Puppet::Network::Server.new(:xmlrpc_handlers => xmlrpc_handlers)
-
# Make sure we've got a localhost ssl cert
Puppet::SSL::Host.localhost
@@ -80,11 +82,21 @@ Puppet::Application.new(:puppetmasterd) do
end
end
- @daemon.daemonize if Puppet[:daemonize]
+ unless options[:rack]
+ @daemon.server = Puppet::Network::Server.new(:xmlrpc_handlers => xmlrpc_handlers)
+ @daemon.daemonize if Puppet[:daemonize]
+ else
+ require 'puppet/network/http/rack'
+ @app = Puppet::Network::HTTP::Rack.new(:xmlrpc_handlers => xmlrpc_handlers, :protocols => [:rest, :xmlrpc])
+ end
Puppet.notice "Starting Puppet server version %s" % [Puppet.version]
- @daemon.start
+ unless options[:rack]
+ @daemon.start
+ else
+ return @app
+ end
end
setup do
@@ -96,7 +108,7 @@ Puppet::Application.new(:puppetmasterd) do
Puppet::Util::Log.level = :info
end
- unless Puppet[:daemonize]
+ unless Puppet[:daemonize] or options[:rack]
Puppet::Util::Log.newdestination(:console)
options[:setdest] = true
end
diff --git a/spec/unit/application/puppetmasterd.rb b/spec/unit/application/puppetmasterd.rb
index 5b193ebbf..df6f87895 100644
--- a/spec/unit/application/puppetmasterd.rb
+++ b/spec/unit/application/puppetmasterd.rb
@@ -131,6 +131,14 @@ describe "PuppetMaster" do
@puppetmasterd.run_setup
end
+ it "should set syslog as the log destination if --rack" do
+ @puppetmasterd.options.stubs(:[]).with(:rack).returns(:true)
+
+ Puppet::Log.expects(:newdestination).with(:syslog)
+
+ @puppetmasterd.run_setup
+ end
+
it "should print puppet config if asked to in Puppet config" do
@puppetmasterd.stubs(:exit)
Puppet.settings.stubs(:print_configs?).returns(true)
@@ -255,6 +263,8 @@ describe "PuppetMaster" do
@puppetmasterd.run_preinit
@server = stub_everything 'server'
Puppet::Network::Server.stubs(:new).returns(@server)
+ @app = stub_everything 'app'
+ Puppet::Network::HTTP::Rack.stubs(:new).returns(@app)
Puppet::SSL::Host.stubs(:localhost)
Puppet::SSL::CertificateAuthority.stubs(:ca?)
Process.stubs(:uid).returns(1000)
@@ -325,6 +335,37 @@ describe "PuppetMaster" do
@puppetmasterd.main
end
+ describe "with --rack" do
+ confine "Rack is not available" => Puppet.features.rack?
+
+ it "it should create the app with REST and XMLRPC support" do
+ @puppetmasterd.options.stubs(:[]).with(:rack).returns(:true)
+
+ Puppet::Network::HTTP::Rack.expects(:new).with { |args|
+ args[:xmlrpc_handlers] == [:Status, :FileServer, :Master, :Report, :Filebucket] and
+ args[:protocols] == [:rest, :xmlrpc]
+ }
+
+ @puppetmasterd.main
+ end
+
+ it "it should not start a daemon" do
+ @puppetmasterd.options.stubs(:[]).with(:rack).returns(:true)
+
+ @daemon.expects(:start).never
+
+ @puppetmasterd.main
+ end
+
+ it "it should return the app" do
+ @puppetmasterd.options.stubs(:[]).with(:rack).returns(:true)
+
+ app = @puppetmasterd.main
+ app.should equal(@app)
+ end
+
+ end
+
end
end
end