diff options
-rw-r--r-- | lib/puppet.rb | 1 | ||||
-rw-r--r-- | lib/puppet/indirector/status.rb | 3 | ||||
-rw-r--r-- | lib/puppet/indirector/status/local.rb | 7 | ||||
-rw-r--r-- | lib/puppet/indirector/status/rest.rb | 5 | ||||
-rw-r--r-- | lib/puppet/network/http/api/v1.rb | 10 | ||||
-rw-r--r-- | lib/puppet/network/rest_authconfig.rb | 1 | ||||
-rw-r--r-- | lib/puppet/status.rb | 20 | ||||
-rwxr-xr-x | spec/integration/bin/puppetmasterd.rb | 155 | ||||
-rwxr-xr-x | spec/unit/indirector/status/rest.rb | 11 | ||||
-rwxr-xr-x | spec/unit/network/rest_authconfig.rb | 1 | ||||
-rw-r--r-- | spec/unit/status.rb | 23 |
11 files changed, 236 insertions, 1 deletions
diff --git a/lib/puppet.rb b/lib/puppet.rb index f53e664be..1fa51c3b4 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -156,6 +156,7 @@ require 'puppet/network' require 'puppet/ssl' require 'puppet/module' require 'puppet/util/storage' +require 'puppet/status' if Puppet[:storeconfigs] require 'puppet/rails' diff --git a/lib/puppet/indirector/status.rb b/lib/puppet/indirector/status.rb new file mode 100644 index 000000000..f40bbc4d8 --- /dev/null +++ b/lib/puppet/indirector/status.rb @@ -0,0 +1,3 @@ +# A stub class, so our constants work. +class Puppet::Indirector::Status +end diff --git a/lib/puppet/indirector/status/local.rb b/lib/puppet/indirector/status/local.rb new file mode 100644 index 000000000..377be89df --- /dev/null +++ b/lib/puppet/indirector/status/local.rb @@ -0,0 +1,7 @@ +require 'puppet/indirector/status' + +class Puppet::Indirector::Status::Local < Puppet::Indirector::Code + def find( *anything ) + return model.new + end +end diff --git a/lib/puppet/indirector/status/rest.rb b/lib/puppet/indirector/status/rest.rb new file mode 100644 index 000000000..22e70429b --- /dev/null +++ b/lib/puppet/indirector/status/rest.rb @@ -0,0 +1,5 @@ +require 'puppet/indirector/status' +require 'puppet/indirector/rest' + +class Puppet::Indirector::Status::Rest < Puppet::Indirector::REST +end diff --git a/lib/puppet/network/http/api/v1.rb b/lib/puppet/network/http/api/v1.rb index 13df7c3d0..6a5ff156a 100644 --- a/lib/puppet/network/http/api/v1.rb +++ b/lib/puppet/network/http/api/v1.rb @@ -34,7 +34,7 @@ module Puppet::Network::HTTP::API::V1 end def indirection2uri(request) - indirection = request.method == :search ? request.indirection_name.to_s + "s" : request.indirection_name.to_s + indirection = request.method == :search ? pluralize(request.indirection_name.to_s) : request.indirection_name.to_s "/#{request.environment.to_s}/#{indirection}/#{request.escaped_key}#{request.query_string}" end @@ -50,12 +50,20 @@ module Puppet::Network::HTTP::API::V1 return method end + def pluralize(indirection) + return "statuses" if indirection == "status" + return indirection + "s" + end + def plurality(indirection) # NOTE This specific hook for facts is ridiculous, but it's a *many*-line # fix to not need this, and our goal is to move away from the complication # that leads to the fix being too long. return :singular if indirection == "facts" + # "status" really is singular + return :singular if indirection == "status" + result = (indirection =~ /s$/) ? :plural : :singular indirection.sub!(/s$/, '') if result diff --git a/lib/puppet/network/rest_authconfig.rb b/lib/puppet/network/rest_authconfig.rb index 635ed1b8d..01ed412cd 100644 --- a/lib/puppet/network/rest_authconfig.rb +++ b/lib/puppet/network/rest_authconfig.rb @@ -15,6 +15,7 @@ module Puppet { :acl => "/certificate/ca", :method => :find, :authenticated => false }, { :acl => "/certificate/", :method => :find, :authenticated => false }, { :acl => "/certificate_request", :method => [:find, :save], :authenticated => false }, + { :acl => "/status", :method => [:find], :authenticated => true }, ] def self.main diff --git a/lib/puppet/status.rb b/lib/puppet/status.rb new file mode 100644 index 000000000..f587a5a2a --- /dev/null +++ b/lib/puppet/status.rb @@ -0,0 +1,20 @@ +require 'puppet/indirector' + +class Puppet::Status + extend Puppet::Indirector + indirects :status, :terminus_class => :local + + attr :status, true + + def initialize( status = nil ) + @status = status || {"is_alive" => true} + end + + def to_pson + @status.to_pson + end + + def self.from_pson( pson ) + self.new( pson ) + end +end diff --git a/spec/integration/bin/puppetmasterd.rb b/spec/integration/bin/puppetmasterd.rb new file mode 100755 index 000000000..a9a8321e9 --- /dev/null +++ b/spec/integration/bin/puppetmasterd.rb @@ -0,0 +1,155 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +describe "puppetmasterd" do + before do + # Get a safe temporary file + file = Tempfile.new("puppetmaster_integration_testing") + @dir = file.path + file.delete + + Dir.mkdir(@dir) + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + Puppet[:certdnsnames] = "localhost" + + @@port = 12345 + + Puppet::SSL::Host.instance_eval{ + @value_cache = {} + } + end + + after { + stop + + Puppet::SSL::Host.ca_location = :none + + system("rm -rf %s" % @dir) + Puppet.settings.clear + } + + def arguments + rundir = File.join(Puppet[:vardir], "run") + @pidfile = File.join(rundir, "testing.pid") + args = "" + args += " --confdir %s" % Puppet[:confdir] + args += " --rundir %s" % rundir + args += " --pidfile %s" % @pidfile + args += " --vardir %s" % Puppet[:vardir] + args += " --certdnsnames %s" % Puppet[:certdnsnames] + args += " --masterport %s" % @@port + args += " --user %s" % Puppet::Util::SUIDManager.uid + args += " --group %s" % Puppet::Util::SUIDManager.gid + args += " --autosign true" + end + + def start(addl_args = "") + Puppet.settings.mkdir(:manifestdir) + Puppet.settings.write(:manifest) do |f| + f.puts { "notify { testing: }" } + end + + args = arguments + " " + addl_args + + bin = File.join(File.dirname(__FILE__), "..", "..", "..", "sbin", "puppetmasterd") + lib = File.join(File.dirname(__FILE__), "..", "..", "..", "lib") + output = %x{/usr/bin/env ruby -I #{lib} #{bin} #{args}}.chomp + end + + def stop + if @pidfile and File.exist?(@pidfile) + pid = File.read(@pidfile).chomp.to_i + Process.kill(:TERM, pid) + 10.times do + break unless File.exist?(@pidfile) + sleep 1 + end + begin + # sigkill and report if process was still running + Process.kill(:KILL, pid) + + raise "Process didn't die from SIGTERM after 10 seconds" + rescue Errno::ESRCH + # process wasn't running. good. + end + + end + end + + it "should create a PID file" do + start + + FileTest.exist?(@pidfile).should be_true + end + + it "should be serving status information over REST" do + start + sleep 6 + + Puppet::Status.indirection.terminus_class = :rest + status = Puppet::Status.find("https://localhost:#{@@port}/production/status/default") + + status.status["is_alive"].should == true + + Puppet::Status.indirection.terminus_class = :local + end + + it "should be serving status information over xmlrpc" do + start + + sleep 6 + + client = Puppet::Network::Client.status.new(:Server => "localhost", :Port => @@port) + + retval = client.status + + retval.should == 1 + end + + it "should exit with return code 0 after parsing if --parseonly is set and there are no errors" do + start(" --parseonly > /dev/null") + sleep(1) + + ps = Facter["ps"].value || "ps -ef" + pid = nil + %x{#{ps}}.chomp.split(/\n/).each { |line| + next if line =~ /^puppet/ # skip normal master procs + if line =~ /puppetmasterd.+--manifest/ + ary = line.split(" ") + pid = ary[1].to_i + end + } + + $?.should == 0 + + pid.should be_nil + end + + it "should exit with return code 1 after parsing if --parseonly is set and there are errors" + + describe "when run for the first time" do + before do + @ssldir = File.join(@dir, 'ssl') + FileUtils.rm_r(@ssldir) if File.exists?(@ssldir) + end + + describe "with noop" do + it "should create its ssl directory" do + File.directory?(@ssldir).should be_false + start(' --noop') + File.directory?(@ssldir).should be_true + end + end + + describe "without noop" do + it "should create its ssl directory" do + File.directory?(@ssldir).should be_false + start + File.directory?(@ssldir).should be_true + end + end + end +end diff --git a/spec/unit/indirector/status/rest.rb b/spec/unit/indirector/status/rest.rb new file mode 100755 index 000000000..8f803a253 --- /dev/null +++ b/spec/unit/indirector/status/rest.rb @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } + +require 'puppet/indirector/status/rest' + +describe Puppet::Indirector::Status::Rest do + it "should be a sublcass of Puppet::Indirector::REST" do + Puppet::Indirector::Status::Rest.superclass.should equal(Puppet::Indirector::REST) + end +end diff --git a/spec/unit/network/rest_authconfig.rb b/spec/unit/network/rest_authconfig.rb index 20a51ba87..407fc43f4 100755 --- a/spec/unit/network/rest_authconfig.rb +++ b/spec/unit/network/rest_authconfig.rb @@ -16,6 +16,7 @@ describe Puppet::Network::RestAuthConfig do { :acl => "/certificate/ca", :method => :find, :authenticated => false }, { :acl => "/certificate/", :method => :find, :authenticated => false }, { :acl => "/certificate_request", :method => [:find, :save], :authenticated => false }, + { :acl => "/status", :method => [:find], :authenticated => true }, ] before :each do diff --git a/spec/unit/status.rb b/spec/unit/status.rb new file mode 100644 index 000000000..b13b246af --- /dev/null +++ b/spec/unit/status.rb @@ -0,0 +1,23 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../spec_helper' + +describe Puppet::Status do + it "should implement find" do + Puppet::Status.find( :default ).should be_is_a(Puppet::Status) + Puppet::Status.find( :default ).status["is_alive"].should == true + end + + it "should default to is_alive is true" do + Puppet::Status.new.status["is_alive"].should == true + end + + it "should return a pson hash" do + Puppet::Status.new.status.to_pson.should == '{"is_alive":true}' + end + + it "should accept a hash from pson" do + status = Puppet::Status.new( { "is_alive" => false } ) + status.status.should == { "is_alive" => false } + end +end |