[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, upstream, updated. 0.25.5-639-g8f94f35

test branch puppet-dev at googlegroups.com
Wed Jul 14 10:31:47 UTC 2010


The following commit has been merged in the upstream branch:
commit 9acd0b2b6d83881dc529c117637aff63a6c44f8d
Author: Jesse Wolfe <jes5199 at gmail.com>
Date:   Thu Jan 21 17:16:38 2010 -0800

    Feature #3115 REST-ified status()
    
    This patch re-implements the status() remote procedure as a REST interface.
    
    A running server returns key-value pairs, currently the only implemented
    key is "is_alive" which will always be set to true.
    
    Some future tool will consume this by:
    Puppet::Status.indirection.terminus_class = :rest
    Puppet::Status.find('https://puppet:8140/production/status/default')
    
    Now with unit tests.
    plus fixes a typo.
    plus integration test and default security setting.
    plus tests suggested by Brice.
    
    Signed-off-by: Jesse Wolfe <jes5199 at gmail.com>

diff --git a/lib/puppet.rb b/lib/puppet.rb
index f53e664..1fa51c3 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 0000000..f40bbc4
--- /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 0000000..377be89
--- /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 0000000..22e7042
--- /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 13df7c3..6a5ff15 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 635ed1b..01ed412 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 0000000..f587a5a
--- /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 0000000..a9a8321
--- /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 0000000..8f803a2
--- /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 20a51ba..407fc43 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 0000000..b13b246
--- /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

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list