Moving all files into a consolidated trunk. All tests pass except the known-failing certificate test, but there appear to be some errors that are incorrectly not resulting in failurs. I will track those down ASAP.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@576 980ebf18-57e1-0310-9a29-db15c13687c0
This commit is contained in:
Родитель
e87eb58ce8
Коммит
6029ef7812
|
@ -0,0 +1,2 @@
|
|||
This entire repository is under the GNU Public License. See www.gnu.org
|
||||
for a copy.
|
|
@ -0,0 +1,22 @@
|
|||
$Id$
|
||||
|
||||
This is what you need to get puppet running:
|
||||
|
||||
-- Check you have Ruby version 1.8.2 or later
|
||||
You can download it from
|
||||
ftp://ftp.ruby-lang.org/pub/ruby/ruby-1.8.2.tar.gz
|
||||
Un tar it, then: ./configure; make; make install
|
||||
|
||||
-- http://reductivelabs.com/downloads/facter/facter-1.0.tgz
|
||||
A library that puppet needs to run. Un tar it, and calling
|
||||
'ruby install.rb' file should successfully install it; let
|
||||
me know if it doesn't. Otherwise, you can just set RUBYLIB
|
||||
to contain its lib directory.
|
||||
|
||||
-- Install puppet
|
||||
Run 'ruby install.rb' or add the 'lib/' directory to your RUBYLIB path.
|
||||
Documentation can be found online at
|
||||
http://reductivelabs.com/projects/puppet/documentation/
|
||||
|
||||
-- After that, you should be able to go into test/ and run ./test,
|
||||
or run 'bin/puppet' on whichever puppet config files you want.
|
|
@ -0,0 +1,4 @@
|
|||
$Id$
|
||||
|
||||
* Syntax for configuration of types (e.g., search path for Services)
|
||||
* Get file parsing working in the language
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/ruby -w
|
||||
|
||||
#--------------------
|
||||
# the puppet client
|
||||
#
|
||||
# $Id$
|
||||
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/openssl'
|
||||
require 'getoptlong'
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
check = false
|
||||
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--debug":
|
||||
when "--check":
|
||||
when "--help":
|
||||
puts "There is no help yet"
|
||||
exit
|
||||
else
|
||||
puts "Invalid option '#{opt}'"
|
||||
exit(10)
|
||||
end
|
||||
}
|
||||
|
||||
Puppet[:logdest] = :console
|
||||
Puppet[:loglevel] = :info
|
||||
|
||||
rootcert = Puppet[:rootcert]
|
||||
rootkey = Puppet[:rootkey]
|
||||
rootkey = Puppet[:rootkey]
|
||||
|
||||
unless rootcert
|
||||
raise "config unset"
|
||||
end
|
||||
|
||||
#mkcertsdir(File.basename(rootcert))
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/ruby -w
|
||||
|
||||
#--------------------
|
||||
# accept and serve files
|
||||
#
|
||||
# $Id$
|
||||
|
||||
require 'getoptlong'
|
||||
require 'puppet/filebucket'
|
||||
|
||||
#[ "--size", "-s", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
result = GetoptLong.new(
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--help"
|
||||
puts "There is no help yet"
|
||||
exit
|
||||
else
|
||||
raise "Invalid option '#{opt}'"
|
||||
end
|
||||
}
|
||||
|
||||
begin
|
||||
server = FileBucket::BucketWebserver.new(
|
||||
:Bucket => File.expand_path("~/.puppet/bucket"),
|
||||
:Debug => true,
|
||||
:Port => 8080
|
||||
)
|
||||
trap(:INT) { server.shutdown }
|
||||
server.start
|
||||
#server = FileBucket::BucketServer.new(
|
||||
# :Bucket => File.expand_path("~/.puppet/bucket")
|
||||
#)
|
||||
rescue => detail
|
||||
$stderr.puts detail
|
||||
exit(1)
|
||||
end
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/ruby -w
|
||||
|
||||
#
|
||||
# = Synopsis
|
||||
#
|
||||
# Run a stand-alone +puppet+ script.
|
||||
#
|
||||
# = Usage
|
||||
#
|
||||
# puppet [-V|--version] [-d|--debug] [-v|--verbose] [-l|--logfile <file>] [-h|--help] <file>
|
||||
#
|
||||
# = Description
|
||||
#
|
||||
# This is the standalone +puppet+ execution script; use it to execute
|
||||
# individual scripts that you write. If you need to execute site-wide
|
||||
# scripts, use +puppetd+ and +puppetmasterd+.
|
||||
#
|
||||
# = Options
|
||||
#
|
||||
# debug::
|
||||
# Enable full debugging.
|
||||
#
|
||||
# help::
|
||||
# Print this help message
|
||||
#
|
||||
# logfile::
|
||||
# Where to send messages. Defaults to sending messages to the console.
|
||||
#
|
||||
# = Example
|
||||
#
|
||||
# puppet -l /tmp/script.log script.pp
|
||||
#
|
||||
# = Author
|
||||
#
|
||||
# Luke Kanies
|
||||
#
|
||||
# = Copyright
|
||||
#
|
||||
# Copyright (c) 2005 Reductive Labs, LLC
|
||||
# Licensed under the Gnu Public License
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/server'
|
||||
require 'puppet/client'
|
||||
require 'getoptlong'
|
||||
|
||||
$haveusage = true
|
||||
|
||||
begin
|
||||
require 'rdoc/usage'
|
||||
rescue
|
||||
$haveusage = false
|
||||
end
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--version", "-V", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--logfile", "-l", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
debug = false
|
||||
verbose = false
|
||||
logfile = false
|
||||
|
||||
begin
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--version"
|
||||
puts "%s" % Puppet.version
|
||||
exit
|
||||
when "--help"
|
||||
if $haveusage
|
||||
RDoc::usage && exit
|
||||
else
|
||||
puts "No help available unless you have RDoc::usage installed"
|
||||
exit
|
||||
end
|
||||
when "--verbose"
|
||||
verbose = true
|
||||
when "--debug"
|
||||
debug = true
|
||||
when "--logfile"
|
||||
logfile = arg
|
||||
else
|
||||
$stderr.puts "Invalid option '#{opt}'"
|
||||
Rdoc::usage(1,'usage')
|
||||
end
|
||||
}
|
||||
rescue GetoptLong::InvalidOption => detail
|
||||
RDoc::usage(1,'usage')
|
||||
end
|
||||
|
||||
if debug
|
||||
Puppet[:loglevel] = :debug
|
||||
elsif verbose
|
||||
Puppet[:loglevel] = :info
|
||||
end
|
||||
|
||||
if logfile
|
||||
Puppet[:logdest] = logfile
|
||||
end
|
||||
|
||||
begin
|
||||
server = Puppet::Master.new(
|
||||
:File => ARGV.shift,
|
||||
:Local => true
|
||||
)
|
||||
rescue => detail
|
||||
$stderr.puts detail
|
||||
exit(1)
|
||||
end
|
||||
|
||||
begin
|
||||
client = Puppet::Client.new(
|
||||
:Server => server
|
||||
)
|
||||
rescue => detail
|
||||
$stderr.puts detail
|
||||
exit(1)
|
||||
end
|
||||
|
||||
begin
|
||||
client.getconfig
|
||||
rescue => detail
|
||||
$stderr.puts detail
|
||||
exit(1)
|
||||
end
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/ruby -w
|
||||
|
||||
#--------------------
|
||||
# the puppet client
|
||||
#
|
||||
# $Id$
|
||||
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/sslcertificates'
|
||||
require 'getoptlong'
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--ssldir", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--list", "-l", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--sign", "-s", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--all", "-a", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--cadir", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--generate", "-g", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
mode = nil
|
||||
all = false
|
||||
generate = nil
|
||||
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--help"
|
||||
puts "There is no help yet"
|
||||
exit
|
||||
when "--list"
|
||||
mode = :list
|
||||
when "--sign"
|
||||
mode = :sign
|
||||
when "--all"
|
||||
all = true
|
||||
when "--verbose"
|
||||
Puppet[:loglevel] = :info
|
||||
when "--debug"
|
||||
Puppet[:loglevel] = :debug
|
||||
when "--generate"
|
||||
generate = arg
|
||||
mode = :generate
|
||||
when "--cadir"
|
||||
Puppet[:cadir] = arg
|
||||
when "--ssldir"
|
||||
Puppet[:ssldir] = arg
|
||||
else
|
||||
puts "Invalid option '#{opt}'"
|
||||
exit(10)
|
||||
end
|
||||
}
|
||||
|
||||
ca = Puppet::SSLCertificates::CA.new()
|
||||
|
||||
unless mode
|
||||
$stderr.puts "You must specify --list or --sign"
|
||||
exit(12)
|
||||
end
|
||||
|
||||
hosts = ca.list
|
||||
unless hosts.length > 0 or mode == :generate
|
||||
Puppet.info "No waiting requests"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
case mode
|
||||
when :list
|
||||
puts hosts.join("\n")
|
||||
when :sign
|
||||
unless ARGV.length > 0 or all
|
||||
$stderr.puts(
|
||||
"You must specify to sign all certificates or you must specify hostnames"
|
||||
)
|
||||
exit(24)
|
||||
end
|
||||
|
||||
unless all
|
||||
hosts = hosts.find_all { |host|
|
||||
ARGV.include?(host)
|
||||
}
|
||||
end
|
||||
|
||||
hosts.each { |host|
|
||||
begin
|
||||
csr = ca.getclientcsr(host)
|
||||
rescue => detail
|
||||
$stderr.puts "Could not retrieve request for %s: %s" % [host, detail]
|
||||
end
|
||||
|
||||
begin
|
||||
ca.sign(csr)
|
||||
rescue => detail
|
||||
$stderr.puts "Could not sign request for %s: %s" % [host, detail]
|
||||
end
|
||||
|
||||
begin
|
||||
ca.removeclientcsr(host)
|
||||
rescue => detail
|
||||
$stderr.puts "Could not remove request for %s: %s" % [host, detail]
|
||||
end
|
||||
}
|
||||
when :generate
|
||||
# we need to generate a certificate for a host
|
||||
unless ARGV.length > 0
|
||||
$stderr.puts "You must specify hosts to generate certs for"
|
||||
exit(84)
|
||||
end
|
||||
ARGV.each { |host|
|
||||
puts "Generating certificate for %s" % host
|
||||
cert = Puppet::SSLCertificates::Certificate.new(
|
||||
:name => host
|
||||
)
|
||||
cert.mkcsr
|
||||
signedcert, cacert = ca.sign(cert.csr)
|
||||
|
||||
cert.cert = signedcert
|
||||
cert.cacert = cacert
|
||||
cert.write
|
||||
}
|
||||
else
|
||||
$stderr.puts "Invalid mode %s" % mode
|
||||
exit(42)
|
||||
end
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
#--------------------
|
||||
# the puppet client
|
||||
#
|
||||
# $Id$
|
||||
|
||||
|
||||
$:.unshift '../lib'
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/server'
|
||||
require 'puppet/client'
|
||||
require 'getoptlong'
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--logfile", "-l", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--ssldir", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--fqdn", "-f", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--server", "-s", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--secure", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--port", "-p", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--noinit", "-n", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
noinit = false
|
||||
server = "localhost"
|
||||
proto = "http"
|
||||
fqdn = nil
|
||||
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--help"
|
||||
puts "There is no help yet"
|
||||
exit
|
||||
when "--verbose"
|
||||
Puppet[:loglevel] = :info
|
||||
when "--debug"
|
||||
Puppet[:loglevel] = :debug
|
||||
when "--ssldir"
|
||||
Puppet[:ssldir] = arg
|
||||
when "--secure"
|
||||
proto = "https"
|
||||
when "--noinit"
|
||||
noinit = true
|
||||
when "--fqdn"
|
||||
fqdn = arg
|
||||
when "--server"
|
||||
server = arg
|
||||
when "--port"
|
||||
Puppet[:masterport] = arg
|
||||
when "--logfile"
|
||||
Puppet[:logfile] = arg
|
||||
else
|
||||
puts "Invalid option '#{opt}'"
|
||||
exit(10)
|
||||
end
|
||||
}
|
||||
|
||||
bg = false
|
||||
|
||||
unless Puppet[:loglevel] == :debug or Puppet[:loglevel] == :info
|
||||
bg = true
|
||||
end
|
||||
|
||||
args = {:Server => server}
|
||||
if fqdn
|
||||
args[:FQDN] = fqdn
|
||||
end
|
||||
client = Puppet::Client.new(args)
|
||||
|
||||
unless client.readcert
|
||||
begin
|
||||
while ! client.requestcert do
|
||||
Puppet.notice "Could not request certificate"
|
||||
sleep 5
|
||||
end
|
||||
rescue => detail
|
||||
Puppet.err "Could not request certificate: %s" % detail.to_s
|
||||
exit(23)
|
||||
end
|
||||
end
|
||||
|
||||
if bg
|
||||
Puppet[:logdest] = Puppet[:logfile]
|
||||
client.daemonize
|
||||
end
|
||||
#client.start
|
||||
client.getconfig
|
||||
|
||||
#threads = []
|
||||
#threads << Thread.new {
|
||||
# trap(:INT) {
|
||||
# client.shutdown
|
||||
# }
|
||||
# client.start
|
||||
#}
|
||||
#
|
||||
#client.getconfig
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/local/bin/ruby
|
||||
#!/usr/bin/ruby -w
|
||||
|
||||
#--------------------
|
||||
# produce documentation on all of the puppet types
|
||||
#
|
||||
# $Id$
|
||||
|
||||
|
||||
$:.unshift '../lib'
|
||||
|
||||
require 'puppet'
|
||||
require 'getoptlong'
|
||||
|
||||
def tab(num)
|
||||
return $tab * num
|
||||
end
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--logfile", "-l", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
debug = false
|
||||
logfile = false
|
||||
|
||||
$tab = " "
|
||||
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--help"
|
||||
puts "There is no help yet"
|
||||
exit
|
||||
when "--debug"
|
||||
debug = true
|
||||
when "--logfile"
|
||||
logfile = arg
|
||||
else
|
||||
raise "Invalid option '#{opt}'"
|
||||
end
|
||||
}
|
||||
|
||||
puts %{
|
||||
==============
|
||||
Type Reference
|
||||
==============
|
||||
|
||||
}
|
||||
|
||||
types = {}
|
||||
Puppet::Type.eachtype { |type|
|
||||
types[type.name] = type
|
||||
}
|
||||
puts %{
|
||||
---------------
|
||||
Meta-Parameters
|
||||
---------------
|
||||
|
||||
}
|
||||
Puppet::Type.eachmetaparam { |param|
|
||||
puts "- **" + param.to_s + "**"
|
||||
puts tab(1) + Puppet::Type.metaparamdoc(param).gsub(/\n\s*/,' ')
|
||||
}
|
||||
|
||||
puts %{
|
||||
-----
|
||||
Types
|
||||
-----
|
||||
|
||||
- *namevar* is the parameter used to uniquely identify a type instance.
|
||||
This is the parameter that gets assigned when a string is provided before
|
||||
the colon in a type declaration.
|
||||
- *states* are the aspects of a type that can be changed.
|
||||
- *params* control how a type implements the state changes.
|
||||
|
||||
|
||||
}
|
||||
|
||||
types.sort { |a,b|
|
||||
a.to_s <=> b.to_s
|
||||
}.each { |name,type|
|
||||
next if name == :puppet
|
||||
next if name == :component
|
||||
|
||||
puts "
|
||||
|
||||
----------------
|
||||
|
||||
"
|
||||
|
||||
puts "
|
||||
%s
|
||||
%s" % [name, "=" * (name.to_s.length + 4)]
|
||||
#String.new('n%s\n') % name.to_s
|
||||
#puts "**" + type.doc.gsub(/\n\s*/, ' ') + "**\n\n"
|
||||
puts type.doc.gsub(/\n\s*/, ' ') + "\n\n"
|
||||
type.buildstatehash
|
||||
#puts tab(1) + "* namevar: %s" % type.namevar
|
||||
puts "%s States\n'''''''''''''''''''''''''''''''" % name.to_s.capitalize
|
||||
type.validstates.sort { |a,b|
|
||||
a.to_s <=> b.to_s
|
||||
}.each { |sname,state|
|
||||
puts "- **%s**" % sname
|
||||
puts tab(1) + state.doc.gsub(/\n\s*/,' ')
|
||||
}
|
||||
|
||||
puts "\n%s Parameters\n''''''''''''''''''''''''''''''" % name.to_s.capitalize
|
||||
type.parameters.sort { |a,b|
|
||||
a.to_s <=> b.to_s
|
||||
}.each { |name,param|
|
||||
print "- **%s**" % name
|
||||
if type.namevar == name and name != :name
|
||||
puts " (*namevar*)"
|
||||
else
|
||||
puts ""
|
||||
end
|
||||
puts tab(1) + type.paramdoc(name).gsub(/\n\s*/,' ')
|
||||
}
|
||||
puts "\n"
|
||||
}
|
||||
|
||||
puts "
|
||||
|
||||
----------------
|
||||
|
||||
"
|
||||
|
||||
puts "\n*This page autogenerated on %s*" % Time.now
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/ruby -w
|
||||
|
||||
#--------------------
|
||||
# the central puppet server
|
||||
#
|
||||
# $Id$
|
||||
|
||||
require 'getoptlong'
|
||||
require 'puppet'
|
||||
require 'puppet/server'
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--logfile", "-l", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--manifest", "-m", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--ssldir", "-s", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--noinit", "-n", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--noca", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
noinit = false
|
||||
ca = true
|
||||
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--help"
|
||||
puts "There is no help yet"
|
||||
exit
|
||||
when "--verbose"
|
||||
Puppet[:loglevel] = :info
|
||||
when "--debug"
|
||||
Puppet[:debug] = true
|
||||
when "--noca"
|
||||
ca = false
|
||||
when "--ssldir"
|
||||
Puppet[:ssldir] = arg
|
||||
when "--manifest"
|
||||
Puppet[:manifest] = arg
|
||||
when "--noinit"
|
||||
noinit = true
|
||||
when "--logfile"
|
||||
Puppet[:masterlog] = arg
|
||||
else
|
||||
raise "Invalid option '#{opt}'"
|
||||
end
|
||||
}
|
||||
|
||||
bg = false
|
||||
|
||||
Puppet[:autosign] = true
|
||||
|
||||
unless Puppet[:loglevel] == :debug or Puppet[:loglevel] == :info
|
||||
bg = true
|
||||
end
|
||||
|
||||
if bg
|
||||
Puppet[:logdest] = Puppet[:masterlog]
|
||||
end
|
||||
|
||||
begin
|
||||
# use the default, um, everything
|
||||
#server = Puppet::Server.new(:CA => ca)
|
||||
server = Puppet::Server.new(
|
||||
:Handlers => {
|
||||
:CA => {}, # so that certs autogenerate
|
||||
:Master => {},
|
||||
:Status => {}
|
||||
}
|
||||
)
|
||||
rescue => detail
|
||||
$stderr.puts detail
|
||||
exit(1)
|
||||
end
|
||||
|
||||
if bg
|
||||
server.daemonize
|
||||
end
|
||||
|
||||
trap(:INT) {
|
||||
server.shutdown
|
||||
}
|
||||
begin
|
||||
server.start
|
||||
rescue => detail
|
||||
Puppet.err "Could not start puppetmaster: %s" % detail
|
||||
exit(1)
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
# $Id$
|
||||
|
||||
define thingie {
|
||||
file { "/tmp/classtest": create => true, mode => 755 }
|
||||
#testing {}
|
||||
}
|
||||
|
||||
class testing {
|
||||
thingie { "componentname": }
|
||||
}
|
||||
|
||||
#component {}
|
||||
testing { "testingname": }
|
|
@ -0,0 +1,11 @@
|
|||
# $Id$
|
||||
|
||||
$goodness = sunos
|
||||
|
||||
$subvariable = $goodness
|
||||
|
||||
$yayness = "this is a string of text"
|
||||
|
||||
#$sleeper = service { sleeper:
|
||||
# running => "1"
|
||||
#}
|
|
@ -0,0 +1,35 @@
|
|||
# $Id$
|
||||
|
||||
# define the server as a class
|
||||
|
||||
import "components"
|
||||
|
||||
class base() {
|
||||
# how do i handle components that don't take arguments? do they still
|
||||
# require a name?
|
||||
sudo { }
|
||||
}
|
||||
|
||||
class server inherits base {
|
||||
file { "/tmp/puppetfiletest":
|
||||
create => true
|
||||
}
|
||||
}
|
||||
|
||||
class webserver(docroot) inherits server {
|
||||
apache {
|
||||
php => false,
|
||||
docroot => $docroot,
|
||||
user => http,
|
||||
group => http
|
||||
}
|
||||
}
|
||||
|
||||
class sleepserver(path) inherits server {
|
||||
sleeper {
|
||||
path => $path,
|
||||
mode => 644
|
||||
}
|
||||
}
|
||||
|
||||
# see 'nodes' for how to handle nodes
|
|
@ -0,0 +1,73 @@
|
|||
# $Id$
|
||||
|
||||
# i still have no 'require'-like functionality, and i should also
|
||||
# have 'recommend'-like functionality...
|
||||
define apache(php,docroot,user,group) {
|
||||
package { apache:
|
||||
version => "2.0.53"
|
||||
}
|
||||
service { apache:
|
||||
running => true
|
||||
}
|
||||
|
||||
|
||||
# this definitely won't parse
|
||||
if $php == "true" {
|
||||
# this needs to do two things:
|
||||
# - mark a dependency
|
||||
# - cause this apache component to receive refresh events generated by php
|
||||
#require("php")
|
||||
$var = value
|
||||
}
|
||||
|
||||
#file { "../examples/root/etc/configfile":
|
||||
# owner => $user
|
||||
#}
|
||||
}
|
||||
|
||||
define sudo() {
|
||||
package { sudo:
|
||||
version => "1.6.8p7"
|
||||
}
|
||||
file { "/etc/sudoers":
|
||||
owner => root,
|
||||
group => root,
|
||||
mode => "440"
|
||||
}
|
||||
}
|
||||
|
||||
define ssh {
|
||||
package { ssh:
|
||||
version => "3.4.4.4"
|
||||
}
|
||||
service { "sshd":
|
||||
running => true
|
||||
}
|
||||
}
|
||||
|
||||
define sleeper(path,mode) {
|
||||
Service {
|
||||
path => "../examples/root/etc/init.d"
|
||||
}
|
||||
|
||||
service { sleeper:
|
||||
running => true,
|
||||
path => "../examples/root/etc/init.d"
|
||||
}
|
||||
file { $path:
|
||||
mode => $mode
|
||||
}
|
||||
$files = ["/tmp/testness","/tmp/funtest"]
|
||||
file { $files:
|
||||
create => true
|
||||
}
|
||||
}
|
||||
|
||||
#apache { "test":
|
||||
# php => false,
|
||||
# docroot => "/export/html",
|
||||
# user => "www-data",
|
||||
# group => "www-data"
|
||||
#}
|
||||
|
||||
#ssh { "yucko":}
|
|
@ -0,0 +1,16 @@
|
|||
$path = "/usr/bin:/bin"
|
||||
|
||||
exec { "mkdir -p /tmp/fakedir":
|
||||
path => $path
|
||||
}
|
||||
|
||||
exec { "rm -rf /tmp/fakedir":
|
||||
path => $path
|
||||
}
|
||||
|
||||
exec { "touch /this/directory/does/not/exist":
|
||||
path => $path,
|
||||
returns => 1
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# $Id$
|
||||
|
||||
# DISABLED
|
||||
|
||||
# facts are now added to the top scope (e.g., operatingsystem and macaddress)
|
||||
|
||||
# these facts have to get defined by the server onto the client before
|
||||
# we can retrieve their values
|
||||
#fact { "videocard":
|
||||
# interpreter => "/bin/sh",
|
||||
# code => "lspci | grep VGA",
|
||||
# os => "Linux"
|
||||
#}
|
||||
$testing = "value"
|
||||
$operatingsystem = fact("operatingsystem")
|
||||
$fact = addfact(
|
||||
name => "videocard",
|
||||
interpreter => "/bin/sh",
|
||||
code => "lspci | grep VGA",
|
||||
os => "Linux"
|
||||
)
|
||||
$card = fact("videocard")
|
|
@ -0,0 +1,10 @@
|
|||
class comp() {
|
||||
file { "/etc/passwd":
|
||||
mode => 644
|
||||
}
|
||||
}
|
||||
|
||||
# this argument is invalid, thus we should get a falure
|
||||
comp {
|
||||
fakearg => "yay"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
class comp(arg1) {
|
||||
file { "/etc/passwd":
|
||||
mode => 644
|
||||
}
|
||||
}
|
||||
|
||||
# i've specified an arg but it's an invalid one
|
||||
comp {
|
||||
fakearg => "yay"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
define comp() {
|
||||
file { "/etc/passwd":
|
||||
mode => 644
|
||||
}
|
||||
}
|
||||
|
||||
comp {
|
||||
fakearg => "yay"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
define comp(arg1) {
|
||||
file { "/etc/passwd":
|
||||
mode => 644
|
||||
}
|
||||
}
|
||||
|
||||
comp {
|
||||
fakearg => "yay"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
file { "/etc/passwd":
|
||||
fakeparam => 644
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# $Id$
|
||||
|
||||
file {
|
||||
"/tmp/atest": create => true, mode => 755;
|
||||
"/tmp/btest": create => true, mode => 755
|
||||
}
|
||||
|
||||
file {
|
||||
"/tmp/ctest": create => true;
|
||||
"/tmp/dtest": create => true;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
# $Id$
|
||||
|
||||
File {
|
||||
mode => 755,
|
||||
recurse => true
|
||||
}
|
||||
|
||||
file { "/tmp/filedefaultstest":
|
||||
create => true
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
# $Id$
|
||||
|
||||
# this will eventually parse different config files
|
||||
|
||||
# this creates the 'passwd' type, but it does not create any instances
|
||||
filetype { "passwd":
|
||||
linesplit => "\n",
|
||||
escapednewlines => false
|
||||
}
|
||||
|
||||
|
||||
# this creates the 'PasswdUser' type, but again, no instances
|
||||
filerecord { "user":
|
||||
filetype => passwd,
|
||||
fields => [name, password, uid, gid, gcos, home, shell],
|
||||
namevar => name,
|
||||
splitchar => ":"
|
||||
|
||||
}
|
||||
|
||||
filetype { ini:
|
||||
linesplit => "\n\n"
|
||||
}
|
||||
|
||||
# ini files are different because we don't really care about validating fields
|
||||
# or at least, we can't do it for most files...
|
||||
filerecord { "initrecord":
|
||||
filetype => ini,
|
||||
fields => [name, password, uid, gid, gcos, home, shell],
|
||||
namevar => name,
|
||||
splitchar => ":"
|
||||
|
||||
}
|
||||
|
||||
# this won't work for multiple record types, will it?
|
||||
# or at least, it requires that we specify multiple times
|
||||
# ah, and it doesn't specify which of the available record types
|
||||
# it works for...
|
||||
passwd { user:
|
||||
complete => true, # manage the whole file
|
||||
path => "/etc/passwd"
|
||||
}
|
||||
|
||||
user { yaytest:
|
||||
password => x,
|
||||
uid => 10000,
|
||||
gid => 10000,
|
||||
home => "/home/yaytest",
|
||||
gcos => "The Yaytest",
|
||||
shell => "/bin/sh"
|
||||
}
|
||||
# there seems to be an intrinsic problem here -- i've got subtypes that only
|
||||
# make sense when an instance of the super type already exists, and i need
|
||||
# to associate the instances of the subtype with the instances of the supertype
|
||||
# even if i created the parsers manually, I'd have the same problem
|
||||
|
||||
# this is the crux of it -- i want to be able to say 'user' here without having
|
||||
# to specify the file, which leaves two options:
|
||||
# 1) associate the record type with a filetype instance (BAD)
|
||||
# 2) once the filetype and record type are created, have another command
|
||||
# that specifically creates a filetype instance and gives names for instances
|
||||
# of its record types
|
||||
|
||||
define syslog {
|
||||
|
||||
# create a new type, with all defaults
|
||||
filetype { "syslog":
|
||||
escapednewlines => true
|
||||
}
|
||||
|
||||
filerecord { "log":
|
||||
filetype => syslog,
|
||||
regex => "^([^#\s]+)\s+(\S+)$",
|
||||
joinchar => "\t",
|
||||
fields => [logs, dest]
|
||||
}
|
||||
|
||||
# these two should just be supported within the filetypes
|
||||
filerecord { "comment":
|
||||
filetype => syslog,
|
||||
regex => "^(#.*)$",
|
||||
joinchar => "s",
|
||||
fields => [comment]
|
||||
}
|
||||
|
||||
filerecord { "blank":
|
||||
filetype => syslog,
|
||||
regex => "^(\s*)$",
|
||||
joinchar => "s",
|
||||
fields => blank
|
||||
}
|
||||
}
|
||||
|
||||
define cron {
|
||||
filetype { "usercrontab":
|
||||
}
|
||||
|
||||
# this won't actually work, of course
|
||||
filerecord { "cronjob":
|
||||
filetype => crontab,
|
||||
regex => "^([^#\s]+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)$",
|
||||
joinchar => " ",
|
||||
fields => [minute, hour, day, month, weekday, command],
|
||||
defaults => ["*", "*", "*", "*", "*", nil],
|
||||
optional => [minute, hour, day, month, weekday]
|
||||
}
|
||||
|
||||
crontab { "luke":
|
||||
}
|
||||
}
|
||||
|
||||
# XXX this doesn't work in the slightest
|
||||
define crontab(name,path) {
|
||||
usercrontab { "${path}/${name}":
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
# $Id$
|
||||
|
||||
file { "/tmp/dirtest/b/a":
|
||||
mode => 755,
|
||||
}
|
||||
|
||||
file { "/tmp/dirtest":
|
||||
mode => 755,
|
||||
recurse => true,
|
||||
}
|
||||
|
||||
file { "/tmp/dirtest/b/b":
|
||||
mode => 644,
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# $Id$
|
||||
|
||||
$yaytest = fact("operatingsystem")
|
|
@ -0,0 +1,7 @@
|
|||
# $Id$
|
||||
|
||||
# there need to be two forms of adding to groups:
|
||||
# add the current host to a group, and add a list of hosts to a
|
||||
# group by name
|
||||
|
||||
$group = "crap"
|
|
@ -0,0 +1,30 @@
|
|||
# $Id$
|
||||
|
||||
# this file is responsible for importing all of the files we want to actually test
|
||||
|
||||
# these are all of the simple tests
|
||||
import "simpletests"
|
||||
import "assignments"
|
||||
import "selectors"
|
||||
import "iftest"
|
||||
import "importing"
|
||||
import "execs"
|
||||
import "filedefaults"
|
||||
|
||||
# facts are now imported into the top of the namespace
|
||||
#import "facts"
|
||||
|
||||
# obsoleted
|
||||
#import "functions"
|
||||
|
||||
# files we no longer need to import directly, or at all in some cases
|
||||
#import "one"
|
||||
#import "classing"
|
||||
#import "components"
|
||||
#import "file.bl"
|
||||
#import "fileparsing.disabled"
|
||||
#import "groups"
|
||||
|
||||
# this imports the more complex files
|
||||
import "allatonce" # imports classing and components
|
||||
import "nodes" # imports classing and components
|
|
@ -0,0 +1,21 @@
|
|||
# $Id$
|
||||
$variable = "value"
|
||||
|
||||
$cooltest = $variable ? {
|
||||
other => yayness,
|
||||
value => goodtest
|
||||
}
|
||||
|
||||
if $variable == "other" {
|
||||
$cooltest = "yayness"
|
||||
$platform = $operatingsystem
|
||||
} elsif $variable == "value" {
|
||||
$cooltest = "goodtest"
|
||||
$platform = $operatingsystem
|
||||
} else {
|
||||
$goodness = $operatingsystemrelease
|
||||
}
|
||||
|
||||
if "value" == "value" {
|
||||
$booyah = "value"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# $Id$
|
||||
|
||||
#import "groups"
|
||||
# testing import loops
|
||||
import "importing"
|
||||
|
||||
$name = "value"
|
||||
$system = $operatingsystem
|
|
@ -0,0 +1,20 @@
|
|||
# $Id$
|
||||
|
||||
# define nodes
|
||||
|
||||
#service.setpath("../examples/root/etc/init.d")
|
||||
|
||||
Service {
|
||||
path => "../examples/root/etc/init.d"
|
||||
}
|
||||
|
||||
import "classing"
|
||||
|
||||
sleepserver {
|
||||
path => $operatingsystem ? {
|
||||
sunos => "../examples/root/etc/configfile",
|
||||
hpux => "../examples/other/etc/configfile",
|
||||
default => "../examples/root/etc/configfile"
|
||||
},
|
||||
schedule => true
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# $Id$
|
||||
|
||||
# this service doesn't actually exist, so we noop it
|
||||
# and this way, we can test noop :)
|
||||
service { "funtest":
|
||||
running => "0",
|
||||
noop => true
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
# $Id$
|
||||
|
||||
#service.setpath("../examples/root/etc/init.d")
|
||||
#puppet.statefile("/tmp/puppetstate")
|
||||
$path = "../examples/root/etc/configfile"
|
||||
path => "../examples/root/etc/init.d"
|
||||
|
||||
|
||||
define files {
|
||||
file { "/tmp/yaytest":
|
||||
create => true,
|
||||
mode => 755
|
||||
}
|
||||
file { "/tmp/exists":
|
||||
checksum => md5
|
||||
}
|
||||
}
|
||||
|
||||
define sleeper {
|
||||
file { $path:
|
||||
mode => 755
|
||||
}
|
||||
service { sleeper:
|
||||
path => "../examples/root/etc/init.d",
|
||||
running => 1
|
||||
}
|
||||
}
|
||||
|
||||
files { }
|
||||
|
||||
sleeper {
|
||||
require => files["yay"],
|
||||
schedule => true
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
# $Id$
|
||||
#
|
||||
|
||||
$platform = sunos
|
||||
|
||||
$funtest = $platform ? {
|
||||
sunos => yayness,
|
||||
aix => goodness,
|
||||
default => badness
|
||||
}
|
||||
|
||||
# this is a comment
|
||||
|
||||
$filename = "/tmp/yayness"
|
||||
|
||||
$sleeper = file { $filename:
|
||||
mode => $platform ? {
|
||||
sunos => 644,
|
||||
default => 755
|
||||
},
|
||||
create => $platform ? sunos => true
|
||||
}
|
||||
|
||||
# i guess it has to be solved this way...
|
||||
|
||||
$platform ? sunos => file { $filename:
|
||||
mode => 644
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# $Id$
|
||||
|
||||
file {
|
||||
"/tmp/atest": create => true;
|
||||
"/tmp/btest": create => true
|
||||
}
|
||||
|
||||
file {
|
||||
"/tmp/ctest": create => true;
|
||||
"/tmp/dtest": create => true;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
# $Id$
|
||||
|
||||
define testargs(file, mode = 755) {
|
||||
file { $file: create => true, mode => $mode }
|
||||
}
|
||||
|
||||
testargs { "testingname":
|
||||
file => "/tmp/argumenttest1"
|
||||
}
|
||||
|
||||
testargs { "testingother":
|
||||
file => "/tmp/argumenttest2",
|
||||
mode => 644
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
# $Id$
|
||||
|
||||
define component {
|
||||
file { "/tmp/classtest": create => true, mode => 755 }
|
||||
#testing {}
|
||||
}
|
||||
|
||||
class testing {
|
||||
component { "componentname": }
|
||||
}
|
||||
|
||||
#component {}
|
||||
testing { "testingname": }
|
|
@ -0,0 +1,19 @@
|
|||
# $Id$
|
||||
|
||||
file {
|
||||
"/tmp/dirchmodtesta": create => directory;
|
||||
"/tmp/dirchmodtesta/testing": create => true
|
||||
}
|
||||
|
||||
file { "/tmp/dirchmodtesta":
|
||||
mode => 644, recurse => true
|
||||
}
|
||||
|
||||
file {
|
||||
"/tmp/dirchmodtestb": create => directory;
|
||||
"/tmp/dirchmodtestb/testing": create => true
|
||||
}
|
||||
|
||||
file { "/tmp/dirchmodtestb":
|
||||
mode => 600, recurse => true
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# $Id$
|
||||
|
||||
file {
|
||||
"/tmp/createatest": create => true, mode => 755;
|
||||
"/tmp/createbtest": create => true, mode => 755
|
||||
}
|
||||
|
||||
file {
|
||||
"/tmp/createctest": create => true;
|
||||
"/tmp/createdtest": create => true;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# $Id$
|
||||
|
||||
File { mode => 755 }
|
||||
|
||||
file { "/tmp/defaulttest": create => true }
|
|
@ -0,0 +1,38 @@
|
|||
# $Id$
|
||||
|
||||
$var = "value"
|
||||
|
||||
file { "/tmp/snippetselectatest":
|
||||
create => true,
|
||||
mode => $var ? {
|
||||
nottrue => 641,
|
||||
value => 755
|
||||
}
|
||||
}
|
||||
|
||||
file { "/tmp/snippetselectbtest":
|
||||
create => true,
|
||||
mode => $var ? {
|
||||
nottrue => 644,
|
||||
default => 755
|
||||
}
|
||||
}
|
||||
|
||||
$othervar = "complex value"
|
||||
|
||||
file { "/tmp/snippetselectctest":
|
||||
create => true,
|
||||
mode => $othervar ? {
|
||||
"complex value" => 755,
|
||||
default => 644
|
||||
}
|
||||
}
|
||||
$anothervar = Yayness
|
||||
|
||||
file { "/tmp/snippetselectdtest":
|
||||
create => true,
|
||||
mode => $anothervar ? {
|
||||
Yayness => 755,
|
||||
default => 644
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
$path = "/usr/bin:/bin"
|
||||
|
||||
file { "/tmp/svntests":
|
||||
recurse => true,
|
||||
checksum => md5
|
||||
}
|
||||
|
||||
exec { "echo 'files have been updated'":
|
||||
cwd => "/tmp/svntests",
|
||||
refreshonly => true,
|
||||
require => file["/tmp/svntests"],
|
||||
path => $path
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/ruby -w
|
||||
|
||||
###
|
||||
# sleep indefinitely as a debug
|
||||
|
||||
require 'getoptlong'
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
def daemonize
|
||||
outfile = "/tmp/sleeperout"
|
||||
if pid = fork()
|
||||
Process.detach(pid)
|
||||
sleep 1
|
||||
# verify that we didn't have any problems starting the daemon
|
||||
if FileTest.exists?(outfile)
|
||||
$stderr.puts "Sleeper failed: %s" % File.read(outfile)
|
||||
File.unlink(outfile)
|
||||
exit(14)
|
||||
else
|
||||
exit(0)
|
||||
end
|
||||
end
|
||||
Process.setsid
|
||||
Dir.chdir("/")
|
||||
begin
|
||||
$stdin.reopen "/dev/null"
|
||||
$stdout.reopen "/dev/null", "a"
|
||||
$stderr.reopen $stdin
|
||||
rescue => detail
|
||||
File.open(outfile, "w") { |f|
|
||||
f.puts detail
|
||||
}
|
||||
exit(12)
|
||||
end
|
||||
end
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
debug = false
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--help"
|
||||
puts "There is no help yet"
|
||||
exit
|
||||
when "--debug"
|
||||
debug = true
|
||||
else
|
||||
raise "Invalid option '#{opt}'"
|
||||
end
|
||||
}
|
||||
|
||||
trap(:INT) {
|
||||
exit
|
||||
}
|
||||
|
||||
unless debug
|
||||
daemonize()
|
||||
end
|
||||
|
||||
var = true
|
||||
|
||||
while var do
|
||||
sleep 600
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
|
||||
bin:x:2:2:bin:/bin:/bin/sh
|
||||
sys:x:3:3:sys:/dev:/bin/sh
|
||||
sync:x:4:65534:sync:/bin:/bin/sync
|
||||
games:x:5:60:games:/usr/games:/bin/sh
|
||||
man:x:6:12:man:/var/cache/man:/bin/sh
|
||||
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
|
||||
mail:x:8:8:mail:/var/mail:/bin/sh
|
||||
news:x:9:9:news:/var/spool/news:/bin/sh
|
||||
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
|
||||
proxy:x:13:13:proxy:/bin:/bin/sh
|
||||
postgres:x:31:32:postgres:/var/lib/postgres:/bin/sh
|
||||
www-data:x:33:33:www-data:/var/www:/bin/sh
|
||||
backup:x:34:34:backup:/var/backups:/bin/sh
|
||||
operator:x:37:37:Operator:/var:/bin/sh
|
||||
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
|
||||
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
|
||||
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
|
||||
sshd:x:102:65534::/var/run/sshd:/bin/false
|
||||
gdm:x:101:101:Gnome Display Manager:/var/lib/gdm:/bin/false
|
||||
telnetd:x:103:103::/usr/lib/telnetd:/bin/false
|
||||
nagios:x:1000:1001::/home/nagios:
|
||||
messagebus:x:104:107::/var/run/dbus:/bin/false
|
||||
saned:x:109:109::/home/saned:/bin/false
|
||||
ganglia:x:105:110:Ganglia Monitor:/var/lib/ganglia:/bin/false
|
||||
zope:x:106:111::/var/lib/zope2.7/var:/bin/false
|
||||
fbgetty:x:112:112::/home/fbgetty:/bin/false
|
|
@ -0,0 +1,71 @@
|
|||
# /etc/syslog.conf Configuration file for syslogd.
|
||||
#
|
||||
# For more information see syslog.conf(5)
|
||||
# manpage.
|
||||
|
||||
#
|
||||
# First some standard logfiles. Log by facility.
|
||||
#
|
||||
|
||||
auth,authpriv.* /var/log/auth.log
|
||||
*.*;auth,authpriv.none -/var/log/syslog
|
||||
#cron.* /var/log/cron.log
|
||||
daemon.* -/var/log/daemon.log
|
||||
kern.* -/var/log/kern.log
|
||||
lpr.* -/var/log/lpr.log
|
||||
mail.* -/var/log/mail.log
|
||||
user.* -/var/log/user.log
|
||||
uucp.* /var/log/uucp.log
|
||||
|
||||
#
|
||||
# Logging for the mail system. Split it up so that
|
||||
# it is easy to write scripts to parse these files.
|
||||
#
|
||||
mail.info -/var/log/mail.info
|
||||
mail.warn -/var/log/mail.warn
|
||||
mail.err /var/log/mail.err
|
||||
|
||||
# Logging for INN news system
|
||||
#
|
||||
news.crit /var/log/news/news.crit
|
||||
news.err /var/log/news/news.err
|
||||
news.notice -/var/log/news/news.notice
|
||||
|
||||
#
|
||||
# Some `catch-all' logfiles.
|
||||
#
|
||||
*.=debug;\
|
||||
auth,authpriv.none;\
|
||||
news.none;mail.none -/var/log/debug
|
||||
*.=info;*.=notice;*.=warn;\
|
||||
auth,authpriv.none;\
|
||||
cron,daemon.none;\
|
||||
mail,news.none -/var/log/messages
|
||||
|
||||
#
|
||||
# Emergencies are sent to everybody logged in.
|
||||
#
|
||||
*.emerg *
|
||||
|
||||
#
|
||||
# I like to have messages displayed on the console, but only on a virtual
|
||||
# console I usually leave idle.
|
||||
#
|
||||
#daemon,mail.*;\
|
||||
# news.=crit;news.=err;news.=notice;\
|
||||
# *.=debug;*.=info;\
|
||||
# *.=notice;*.=warn /dev/tty8
|
||||
|
||||
# The named pipe /dev/xconsole is for the `xconsole' utility. To use it,
|
||||
# you must invoke `xconsole' with the `-file' option:
|
||||
#
|
||||
# $ xconsole -file /dev/xconsole [...]
|
||||
#
|
||||
# NOTE: adjust the list below, or you'll go crazy if you have a reasonably
|
||||
# busy site..
|
||||
#
|
||||
daemon.*;mail.*;\
|
||||
news.crit;news.err;news.notice;\
|
||||
*.=debug;*.=info;\
|
||||
*.=notice;*.=warn |/dev/xconsole
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/bin/bash
|
||||
|
||||
# $Id$
|
||||
|
||||
script=$0
|
||||
path=`echo $script | sed 's/etc..*/bin/'`
|
||||
|
||||
PATH=$PATH:$path
|
||||
|
||||
ps=`facter ps | cut -d ' ' -f3-`
|
||||
|
||||
if [ -z "$ps" ]; then
|
||||
ps="ps -ef"
|
||||
fi
|
||||
|
||||
function start
|
||||
{
|
||||
sleeper
|
||||
}
|
||||
|
||||
function stop
|
||||
{
|
||||
#if [ -n `which pgrep` ]; then
|
||||
# pid=`pgrep sleeper`
|
||||
#else
|
||||
pid=`$ps | grep -v grep | grep sleeper | grep ruby | awk '{print $2}'`
|
||||
#fi
|
||||
if [ -n "$pid" ]; then
|
||||
kill $pid
|
||||
fi
|
||||
}
|
||||
|
||||
function status
|
||||
{
|
||||
#if [ -n `which pgrep` ]; then
|
||||
# cmd="pgrep sleeper"
|
||||
#else
|
||||
#cmd="$ps | grep -v grep | grep sleeper | grep ruby | awk '{print $2}'"
|
||||
#fi
|
||||
#$cmd
|
||||
$ps | grep -v grep | grep sleeper | grep ruby
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop; start
|
||||
;;
|
||||
status)
|
||||
output=`status`
|
||||
#status
|
||||
exit $?
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $N {start|stop|restart|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,155 @@
|
|||
require 'openssl'
|
||||
require 'puppet'
|
||||
require 'puppet/sslcertificates'
|
||||
require 'xmlrpc/server'
|
||||
|
||||
# Much of this was taken from QuickCert:
|
||||
# http://segment7.net/projects/ruby/QuickCert/
|
||||
|
||||
module Puppet
|
||||
class CAError < Puppet::Error; end
|
||||
class CA
|
||||
attr_reader :ca
|
||||
|
||||
def self.interface
|
||||
XMLRPC::Service::Interface.new("puppetca") { |iface|
|
||||
iface.add_method("array getcert(csr)")
|
||||
}
|
||||
end
|
||||
|
||||
def autosign?(hostname)
|
||||
# simple values are easy
|
||||
asign = Puppet[:autosign]
|
||||
if asign == true or asign == false
|
||||
return asign
|
||||
end
|
||||
|
||||
# we only otherwise know how to handle files
|
||||
unless asign =~ /^\//
|
||||
raise Puppet::Error, "Invalid autosign value %s" %
|
||||
asign
|
||||
end
|
||||
|
||||
unless FileTest.exists?(asign)
|
||||
Puppet.warning "Autosign is enabled but %s is missing" % asign
|
||||
return false
|
||||
end
|
||||
File.open(asign) { |f|
|
||||
f.each { |line|
|
||||
line.chomp!
|
||||
if line =~ /^[.\w-]+$/ and line == hostname
|
||||
Puppet.info "%s exactly matched %s" % [hostname, line]
|
||||
return true
|
||||
else
|
||||
begin
|
||||
rx = Regexp.new(line)
|
||||
rescue => detail
|
||||
Puppet.err(
|
||||
"Could not create regexp out of autosign line %s: %s" %
|
||||
[line, detail]
|
||||
)
|
||||
next
|
||||
end
|
||||
|
||||
if hostname =~ rx
|
||||
Puppet.info "%s matched %s" % [hostname, line]
|
||||
return true
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def initialize(hash = {})
|
||||
@ca = Puppet::SSLCertificates::CA.new()
|
||||
end
|
||||
|
||||
# our client sends us a csr, and we either store it for later signing,
|
||||
# or we sign it right away
|
||||
def getcert(csrtext, request = nil)
|
||||
# okay, i need to retrieve the hostname from the csr, and then
|
||||
# verify that i get the same hostname through reverse lookup or
|
||||
# something
|
||||
|
||||
Puppet.info "Someone's trying for a cert"
|
||||
csr = OpenSSL::X509::Request.new(csrtext)
|
||||
|
||||
subject = csr.subject
|
||||
|
||||
nameary = subject.to_a.find { |ary|
|
||||
ary[0] == "CN"
|
||||
}
|
||||
|
||||
if nameary.nil?
|
||||
Puppet.err "Invalid certificate request"
|
||||
return "invalid"
|
||||
end
|
||||
|
||||
hostname = nameary[1]
|
||||
|
||||
unless @ca
|
||||
Puppet.notice "Host %s asked for signing from non-CA master" % hostname
|
||||
return ""
|
||||
end
|
||||
|
||||
# okay, we're now going to store the public key if we don't already
|
||||
# have it
|
||||
public_key = csr.public_key
|
||||
unless FileTest.directory?(Puppet[:publickeydir])
|
||||
Puppet.recmkdir(Puppet[:publickeydir])
|
||||
end
|
||||
pkeyfile = File.join(Puppet[:publickeydir], [hostname, "pem"].join('.'))
|
||||
|
||||
if FileTest.exists?(pkeyfile)
|
||||
currentkey = File.open(pkeyfile) { |k| k.read }
|
||||
unless currentkey == public_key.to_s
|
||||
raise Puppet::Error, "public keys for %s differ" % hostname
|
||||
end
|
||||
else
|
||||
File.open(pkeyfile, "w", 0644) { |f|
|
||||
f.print public_key.to_s
|
||||
}
|
||||
end
|
||||
unless FileTest.directory?(Puppet[:certdir])
|
||||
Puppet.recmkdir(Puppet[:certdir], 0770)
|
||||
end
|
||||
certfile = File.join(Puppet[:certdir], [hostname, "pem"].join("."))
|
||||
|
||||
#puts hostname
|
||||
#puts certfile
|
||||
|
||||
unless FileTest.directory?(Puppet[:csrdir])
|
||||
Puppet.recmkdir(Puppet[:csrdir], 0770)
|
||||
end
|
||||
# first check to see if we already have a signed cert for the host
|
||||
cert, cacert = ca.getclientcert(hostname)
|
||||
if cert and cacert
|
||||
Puppet.info "Retrieving existing certificate for %s" % hostname
|
||||
Puppet.info "Cert: %s; Cacert: %s" % [cert.class, cacert.class]
|
||||
return [cert.to_pem, cacert.to_pem]
|
||||
elsif @ca
|
||||
if self.autosign?(hostname)
|
||||
# okay, we don't have a signed cert
|
||||
# if we're a CA and autosign is turned on, then go ahead and sign
|
||||
# the csr and return the results
|
||||
Puppet.info "Signing certificate for %s" % hostname
|
||||
cert, cacert = @ca.sign(csr)
|
||||
Puppet.info "Cert: %s; Cacert: %s" % [cert.class, cacert.class]
|
||||
return [cert.to_pem, cacert.to_pem]
|
||||
else # just write out the csr for later signing
|
||||
if @ca.getclientcsr(hostname)
|
||||
Puppet.info "Not replacing existing request from %s" % hostname
|
||||
else
|
||||
Puppet.info "Storing certificate request for %s" % hostname
|
||||
@ca.storeclientcsr(csr)
|
||||
end
|
||||
return ["", ""]
|
||||
end
|
||||
else
|
||||
raise "huh?"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,6 +5,7 @@
|
|||
require 'puppet'
|
||||
require 'puppet/sslcertificates'
|
||||
require 'puppet/type'
|
||||
require 'puppet/server'
|
||||
require 'facter'
|
||||
require 'openssl'
|
||||
require 'puppet/transaction'
|
||||
|
@ -32,22 +33,23 @@ module Puppet
|
|||
class NetworkClient < XMLRPC::Client
|
||||
#include Puppet::Daemon
|
||||
|
||||
@@methods = {
|
||||
"puppetmaster" => [ :getconfig ],
|
||||
"puppetca" => [ :getcert ]
|
||||
}
|
||||
@@handlers = [Puppet::FileServer, Puppet::CA, Puppet::Master]
|
||||
|
||||
@@methods.each { |namespace, methods|
|
||||
methods.each { |method|
|
||||
@@handlers.each { |handler|
|
||||
interface = handler.interface
|
||||
namespace = interface.prefix
|
||||
|
||||
interface.methods.each { |ary|
|
||||
method = ary[0]
|
||||
self.send(:define_method,method) { |*args|
|
||||
Puppet.info "peer cert is %s" % @http.peer_cert
|
||||
#Puppet.info "peer cert is %s" % @http.peer_cert
|
||||
#Puppet.info "cert is %s" % @http.cert
|
||||
begin
|
||||
call("%s.%s" % [namespace, method.to_s],*args)
|
||||
rescue XMLRPC::FaultException => detail
|
||||
Puppet.err "XML Could not call %s.%s: %s" %
|
||||
[namespace, method, detail.faultString]
|
||||
raise NetworkClientError.new,
|
||||
raise NetworkClientError,
|
||||
"XMLRPC Error: %s" % detail.faultString
|
||||
rescue => detail
|
||||
Puppet.err "Could not call %s.%s: %s" %
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
require 'puppet'
|
||||
require 'cgi'
|
||||
|
||||
module Puppet
|
||||
class FileServerError < Puppet::Error; end
|
||||
class FileServer
|
||||
attr_accessor :local
|
||||
|
||||
#CHECKPARAMS = %w{checksum type mode owner group}
|
||||
CHECKPARAMS = [:mode, :type, :owner, :group, :checksum]
|
||||
|
||||
def self.interface
|
||||
XMLRPC::Service::Interface.new("fileserver") { |iface|
|
||||
iface.add_method("string describe(string)")
|
||||
iface.add_method("string list(string, boolean)")
|
||||
iface.add_method("string retrieve(string)")
|
||||
}
|
||||
end
|
||||
|
||||
def check(dir)
|
||||
unless FileTest.exists?(dir)
|
||||
Puppet.notice "File source %s does not exist" % dir
|
||||
return nil
|
||||
end
|
||||
|
||||
obj = nil
|
||||
unless obj = Puppet::Type::PFile[dir]
|
||||
obj = Puppet::Type::PFile.new(
|
||||
:name => dir,
|
||||
:check => CHECKPARAMS
|
||||
)
|
||||
end
|
||||
# we should really have a timeout here -- we don't
|
||||
# want to actually check on every connection, maybe no more
|
||||
# than every 60 seconds or something
|
||||
#@files[mount].evaluate
|
||||
obj.evaluate
|
||||
|
||||
return obj
|
||||
end
|
||||
|
||||
def describe(file)
|
||||
mount, path = splitpath(file)
|
||||
|
||||
subdir = nil
|
||||
unless subdir = subdir(mount, path)
|
||||
Puppet.notice "Could not find subdirectory %s" %
|
||||
"//%s/%s" % [mount, path]
|
||||
return ""
|
||||
end
|
||||
|
||||
obj = nil
|
||||
unless obj = self.check(subdir)
|
||||
return ""
|
||||
end
|
||||
|
||||
desc = []
|
||||
CHECKPARAMS.each { |check|
|
||||
if state = obj.state(check)
|
||||
unless state.is
|
||||
Puppet.notice "Manually retrieving info for %s" % check
|
||||
state.retrieve
|
||||
end
|
||||
desc << state.is
|
||||
else
|
||||
if check == "checksum" and obj.state(:type).is == "file"
|
||||
Puppet.notice "File %s does not have data for %s" %
|
||||
[obj.name, check]
|
||||
end
|
||||
desc << nil
|
||||
end
|
||||
}
|
||||
|
||||
return desc.join("\t")
|
||||
end
|
||||
|
||||
def initialize(hash = {})
|
||||
@mounts = {}
|
||||
@files = {}
|
||||
|
||||
if hash[:Local]
|
||||
@local = hash[:Local]
|
||||
else
|
||||
@local = false
|
||||
end
|
||||
end
|
||||
|
||||
def list(dir, recurse = false, sum = "md5")
|
||||
mount, path = splitpath(dir)
|
||||
|
||||
subdir = nil
|
||||
unless subdir = subdir(mount, path)
|
||||
Puppet.notice "Could not find subdirectory %s" %
|
||||
"//%s/%s" % [mount, path]
|
||||
return ""
|
||||
end
|
||||
|
||||
obj = nil
|
||||
unless FileTest.exists?(subdir)
|
||||
return ""
|
||||
end
|
||||
|
||||
#rmdir = File.dirname(File.join(@mounts[mount], path))
|
||||
rmdir = nameswap(dir, mount)
|
||||
desc = self.reclist(rmdir, subdir, recurse)
|
||||
|
||||
if desc.length == 0
|
||||
Puppet.notice "Got no information on //%s/%s" %
|
||||
[mount, path]
|
||||
return ""
|
||||
end
|
||||
|
||||
desc.collect { |sub|
|
||||
sub.join("\t")
|
||||
}.join("\n")
|
||||
end
|
||||
|
||||
def mount(dir, name)
|
||||
if @mounts.include?(name)
|
||||
if @mounts[name] != dir
|
||||
raise FileServerError, "%s is already mounted at %s" %
|
||||
[@mounts[name], name]
|
||||
else
|
||||
# it's already mounted; no problem
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
unless name =~ %r{^\w+$}
|
||||
raise FileServerError, "Invalid name format '%s'" % name
|
||||
end
|
||||
|
||||
unless FileTest.exists?(dir)
|
||||
raise FileServerError, "%s does not exist" % dir
|
||||
end
|
||||
|
||||
if FileTest.directory?(dir)
|
||||
if FileTest.readable?(dir)
|
||||
Puppet.info "Mounting %s at %s" % [dir, name]
|
||||
@mounts[name] = dir
|
||||
else
|
||||
raise FileServerError, "%s is not readable" % dir
|
||||
end
|
||||
else
|
||||
raise FileServerError, "%s is not a directory" % dir
|
||||
end
|
||||
end
|
||||
|
||||
# recursive listing function
|
||||
def reclist(root, path, recurse)
|
||||
#desc = [obj.name.sub(%r{#{root}/?}, '')]
|
||||
name = path.sub(root, '')
|
||||
if name == ""
|
||||
name = "/"
|
||||
end
|
||||
|
||||
if name == path
|
||||
raise Puppet::FileServerError, "Could not match %s in %s" %
|
||||
[root, path]
|
||||
end
|
||||
|
||||
desc = [name]
|
||||
ftype = File.stat(path).ftype
|
||||
|
||||
desc << ftype
|
||||
if recurse.is_a?(Integer)
|
||||
recurse -= 1
|
||||
end
|
||||
|
||||
ary = [desc]
|
||||
if recurse == true or (recurse.is_a?(Integer) and recurse > -1)
|
||||
if ftype == "directory"
|
||||
Dir.entries(path).each { |child|
|
||||
next if child =~ /^\.\.?$/
|
||||
self.reclist(root, File.join(path, child), recurse).each { |cobj|
|
||||
ary << cobj
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return ary.reject { |c| c.nil? }
|
||||
end
|
||||
|
||||
def retrieve(file)
|
||||
mount, path = splitpath(file)
|
||||
|
||||
unless (@mounts.include?(mount))
|
||||
# FIXME I really need some better way to pass and handle xmlrpc errors
|
||||
raise FileServerError, "%s not mounted" % mount
|
||||
end
|
||||
|
||||
fpath = nil
|
||||
if path
|
||||
fpath = File.join(@mounts[mount], path)
|
||||
else
|
||||
fpath = @mounts[mount]
|
||||
end
|
||||
|
||||
unless FileTest.exists?(fpath)
|
||||
return ""
|
||||
end
|
||||
|
||||
str = File.read(fpath)
|
||||
|
||||
if @local
|
||||
return str
|
||||
else
|
||||
return CGI.escape(str)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def nameswap(name, mount)
|
||||
name.sub(/\/#{mount}/, @mounts[mount]).gsub(%r{//}, '/').sub(
|
||||
%r{/$}, ''
|
||||
)
|
||||
#Puppet.info "Swapped %s to %s" % [name, newname]
|
||||
#newname
|
||||
end
|
||||
|
||||
def splitpath(dir)
|
||||
# the dir is based on one of the mounts
|
||||
# so first retrieve the mount path
|
||||
mount = nil
|
||||
path = nil
|
||||
if dir =~ %r{/(\w+)/?}
|
||||
mount = $1
|
||||
path = dir.sub(%r{/#{mount}/?}, '')
|
||||
|
||||
unless @mounts.include?(mount)
|
||||
raise FileServerError, "%s not mounted" % mount
|
||||
end
|
||||
else
|
||||
raise FileServerError, "Invalid path '%s'" % dir
|
||||
end
|
||||
|
||||
if path == ""
|
||||
path = nil
|
||||
end
|
||||
return mount, path
|
||||
end
|
||||
|
||||
def subdir(mount, dir)
|
||||
basedir = @mounts[mount]
|
||||
|
||||
dirname = nil
|
||||
if dir
|
||||
dirname = File.join(basedir, dir.split("/").join(File::SEPARATOR))
|
||||
else
|
||||
dirname = basedir
|
||||
end
|
||||
|
||||
return dirname
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# $Id$
|
|
@ -0,0 +1,88 @@
|
|||
require 'openssl'
|
||||
require 'puppet'
|
||||
require 'puppet/parser/interpreter'
|
||||
require 'puppet/sslcertificates'
|
||||
require 'xmlrpc/server'
|
||||
|
||||
module Puppet
|
||||
class MasterError < Puppet::Error; end
|
||||
class Master
|
||||
attr_accessor :ast, :local
|
||||
attr_reader :ca
|
||||
|
||||
def self.interface
|
||||
XMLRPC::Service::Interface.new("puppetmaster") { |iface|
|
||||
iface.add_method("string getconfig(string)")
|
||||
}
|
||||
end
|
||||
|
||||
def initialize(hash = {})
|
||||
|
||||
# build our AST
|
||||
@file = hash[:File] || Puppet[:manifest]
|
||||
@parser = Puppet::Parser::Parser.new()
|
||||
@parser.file = @file
|
||||
@ast = @parser.parse
|
||||
hash.delete(:File)
|
||||
|
||||
if hash[:Local]
|
||||
@local = hash[:Local]
|
||||
else
|
||||
@local = false
|
||||
end
|
||||
|
||||
if hash.include?(:CA) and hash[:CA]
|
||||
@ca = Puppet::SSLCertificates::CA.new()
|
||||
else
|
||||
@ca = nil
|
||||
end
|
||||
end
|
||||
|
||||
def getconfig(facts, request = nil)
|
||||
if request
|
||||
#Puppet.warning request.inspect
|
||||
end
|
||||
if @local
|
||||
# we don't need to do anything, since we should already
|
||||
# have raw objects
|
||||
Puppet.debug "Our client is local"
|
||||
else
|
||||
Puppet.debug "Our client is remote"
|
||||
|
||||
# XXX this should definitely be done in the protocol, somehow
|
||||
begin
|
||||
facts = Marshal::load(CGI.unescape(facts))
|
||||
rescue => detail
|
||||
puts "AAAAA"
|
||||
puts detail
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
Puppet.debug("Creating interpreter")
|
||||
|
||||
begin
|
||||
interpreter = Puppet::Parser::Interpreter.new(
|
||||
:ast => @ast,
|
||||
:facts => facts
|
||||
)
|
||||
rescue => detail
|
||||
return detail.to_s
|
||||
end
|
||||
|
||||
Puppet.debug("Running interpreter")
|
||||
begin
|
||||
retobjects = interpreter.run()
|
||||
rescue => detail
|
||||
Puppet.err detail.to_s
|
||||
return ""
|
||||
end
|
||||
|
||||
if @local
|
||||
return retobjects
|
||||
else
|
||||
return CGI.escape(Marshal::dump(retobjects))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -223,7 +223,7 @@ module Puppet
|
|||
begin
|
||||
RRD.graph(*args)
|
||||
rescue => detail
|
||||
err "Failed to graph %s: %s" % [self.name,detail]
|
||||
Puppet.err "Failed to graph %s: %s" % [self.name,detail]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -241,7 +241,7 @@ module Puppet
|
|||
begin
|
||||
RRD.update(self.path,args.join(":"))
|
||||
rescue => detail
|
||||
err "Failed to update %s: %s" % [self.name,detail]
|
||||
Puppet.err "Failed to update %s: %s" % [self.name,detail]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,672 @@
|
|||
#/usr/bin/ruby
|
||||
|
||||
# $Id$
|
||||
# vim: syntax=ruby
|
||||
|
||||
# the parser
|
||||
|
||||
class Puppet::Parser::Parser
|
||||
|
||||
token LBRACK QTEXT RBRACK LBRACE RBRACE SYMBOL FARROW COMMA TRUE FALSE EQUALS
|
||||
token QMARK LPAREN RPAREN ISEQUAL GREATEREQUAL GREATERTHAN LESSTHAN LESSEQUAL NOTEQUAL
|
||||
token IF ELSE IMPORT DEFINE ELSIF VARIABLE CLASS INHERITS NODE BOOLEAN DOT COLON TYPE
|
||||
token NAME SEMIC
|
||||
|
||||
rule
|
||||
program: statements {
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
result = val[0]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:children => [val[0]]
|
||||
)
|
||||
end
|
||||
|
||||
# this is mainly so we can test the parser separately from the
|
||||
# interpreter
|
||||
if Puppet[:parseonly]
|
||||
begin
|
||||
if Puppet[:debug]
|
||||
puts result.tree(0)
|
||||
end
|
||||
rescue NoMethodError => detail
|
||||
Puppet.err detail
|
||||
#exit(78)
|
||||
end
|
||||
#require 'puppet/parser/interpreter'
|
||||
#result = Puppet::Server.new(result)
|
||||
end
|
||||
}
|
||||
|
||||
statements: statement
|
||||
| statements statement {
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
val[0].push(val[1])
|
||||
result = val[0]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line,
|
||||
:children => [val[0],val[1]]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
statement: object
|
||||
| assignment
|
||||
| selector
|
||||
| iftest
|
||||
| import
|
||||
| definition
|
||||
| hostclass
|
||||
|
||||
#object: name LBRACE objectname COLON params endcomma RBRACE {
|
||||
object: name LBRACE objectinstances endsemi RBRACE {
|
||||
ary = val[2]
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
Puppet.notice "invalid name"
|
||||
raise Puppet::ParseError, "Invalid name"
|
||||
end
|
||||
if ary[0].is_a?(AST::Leaf)
|
||||
ary = [ary]
|
||||
end
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file
|
||||
)
|
||||
ary.each { |instance|
|
||||
Puppet.debug "Adding %s with name %s" % [val[0].value, instance[0].value]
|
||||
result.push AST::ObjectDef.new(
|
||||
:pin => "{}",
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:type => val[0],
|
||||
:name => instance[0],
|
||||
:params => instance[1]
|
||||
)
|
||||
}
|
||||
} | name LBRACE params endcomma RBRACE {
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
Puppet.notice "invalid name"
|
||||
raise Puppet::ParseError, "Invalid name"
|
||||
end
|
||||
# an object but without a name
|
||||
# this cannot be an instance of a library type
|
||||
|
||||
Puppet.debug "Adding %s" % val[0].value
|
||||
# make a unique name for bookkeeping purposes
|
||||
name = AST::Name.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => [val[0].value, "-", val[0].object_id].join('')
|
||||
)
|
||||
|
||||
result = AST::ObjectDef.new(
|
||||
:pin => "{}",
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:type => val[0],
|
||||
:name => name,
|
||||
:params => val[2]
|
||||
)
|
||||
} | type LBRACE params endcomma RBRACE {
|
||||
# a template setting for a type
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
Puppet.notice "invalid type"
|
||||
raise Puppet::ParseError, "Invalid type"
|
||||
end
|
||||
result = AST::TypeDefaults.new(
|
||||
:pin => "{}",
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:type => val[0],
|
||||
:params => val[2]
|
||||
)
|
||||
}
|
||||
|
||||
objectinst: objectname COLON params {
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],val[2]]
|
||||
)
|
||||
}
|
||||
|
||||
objectinstances: objectinst
|
||||
| objectinstances SEMIC objectinst {
|
||||
if val[0][0].is_a?(AST::ASTArray)
|
||||
val[0].push val[2]
|
||||
result = val[0]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],val[2]]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
endsemi: # nothing
|
||||
| SEMIC
|
||||
|
||||
name: NAME {
|
||||
result = AST::Name.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => val[0]
|
||||
)
|
||||
}
|
||||
|
||||
type: TYPE {
|
||||
result = AST::Type.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => val[0]
|
||||
)
|
||||
}
|
||||
|
||||
objectname: quotedtext
|
||||
| name
|
||||
| selector
|
||||
| variable
|
||||
| array
|
||||
|
||||
assignment: VARIABLE EQUALS rvalue {
|
||||
# this is distinct from referencing a variable
|
||||
variable = AST::Name.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => val[0].sub(/^\$/,'')
|
||||
)
|
||||
result = AST::VarDef.new(
|
||||
:pin => "=",
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:name => variable,
|
||||
:value => val[2]
|
||||
)
|
||||
}
|
||||
|
||||
params: # nothing
|
||||
{
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => []
|
||||
)
|
||||
}
|
||||
| param { result = val[0] }
|
||||
| params COMMA param {
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
val[0].push(val[2])
|
||||
result = val[0]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],val[2]]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
param: NAME FARROW rvalue {
|
||||
leaf = AST::String.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => val[0]
|
||||
)
|
||||
result = AST::ObjectParam.new(
|
||||
:pin => "=>",
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:param => leaf,
|
||||
:value => val[2]
|
||||
)
|
||||
}
|
||||
|
||||
rvalues: rvalue
|
||||
| rvalues comma rvalue {
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
result = val[0].push(val[2])
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],val[2]]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
rvalue: quotedtext
|
||||
| name
|
||||
| type
|
||||
| boolean
|
||||
| selector
|
||||
| object
|
||||
| variable
|
||||
| array
|
||||
| objectref
|
||||
|
||||
quotedtext: QTEXT {
|
||||
result = AST::String.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => val[0]
|
||||
)
|
||||
}
|
||||
|
||||
boolean: BOOLEAN {
|
||||
result = AST::Boolean.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => val[0]
|
||||
)
|
||||
}
|
||||
|
||||
objectref: name LBRACK rvalue RBRACK {
|
||||
result = AST::ObjectRef.new(
|
||||
:pin => '[]',
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:type => val[0],
|
||||
:name => val[2]
|
||||
)
|
||||
}
|
||||
|
||||
iftest: IF test LBRACE statements RBRACE {
|
||||
result = AST::If.new(
|
||||
:pin => "if",
|
||||
:test => val[1],
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line,
|
||||
:statements => val[3]
|
||||
)
|
||||
}
|
||||
| IF test LBRACE statements RBRACE elsifs ELSE LBRACE statements RBRACE {
|
||||
# make sure our elsifs are an array, as it will save lots of
|
||||
# effort later
|
||||
unless val[5].is_a?(AST::ASTArray)
|
||||
val[5] = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[5]]
|
||||
)
|
||||
end
|
||||
|
||||
result = AST::If.new(
|
||||
:pin => "if",
|
||||
:test => val[1],
|
||||
:statements => val[3],
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line,
|
||||
:else => val[8],
|
||||
:elsif => val[5]
|
||||
)
|
||||
|
||||
}
|
||||
| IF test LBRACE statements RBRACE ELSE LBRACE statements RBRACE {
|
||||
result = AST::If.new(
|
||||
:pin => "if",
|
||||
:test => val[1],
|
||||
:statements => val[3],
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line,
|
||||
:else => val[7]
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
elsifs: ELSIF test LBRACE statements RBRACE {
|
||||
result = AST::If.new(
|
||||
:pin => "elseif",
|
||||
:test => val[1],
|
||||
:file => @lexer.file,
|
||||
:statements => val[3],
|
||||
:line => @lexer.line
|
||||
)
|
||||
}
|
||||
| elsifs ELSIF test LBRACE statements RBRACE {
|
||||
second = AST::If.new(
|
||||
:pin => "elsif",
|
||||
:test => val[2],
|
||||
:statements => val[4],
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line
|
||||
)
|
||||
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
val[0].push(second)
|
||||
result = val[0]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],second]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
test: rvalue
|
||||
| rvalue testop rvalue {
|
||||
result = AST::Test.new(
|
||||
:pin => val[1],
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:lhs => val[0],
|
||||
:rhs => val[2]
|
||||
)
|
||||
}
|
||||
|
||||
testop: ISEQUAL
|
||||
| GREATEREQUAL
|
||||
| GREATERTHAN
|
||||
| LESSTHAN
|
||||
| LESSEQUAL
|
||||
| NOTEQUAL
|
||||
|
||||
selector: variable QMARK svalues {
|
||||
result = AST::Selector.new(
|
||||
:pin => "?",
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:param => val[0],
|
||||
:value => val[2]
|
||||
)
|
||||
}
|
||||
|
||||
svalues: selectval
|
||||
| LBRACE sintvalues RBRACE { result = val[1] }
|
||||
|
||||
sintvalues: selectval
|
||||
| sintvalues comma selectval {
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
val[0].push(val[2])
|
||||
result = val[0]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],val[2]]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
selectval: selectlhand FARROW rvalue {
|
||||
leaf = AST::String.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => val[0]
|
||||
)
|
||||
result = AST::ObjectParam.new(
|
||||
:pin => "=>",
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:param => leaf,
|
||||
:value => val[2]
|
||||
)
|
||||
}
|
||||
|
||||
selectlhand: NAME
|
||||
| TYPE
|
||||
| QTEXT
|
||||
|
||||
import: IMPORT QTEXT {
|
||||
# importing files
|
||||
# yuk, i hate keywords
|
||||
# we'll probably have to have some kind of search path eventually
|
||||
# but for now, just use a path relative to the file doing the importing
|
||||
path = @lexer.file.sub(%r{[^/]+$},val[1])
|
||||
parser = Puppet::Parser::Parser.new()
|
||||
parser.stack = self.stack
|
||||
Puppet.debug("importing %s" % path)
|
||||
noimport = false
|
||||
begin
|
||||
parser.file = path
|
||||
rescue Puppet::ImportError
|
||||
Puppet.warning("Importing %s would result in an import loop" % path)
|
||||
result = AST::ASTArray.new(
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line
|
||||
)
|
||||
noimport = true
|
||||
end
|
||||
unless noimport
|
||||
result = parser.parse
|
||||
end
|
||||
}
|
||||
|
||||
definition: DEFINE NAME argumentlist LBRACE statements RBRACE {
|
||||
result = AST::CompDef.new(
|
||||
:name => AST::Name.new(:value => val[1], :line => @lexer.line),
|
||||
:args => val[2],
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line,
|
||||
:code => val[4]
|
||||
)
|
||||
}
|
||||
|
||||
hostclass: CLASS NAME argumentlist parent LBRACE statements RBRACE {
|
||||
result = AST::ClassDef.new(
|
||||
:name => AST::Name.new(:value => val[1], :line => @lexer.line),
|
||||
:args => val[2],
|
||||
:parentclass => val[3],
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line,
|
||||
:code => val[5]
|
||||
)
|
||||
}
|
||||
|
||||
#nodedef: NODE words LBRACE statements RBRACE {
|
||||
# result = AST::NodeDef.new(
|
||||
# :names => val[1],
|
||||
# :code => val[3]
|
||||
# )
|
||||
#}
|
||||
|
||||
nothing: {
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => []
|
||||
)
|
||||
}
|
||||
|
||||
argumentlist: nothing
|
||||
| LPAREN nothing RPAREN {
|
||||
result = val[1]
|
||||
}
|
||||
| LPAREN arguments RPAREN {
|
||||
if val[1].is_a?(AST::ASTArray)
|
||||
result = val[1]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0]]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
arguments: argument
|
||||
| arguments COMMA argument {
|
||||
if val[0].is_a?(AST::ASTArray)
|
||||
val[0].push(val[2])
|
||||
result = val[0]
|
||||
else
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],val[2]]
|
||||
)
|
||||
end
|
||||
}
|
||||
|
||||
argument: name EQUALS rvalue {
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0],val[2]]
|
||||
)
|
||||
}
|
||||
| name {
|
||||
result = AST::ASTArray.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:children => [val[0]]
|
||||
)
|
||||
}
|
||||
|
||||
parent: nothing
|
||||
| INHERITS NAME {
|
||||
result = AST::Name.new(
|
||||
:value => val[1],
|
||||
:file => @lexer.file,
|
||||
:line => @lexer.line
|
||||
)
|
||||
}
|
||||
|
||||
variable: VARIABLE {
|
||||
name = val[0].sub(/^\$/,'')
|
||||
result = AST::Variable.new(
|
||||
:line => @lexer.line,
|
||||
:file => @lexer.file,
|
||||
:value => name
|
||||
)
|
||||
}
|
||||
|
||||
array: LBRACK rvalues RBRACK {
|
||||
if val[1].is_a?(AST::ASTArray)
|
||||
result = val[1]
|
||||
else
|
||||
result = AST::ASTArray.new
|
||||
result.push val[1]
|
||||
end
|
||||
}
|
||||
|
||||
comma: FARROW
|
||||
| COMMA
|
||||
|
||||
endcomma: # nothing
|
||||
| COMMA { result = nil }
|
||||
|
||||
end
|
||||
---- header ----
|
||||
require 'puppet'
|
||||
require 'puppet/parser/lexer'
|
||||
require 'puppet/parser/ast'
|
||||
#require 'puppet/parser/interpreter'
|
||||
|
||||
module Puppet
|
||||
# this exception class already has a :stack accessor
|
||||
class ParseError < Puppet::Error
|
||||
attr_accessor :line, :file
|
||||
end
|
||||
|
||||
class ImportError < Racc::ParseError; end
|
||||
end
|
||||
|
||||
Puppet[:typecheck] = true
|
||||
Puppet[:paramcheck] = true
|
||||
|
||||
---- inner ----
|
||||
attr_writer :stack
|
||||
attr_reader :file
|
||||
|
||||
def file=(file)
|
||||
if self.stack.include?(file)
|
||||
raise Puppet::ImportError.new("Import loop detected")
|
||||
else
|
||||
@lexer.file = file
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@lexer = Puppet::Parser::Lexer.new()
|
||||
if Puppet[:debug]
|
||||
@yydebut = true
|
||||
end
|
||||
end
|
||||
|
||||
def on_error(token,value,stack)
|
||||
#on '%s' at '%s' in\n'%s'" % [token,value,stack]
|
||||
#error = "line %s: parse error after '%s'" %
|
||||
# [@lexer.line,@lexer.last]
|
||||
error = "an error was found"
|
||||
|
||||
if Puppet[:debug]
|
||||
puts stack.inspect
|
||||
puts stack
|
||||
end
|
||||
if @lexer.file
|
||||
error += (" in '%s'" % @lexer.file)
|
||||
end
|
||||
|
||||
except = Puppet::ParseError.new(error)
|
||||
except.line = @lexer.line
|
||||
if @lexer.file
|
||||
except.file = @lexer.file
|
||||
end
|
||||
|
||||
raise except
|
||||
end
|
||||
|
||||
# how should I do error handling here?
|
||||
def parse
|
||||
begin
|
||||
yyparse(@lexer,:scan)
|
||||
rescue Racc::ParseError => except
|
||||
error = Puppet::ParseError.new(except)
|
||||
error.line = @lexer.line
|
||||
error.file = @lexer.file
|
||||
error.stack = caller
|
||||
raise error
|
||||
rescue Puppet::ParseError => except
|
||||
except.line ||= @lexer.line
|
||||
except.file ||= @lexer.file
|
||||
raise except
|
||||
rescue Puppet::Error => except
|
||||
# and this is a framework error
|
||||
except.line ||= @lexer.line
|
||||
except.file ||= @lexer.file
|
||||
except.stack ||= except.stack
|
||||
raise except
|
||||
rescue Puppet::DevError => except
|
||||
except.line ||= @lexer.line
|
||||
except.file ||= @lexer.file
|
||||
except.stack ||= caller
|
||||
if Puppet[:debug]
|
||||
puts except.stack
|
||||
end
|
||||
raise except
|
||||
rescue => except
|
||||
error = Puppet::DevError.new(except.message)
|
||||
error.line = @lexer.line
|
||||
error.file = @lexer.file
|
||||
error.stack = caller
|
||||
if Puppet[:debug]
|
||||
puts caller
|
||||
end
|
||||
raise error
|
||||
end
|
||||
end
|
||||
|
||||
def stack
|
||||
if defined? @stack and ! @stack.nil?
|
||||
if @lexer.file
|
||||
return [@stack,@lexer.file].flatten
|
||||
else
|
||||
return @stack
|
||||
end
|
||||
else
|
||||
if @lexer.file
|
||||
return [@lexer.file]
|
||||
else
|
||||
return []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def string=(string)
|
||||
@lexer.string = string
|
||||
end
|
|
@ -0,0 +1,135 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# $Id$
|
||||
|
||||
# the interpreter
|
||||
#
|
||||
# this builds our virtual pinball machine, into which we'll place our host-specific
|
||||
# information and out of which we'll receive our host-specific configuration
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/parser/parser'
|
||||
require 'puppet/parser/scope'
|
||||
|
||||
|
||||
module Puppet
|
||||
module Parser
|
||||
#---------------------------------------------------------------
|
||||
class Interpreter
|
||||
attr_accessor :ast, :topscope
|
||||
# just shorten the constant path a bit, using what amounts to an alias
|
||||
AST = Puppet::Parser::AST
|
||||
|
||||
#------------------------------------------------------------
|
||||
def clear
|
||||
TransObject.clear
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
#def callfunc(function,*args)
|
||||
# #Puppet.debug("Calling %s on %s" % [function,@client])
|
||||
# @client.callfunc(function,*args)
|
||||
# #Puppet.debug("Finished %s" % function)
|
||||
#end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# create our interpreter
|
||||
def initialize(hash)
|
||||
unless hash.include?(:ast)
|
||||
raise ArgumentError.new("Must pass tree and client to Interpreter")
|
||||
end
|
||||
@ast = hash[:ast]
|
||||
#@client = hash[:client]
|
||||
|
||||
@scope = Puppet::Parser::Scope.new() # no parent scope
|
||||
@topscope = @scope
|
||||
@scope.interp = self
|
||||
|
||||
if hash.include?(:facts)
|
||||
facts = hash[:facts]
|
||||
unless facts.is_a?(Hash)
|
||||
raise ArgumentError.new("Facts must be a hash")
|
||||
end
|
||||
|
||||
facts.each { |fact,value|
|
||||
@scope.setvar(fact,value)
|
||||
}
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# evaluate our whole tree
|
||||
def run
|
||||
# evaluate returns a value, but at the top level we only
|
||||
# care about its side effects
|
||||
# i think
|
||||
unless @ast.is_a?(AST) or @ast.is_a?(AST::ASTArray)
|
||||
Puppet.err "Received top-level non-ast '%s' of type %s" %
|
||||
[@ast,@ast.class]
|
||||
raise TypeError.new("Received non-ast '%s' of type %s" %
|
||||
[@ast,@ast.class])
|
||||
end
|
||||
|
||||
begin
|
||||
@ast.evaluate(@scope)
|
||||
rescue Puppet::DevError, Puppet::Error, Puppet::ParseError => except
|
||||
#Puppet.err "File %s, line %s: %s" %
|
||||
# [except.file, except.line, except.message]
|
||||
if Puppet[:debug]
|
||||
puts except.stack
|
||||
end
|
||||
#exit(1)
|
||||
raise
|
||||
rescue => except
|
||||
error = Puppet::DevError.new("%s: %s" %
|
||||
[except.class, except.message])
|
||||
error.stack = caller
|
||||
if Puppet[:debug]
|
||||
puts error.stack
|
||||
end
|
||||
raise error
|
||||
end
|
||||
|
||||
# okay, at this point we have a tree of scopes, and we want to
|
||||
# unzip along that tree, building our structure of objects
|
||||
# to pass to the client
|
||||
# this will be heirarchical, and will (at this point) contain
|
||||
# only TransObjects and TransSettings
|
||||
@topscope.name = "top"
|
||||
@topscope.type = "puppet"
|
||||
begin
|
||||
topbucket = @topscope.to_trans
|
||||
rescue => detail
|
||||
Puppet.warning detail
|
||||
raise
|
||||
end
|
||||
|
||||
# add our settings to the front of the array
|
||||
# at least, for now
|
||||
#@topscope.typesets.each { |setting|
|
||||
# topbucket.unshift setting
|
||||
#}
|
||||
|
||||
# guarantee that settings are at the very top
|
||||
#topbucket.push settingbucket
|
||||
#topbucket.push @scope.to_trans
|
||||
|
||||
#retlist = TransObject.list
|
||||
#Puppet.debug "retobject length is %s" % retlist.length
|
||||
#TransObject.clear
|
||||
return topbucket
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def scope
|
||||
return @scope
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
end
|
||||
#---------------------------------------------------------------
|
||||
end
|
||||
end
|
|
@ -0,0 +1,225 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# $Id$
|
||||
|
||||
# the scanner/lexer
|
||||
|
||||
require 'strscan'
|
||||
require 'puppet'
|
||||
|
||||
|
||||
module Puppet
|
||||
class LexError < RuntimeError; end
|
||||
module Parser
|
||||
#---------------------------------------------------------------
|
||||
class Lexer
|
||||
attr_reader :line, :last, :file
|
||||
|
||||
#%r{\w+} => :WORD,
|
||||
@@tokens = {
|
||||
%r{#.*} => :COMMENT,
|
||||
%r{\[} => :LBRACK,
|
||||
%r{\]} => :RBRACK,
|
||||
%r{\{} => :LBRACE,
|
||||
%r{\}} => :RBRACE,
|
||||
%r{\(} => :LPAREN,
|
||||
%r{\)} => :RPAREN,
|
||||
%r{"} => :DQUOTE,
|
||||
%r{\n} => :RETURN,
|
||||
%r{'} => :SQUOTE,
|
||||
%r{=} => :EQUALS,
|
||||
%r{==} => :ISEQUAL,
|
||||
%r{>=} => :GREATEREQUAL,
|
||||
%r{>} => :GREATERTHAN,
|
||||
%r{<} => :LESSTHAN,
|
||||
%r{<=} => :LESSEQUAL,
|
||||
%r{!=} => :NOTEQUAL,
|
||||
%r{,} => :COMMA,
|
||||
%r{\.} => :DOT,
|
||||
%r{:} => :COLON,
|
||||
%r{;} => :SEMIC,
|
||||
%r{\?} => :QMARK,
|
||||
%r{\\} => :BACKSLASH,
|
||||
%r{=>} => :FARROW,
|
||||
%r{[a-z]\w*} => :NAME,
|
||||
%r{[A-Z]\w*} => :TYPE,
|
||||
%r{[0-9]+} => :NUMBER,
|
||||
%r{\$\w+} => :VARIABLE
|
||||
}
|
||||
|
||||
@@keywords = {
|
||||
"if" => :IF,
|
||||
"elsif" => :ELSIF,
|
||||
"else" => :ELSE,
|
||||
"import" => :IMPORT,
|
||||
"class" => :CLASS,
|
||||
"node" => :NODE,
|
||||
"host" => :NODE,
|
||||
"true" => :BOOLEAN,
|
||||
"false" => :BOOLEAN,
|
||||
"inherits" => :INHERITS,
|
||||
"define" => :DEFINE
|
||||
}
|
||||
|
||||
# scan the whole file
|
||||
# basically just used for testing
|
||||
def fullscan
|
||||
array = []
|
||||
|
||||
self.scan { |token,str|
|
||||
#Puppet.debug("got token '%s' => '%s'" % [token,str])
|
||||
if token.nil?
|
||||
return array
|
||||
else
|
||||
array.push([token,str])
|
||||
end
|
||||
}
|
||||
return array
|
||||
end
|
||||
|
||||
# this is probably pretty damned inefficient...
|
||||
# it'd be nice not to have to load the whole file first...
|
||||
def file=(file)
|
||||
@file = file
|
||||
@line = 1
|
||||
File.open(file) { |of|
|
||||
str = ""
|
||||
of.each { |line| str += line }
|
||||
@scanner = StringScanner.new(str)
|
||||
}
|
||||
end
|
||||
|
||||
def initialize
|
||||
@line = 1
|
||||
@last = ""
|
||||
@scanner = nil
|
||||
@file = nil
|
||||
# AAARRGGGG! okay, regexes in ruby are bloody annoying
|
||||
# no one else has "\n" =~ /\s/
|
||||
@skip = %r{[ \t]+}
|
||||
end
|
||||
|
||||
def rest
|
||||
@scanner.rest
|
||||
end
|
||||
|
||||
# this is the heart of the lexer
|
||||
def scan
|
||||
#Puppet.debug("entering scan")
|
||||
if @scanner.nil?
|
||||
raise TypeError.new("Invalid or empty string")
|
||||
end
|
||||
|
||||
@scanner.skip(@skip)
|
||||
until @scanner.eos? do
|
||||
yielded = false
|
||||
sendbreak = false # gah, this is a nasty hack
|
||||
stoken = nil
|
||||
sregex = nil
|
||||
value = ""
|
||||
|
||||
# first find out which type of token we've got
|
||||
@@tokens.each { |regex,token|
|
||||
# we're just checking, which doesn't advance the scan
|
||||
# pointer
|
||||
tmp = @scanner.check(regex)
|
||||
if tmp.nil?
|
||||
#puppet.debug("did not match %s to '%s'" %
|
||||
# [regex,@scanner.rest])
|
||||
next
|
||||
end
|
||||
|
||||
# find the longest match
|
||||
if tmp.length > value.length
|
||||
value = tmp
|
||||
stoken = token
|
||||
sregex = regex
|
||||
else
|
||||
# we've already got a longer match
|
||||
next
|
||||
end
|
||||
}
|
||||
|
||||
# error out if we didn't match anything at all
|
||||
if stoken.nil?
|
||||
nword = nil
|
||||
if @scanner.rest =~ /^(\S+)/
|
||||
nword = $1
|
||||
elsif@scanner.rest =~ /^(\s+)/
|
||||
nword = $1
|
||||
else
|
||||
nword = @scanner.rest
|
||||
end
|
||||
raise "Could not match '%s'" % nword
|
||||
end
|
||||
|
||||
value = @scanner.scan(sregex)
|
||||
|
||||
if value == ""
|
||||
raise "Didn't match regex on token %s" % stoken
|
||||
end
|
||||
|
||||
# token-specific operations
|
||||
# if this gets much more complicated, it should
|
||||
# be moved up to where the tokens themselves are defined
|
||||
# which will get me about 75% of the way to a lexer generator
|
||||
case stoken
|
||||
when :NAME then
|
||||
wtoken = stoken
|
||||
# we're looking for keywords here
|
||||
if @@keywords.include?(value)
|
||||
wtoken = @@keywords[value]
|
||||
#Puppet.debug("token '%s'" % wtoken)
|
||||
end
|
||||
yield [wtoken,value]
|
||||
@last = value
|
||||
when :NUMBER then
|
||||
yield [:NAME,value]
|
||||
# just throw comments away
|
||||
when :COMMENT then
|
||||
# just throw comments away
|
||||
when :RETURN then
|
||||
@line += 1
|
||||
@scanner.skip(@skip)
|
||||
when :DQUOTE then
|
||||
#Puppet.debug("searching '%s' after '%s'" % [self.rest,value])
|
||||
value = self.slurpstring(value)
|
||||
yield [:QTEXT,value]
|
||||
@last = value
|
||||
#stoken = :QTEXT
|
||||
#Puppet.debug("got string '%s' => '%s'" % [:QTEXT,value])
|
||||
else
|
||||
yield [stoken,value]
|
||||
@last = value
|
||||
#Puppet.debug("got token '%s' => '%s'" % [stoken,value])
|
||||
end
|
||||
@scanner.skip(@skip)
|
||||
end
|
||||
@scanner = nil
|
||||
yield [false,false]
|
||||
end
|
||||
|
||||
# we've encountered an opening quote...
|
||||
# slurp in the rest of the string and return it
|
||||
def slurpstring(quote)
|
||||
#Puppet.debug("searching '%s'" % self.rest)
|
||||
str = @scanner.scan_until(/[^\\]#{quote}/)
|
||||
#str = @scanner.scan_until(/"/)
|
||||
if str.nil?
|
||||
raise Puppet::LexError.new("Unclosed quote after '%s' in '%s'" %
|
||||
[self.last,self.rest])
|
||||
else
|
||||
str.sub!(/#{quote}$/,"")
|
||||
str.gsub!(/\\#{quote}/,quote)
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
def string=(string)
|
||||
@scanner = StringScanner.new(string)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
#parser.rb: grammar.ry
|
||||
# ryacc --output parser grammar
|
||||
|
||||
parser.rb: grammar.ra
|
||||
racc -v -o$@ grammar.ra
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,427 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# $Id$
|
||||
|
||||
# the interpreter
|
||||
#
|
||||
# this builds our virtual pinball machine, into which we'll place our host-specific
|
||||
# information and out of which we'll receive our host-specific configuration
|
||||
|
||||
require 'puppet/transportable'
|
||||
|
||||
module Puppet
|
||||
module Parser
|
||||
class ScopeError < RuntimeError
|
||||
attr_accessor :line, :file
|
||||
end
|
||||
#---------------------------------------------------------------
|
||||
class Scope
|
||||
|
||||
attr_accessor :symtable, :objectable, :parent, :level, :interp
|
||||
attr_accessor :name, :type
|
||||
|
||||
# i don't really know how to deal with a global scope yet, so
|
||||
# i'm leaving it disabled
|
||||
@@global = nil
|
||||
|
||||
@@hosttable = {}
|
||||
@@settingtable = []
|
||||
@@declarative = true
|
||||
|
||||
#------------------------------------------------------------
|
||||
def Scope.declarative
|
||||
return @@declarative
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def Scope.declarative=(val)
|
||||
@@declarative = val
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def Scope.global
|
||||
return @@global
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def child=(scope)
|
||||
@children.push(scope)
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def declarative
|
||||
return @@declarative
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def initialize(parent = nil, declarative = true)
|
||||
@parent = parent
|
||||
if @parent.nil?
|
||||
@level = 1
|
||||
@@declarative = declarative
|
||||
else
|
||||
@parent.child = self
|
||||
@level = @parent.level + 1
|
||||
@interp = @parent.interp
|
||||
end
|
||||
|
||||
@children = []
|
||||
|
||||
@symtable = Hash.new(nil)
|
||||
@typetable = Hash.new(nil)
|
||||
|
||||
# the defaultstable is a hash of hashes
|
||||
@defaultstable = Hash.new { |dhash,type|
|
||||
dhash[type] = Hash.new(nil)
|
||||
}
|
||||
|
||||
@objectable = Hash.new { |typehash,typekey|
|
||||
#hash[key] = TransObject.new(key)
|
||||
typehash[typekey] = Hash.new { |namehash, namekey|
|
||||
#Puppet.debug("Creating iobject with name %s and type %s" %
|
||||
# [namekey,typekey])
|
||||
namehash[namekey] = TransObject.new(namekey,typekey)
|
||||
@children.push namehash[namekey]
|
||||
|
||||
# this has to be last, because the return value of the
|
||||
# block is the actual hash
|
||||
namehash[namekey]
|
||||
}
|
||||
}
|
||||
@map = {
|
||||
"variable" => @symtable,
|
||||
"type" => @typetable,
|
||||
"object" => @objectable,
|
||||
"defaults" => @defaultstable
|
||||
}
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# this method just abstracts the upwards-recursive nature of
|
||||
# name resolution
|
||||
# because different tables are different depths (e.g., flat, or
|
||||
# hash of hashes), we pass in a code snippet that gets passed
|
||||
# the table. It is assumed that the code snippet already has
|
||||
# the name in it
|
||||
def lookup(type,sub)
|
||||
table = @map[type]
|
||||
if table.nil?
|
||||
error = Puppet::ParseError.new(
|
||||
"Could not retrieve %s table at level %s" % [type,self.level]
|
||||
)
|
||||
error.stack = caller
|
||||
raise error
|
||||
end
|
||||
|
||||
if sub.is_a?(Proc) and obj = sub.call(table)
|
||||
return obj
|
||||
elsif table.include?(sub)
|
||||
return table[sub]
|
||||
elsif ! @parent.nil?
|
||||
return @parent.lookup(type,sub)
|
||||
else
|
||||
return :undefined
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def lookuphost(name)
|
||||
if @@hosttable.include?(name)
|
||||
return @@hosttable[name]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# collect all of the defaults set at any higher scopes
|
||||
# this is a different type of lookup because it's additive --
|
||||
# it collects all of the defaults, with defaults in closer scopes
|
||||
# overriding those in later scopes
|
||||
def lookupdefaults(type)
|
||||
values = {}
|
||||
# first collect the values from the parents
|
||||
unless @parent.nil?
|
||||
@parent.lookupdefaults(type).each { |var,value|
|
||||
values[var] = value
|
||||
}
|
||||
end
|
||||
|
||||
# then override them with any current values
|
||||
# this should probably be done differently
|
||||
if @defaultstable.include?(type)
|
||||
@defaultstable[type].each { |var,value|
|
||||
values[var] = value
|
||||
}
|
||||
end
|
||||
Puppet.debug "Got defaults for %s: %s" %
|
||||
[type,values.inspect]
|
||||
return values
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def lookuptype(name)
|
||||
Puppet.debug "Looking up type %s" % name
|
||||
value = self.lookup("type",name)
|
||||
if value == :undefined
|
||||
return nil
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# slightly different, because we're looking through a hash of hashes
|
||||
def lookupobject(name,type)
|
||||
Puppet.debug "Looking up object %s of type %s" % [name, type]
|
||||
sub = proc { |table|
|
||||
if table.include?(type)
|
||||
if type[type].include?(name)
|
||||
type[type][name]
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
}
|
||||
value = self.lookup("object",sub)
|
||||
if value == :undefined
|
||||
return nil
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def lookupvar(name)
|
||||
Puppet.debug "Looking up variable %s" % name
|
||||
value = self.lookup("variable", name)
|
||||
if value == :undefined
|
||||
error = Puppet::ParseError.new(
|
||||
"Undefined variable '%s'" % name
|
||||
)
|
||||
error.stack = caller
|
||||
raise error
|
||||
else
|
||||
#Puppet.debug "Value of '%s' is '%s'" % [name,value]
|
||||
return value
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def newscope
|
||||
Puppet.debug "Creating new scope, level %s" % [self.level + 1]
|
||||
return Puppet::Parser::Scope.new(self)
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def setdefaults(type,params)
|
||||
table = @defaultstable[type]
|
||||
|
||||
# if we got a single param, it'll be in its own array
|
||||
unless params[0].is_a?(Array)
|
||||
params = [params]
|
||||
end
|
||||
|
||||
params.each { |ary|
|
||||
Puppet.debug "Default for %s is %s => %s" %
|
||||
[type,ary[0].inspect,ary[1].inspect]
|
||||
if @@declarative
|
||||
if table.include?(ary[0])
|
||||
error = Puppet::ParseError.new(
|
||||
"Default already defined for %s { %s }" %
|
||||
[type,ary[0]]
|
||||
)
|
||||
error.stack = caller
|
||||
raise error
|
||||
end
|
||||
else
|
||||
if table.include?(ary[0])
|
||||
# we should maybe allow this warning to be turned off...
|
||||
Puppet.warning "Replacing default for %s { %s }" %
|
||||
[type,ary[0]]
|
||||
end
|
||||
end
|
||||
table[ary[0]] = ary[1]
|
||||
}
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def sethost(name,host)
|
||||
@@hosttable[name] = host
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def settype(name,ltype)
|
||||
@typetable[name] = ltype
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# when we have an 'eval' function, we should do that instead
|
||||
# for now, we only support variables in strings
|
||||
def strinterp(string)
|
||||
newstring = string.dup
|
||||
regex = Regexp.new('\$\{(\w+)\}|\$(\w+)')
|
||||
#Puppet.debug("interpreting '%s'" % string)
|
||||
while match = regex.match(newstring) do
|
||||
if match[1]
|
||||
newstring.sub!(regex,self.lookupvar(match[1]))
|
||||
elsif match[2]
|
||||
newstring.sub!(regex,self.lookupvar(match[2]))
|
||||
else
|
||||
raise 'fuh?'
|
||||
end
|
||||
end
|
||||
#Puppet.debug("result is '%s'" % newstring)
|
||||
return newstring
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# this is kind of quirky, because it doesn't differentiate between
|
||||
# creating a new object and adding params to an existing object
|
||||
# it doesn't solve the real problem, though: cases like file recursion,
|
||||
# where one statement explicitly modifies an object, and another
|
||||
# statement modifies it because of recursion
|
||||
def setobject(type, name, params, file, line)
|
||||
obj = self.lookupobject(name,type)
|
||||
if obj == :undefined or obj.nil?
|
||||
obj = @objectable[type][name]
|
||||
|
||||
# only set these if we've created the object, which is the
|
||||
# most common case
|
||||
obj.file = file
|
||||
obj.line = line
|
||||
end
|
||||
|
||||
# now add the params to whatever object we've found, whether
|
||||
# it was in a higher scope or we just created it
|
||||
# it will not be obvious where these parameters are from, that is,
|
||||
# which file they're in or whatever
|
||||
params.each { |var,value|
|
||||
obj[var] = value
|
||||
}
|
||||
return obj
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
def setvar(name,value)
|
||||
Puppet.debug "Setting '%s' to '%s' at level %s" %
|
||||
[name.inspect,value,self.level]
|
||||
if @@declarative and @symtable.include?(name)
|
||||
error = Puppet::ParseError.new(
|
||||
"Cannot reassign variable %s" % name
|
||||
)
|
||||
error.stack = caller
|
||||
raise error
|
||||
else
|
||||
if @symtable.include?(name)
|
||||
Puppet.warning "Reassigning %s to %s" % [name,value]
|
||||
end
|
||||
@symtable[name] = value
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------
|
||||
# I'm pretty sure this method could be obviated, but it doesn't
|
||||
# really seem worth it
|
||||
def to_trans
|
||||
Puppet.debug "Translating scope %s at level %s" %
|
||||
[self.object_id,self.level]
|
||||
|
||||
results = []
|
||||
|
||||
@children.each { |child|
|
||||
if child.is_a?(Scope)
|
||||
cresult = child.to_trans
|
||||
Puppet.debug "Got %s from scope %s" %
|
||||
[cresult.class,child.object_id]
|
||||
|
||||
# get rid of the arrayness
|
||||
unless cresult.is_a?(TransBucket)
|
||||
cresult.each { |result|
|
||||
results.push(result)
|
||||
}
|
||||
else
|
||||
results.push(cresult)
|
||||
end
|
||||
elsif child.is_a?(TransObject)
|
||||
results.push(child)
|
||||
else
|
||||
error = Puppet::DevError.new(
|
||||
"Puppet::Parse::Scope cannot handle objects of type %s" %
|
||||
child.class
|
||||
)
|
||||
error.stack = caller
|
||||
raise error
|
||||
end
|
||||
}
|
||||
results = results.reject { |child|
|
||||
# if a scope didn't result in any objects, we get some nils
|
||||
# just get rid of them
|
||||
child.nil?
|
||||
}
|
||||
|
||||
# if we have a name and type, then make a TransBucket, which
|
||||
# becomes a component
|
||||
# else, just stack all of the objects into the current bucket
|
||||
if defined? @name
|
||||
bucket = TransBucket.new
|
||||
bucket.name = @name
|
||||
|
||||
# it'd be nice not to have to do this...
|
||||
results.each { |result|
|
||||
#Puppet.debug "Result type is %s" % result.class
|
||||
bucket.push(result)
|
||||
}
|
||||
if defined? @type
|
||||
bucket.type = @type
|
||||
else
|
||||
error = Puppet::ParseError.new(
|
||||
"No type for scope %s" % @name
|
||||
)
|
||||
error.stack = caller
|
||||
raise error
|
||||
end
|
||||
Puppet.debug "TransBucket with name %s and type %s in scope %s" %
|
||||
[@name,@type,self.object_id]
|
||||
|
||||
# now find metaparams
|
||||
@symtable.each { |var,value|
|
||||
if Puppet::Type.metaparam?(var.intern)
|
||||
#Puppet.debug("Adding metaparam %s" % var)
|
||||
bucket.param(var,value)
|
||||
else
|
||||
#Puppet.debug("%s is not a metaparam" % var)
|
||||
end
|
||||
}
|
||||
#Puppet.debug "Returning bucket %s from scope %s" %
|
||||
# [bucket.name,self.object_id]
|
||||
return bucket
|
||||
else
|
||||
#Puppet.debug "nameless scope; just returning a list"
|
||||
return results
|
||||
end
|
||||
end
|
||||
#------------------------------------------------------------
|
||||
end
|
||||
#---------------------------------------------------------------
|
||||
end
|
||||
end
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/local/bin/ruby -w
|
||||
|
||||
# $Id$
|
||||
|
||||
# the server
|
||||
#
|
||||
# allow things to connect to us and communicate, and stuff
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/daemon'
|
||||
require 'puppet/servlet'
|
||||
require 'puppet/master'
|
||||
require 'puppet/ca'
|
||||
|
||||
$noservernetworking = false
|
||||
|
||||
begin
|
||||
require 'webrick'
|
||||
require 'webrick/https'
|
||||
require 'cgi'
|
||||
require 'xmlrpc/server'
|
||||
require 'xmlrpc/client'
|
||||
rescue LoadError => detail
|
||||
$noservernetworking = detail
|
||||
end
|
||||
|
||||
module Puppet
|
||||
class ServerError < RuntimeError; end
|
||||
#---------------------------------------------------------------
|
||||
if $noservernetworking
|
||||
Puppet.err "Could not create server: %s" % $noservernetworking
|
||||
else
|
||||
class ServerStatus
|
||||
attr_reader :ca
|
||||
|
||||
def self.interface
|
||||
XMLRPC::Service::Interface.new("status") { |iface|
|
||||
iface.add_method("int status()")
|
||||
}
|
||||
end
|
||||
|
||||
def initialize(hash = {})
|
||||
end
|
||||
|
||||
def status(status = nil, request = nil)
|
||||
Puppet.warning "Returning status"
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
class Server < WEBrick::HTTPServer
|
||||
include Puppet::Daemon
|
||||
|
||||
# a bit of a hack for now, but eh, wadda ya gonna do?
|
||||
@@handlers = {
|
||||
:Master => Puppet::Master,
|
||||
:CA => Puppet::CA,
|
||||
:Status => Puppet::ServerStatus
|
||||
}
|
||||
|
||||
def self.inithandler(handler,args)
|
||||
unless @@handlers.include?(handler)
|
||||
raise ServerError, "Invalid handler %s" % handler
|
||||
end
|
||||
|
||||
hclass = @@handlers[handler]
|
||||
|
||||
obj = hclass.new(args)
|
||||
return obj
|
||||
end
|
||||
|
||||
def initialize(hash = {})
|
||||
hash[:Port] ||= Puppet[:masterport]
|
||||
hash[:Logger] ||= self.httplog
|
||||
hash[:AccessLog] ||= [
|
||||
[ self.httplog, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
|
||||
[ self.httplog, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
|
||||
]
|
||||
|
||||
if hash.include?(:Handlers)
|
||||
unless hash[:Handlers].is_a?(Hash)
|
||||
raise ServerError, "Handlers must have arguments"
|
||||
end
|
||||
|
||||
@handlers = hash[:Handlers].collect { |handler, args|
|
||||
self.class.inithandler(handler, args)
|
||||
}
|
||||
else
|
||||
raise ServerError, "A server must have handlers"
|
||||
end
|
||||
|
||||
# okay, i need to retrieve my cert and set it up, somehow
|
||||
# the default case will be that i'm also the ca
|
||||
if ca = @handlers.find { |handler| handler.is_a?(Puppet::CA) }
|
||||
@driver = ca
|
||||
@secureinit = true
|
||||
self.fqdn
|
||||
end
|
||||
|
||||
unless self.readcert
|
||||
unless self.requestcert
|
||||
raise Puppet::Error, "Cannot start without certificates"
|
||||
end
|
||||
end
|
||||
|
||||
hash[:SSLCertificate] = @cert
|
||||
hash[:SSLPrivateKey] = @key
|
||||
hash[:SSLStartImmediately] = true
|
||||
hash[:SSLEnable] = true
|
||||
hash[:SSLCACertificateFile] = @cacertfile
|
||||
hash[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_NONE
|
||||
hash[:SSLCertName] = nil
|
||||
|
||||
super(hash)
|
||||
|
||||
# this creates a new servlet for every connection,
|
||||
# but all servlets have the same list of handlers
|
||||
# thus, the servlets can have their own state -- passing
|
||||
# around the requests and such -- but the handlers
|
||||
# have a global state
|
||||
|
||||
# mount has to be called after the server is initialized
|
||||
self.mount("/RPC2", Puppet::Servlet, @handlers)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------
|
||||
end
|
|
@ -0,0 +1,110 @@
|
|||
require 'xmlrpc/server'
|
||||
|
||||
module Puppet
|
||||
class ServletError < RuntimeError; end
|
||||
class Servlet < XMLRPC::WEBrickServlet
|
||||
attr_accessor :request
|
||||
|
||||
# this is just a duplicate of the normal method; it's here for
|
||||
# debugging when i need it
|
||||
def self.get_instance(server, *options)
|
||||
self.new(server, *options)
|
||||
end
|
||||
|
||||
def initialize(server, handlers)
|
||||
#Puppet.info server.inspect
|
||||
|
||||
# the servlet base class does not consume any arguments
|
||||
# and its BasicServer base class only accepts a 'class_delim'
|
||||
# option which won't change in Puppet at all
|
||||
# thus, we don't need to pass any args to our base class,
|
||||
# and we can consume them all ourselves
|
||||
super()
|
||||
|
||||
handlers.each { |handler|
|
||||
Puppet.debug "adding handler for %s" % handler.class
|
||||
self.add_handler(handler.class.interface, handler)
|
||||
}
|
||||
|
||||
@request = nil
|
||||
self.set_service_hook { |obj, *args|
|
||||
#raise "crap!"
|
||||
if @request
|
||||
args.push @request
|
||||
#obj.call(args, @request)
|
||||
end
|
||||
begin
|
||||
obj.call(*args)
|
||||
rescue => detail
|
||||
Puppet.warning obj.inspect
|
||||
Puppet.err "Could not call: %s" % detail.to_s
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def service(request, response)
|
||||
@request = request
|
||||
if @request.client_cert
|
||||
Puppet.info "client cert is %s" % @request.client_cert
|
||||
end
|
||||
if @request.server_cert
|
||||
Puppet.info "server cert is %s" % @request.server_cert
|
||||
end
|
||||
#p @request
|
||||
begin
|
||||
super
|
||||
rescue => detail
|
||||
Puppet.err "Could not service request: %s: %s" %
|
||||
[detail.class, detail]
|
||||
end
|
||||
@request = nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# this is pretty much just a copy of the original method but with more
|
||||
# feedback
|
||||
def dispatch(methodname, *args)
|
||||
#Puppet.warning "dispatch on %s called with %s" %
|
||||
# [methodname, args.inspect]
|
||||
for name, obj in @handler
|
||||
if obj.kind_of? Proc
|
||||
unless methodname == name
|
||||
Puppet.debug "obj is proc but %s != %s" %
|
||||
[methodname, name]
|
||||
next
|
||||
end
|
||||
else
|
||||
unless methodname =~ /^#{name}(.+)$/
|
||||
Puppet.debug "methodname did not match"
|
||||
next
|
||||
end
|
||||
unless obj.respond_to? $1
|
||||
Puppet.debug "methodname does not respond to %s" % $1
|
||||
next
|
||||
end
|
||||
obj = obj.method($1)
|
||||
end
|
||||
|
||||
if check_arity(obj, args.size)
|
||||
if @service_hook.nil?
|
||||
return obj.call(*args)
|
||||
else
|
||||
return @service_hook.call(obj, *args)
|
||||
end
|
||||
else
|
||||
Puppet.debug "arity is incorrect"
|
||||
end
|
||||
end
|
||||
|
||||
if @default_handler.nil?
|
||||
raise XMLRPC::FaultException.new(
|
||||
ERR_METHOD_MISSING,
|
||||
"Method #{methodname} missing or wrong number of parameters!"
|
||||
)
|
||||
else
|
||||
@default_handler.call(methodname, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -409,9 +409,13 @@ class Type < Puppet::Element
|
|||
# does the name reflect a valid parameter?
|
||||
def self.validparameter?(name)
|
||||
unless defined? @parameters
|
||||
raise "Class %s has not defined parameters" % self
|
||||
raise Puppet::DevError, "Class %s has not defined parameters" % self
|
||||
end
|
||||
if @parameters.include?(name) or @@metaparams.include?(name)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
return @parameters.include?(name)
|
||||
end
|
||||
#---------------------------------------------------------------
|
||||
|
||||
|
@ -474,6 +478,7 @@ class Type < Puppet::Element
|
|||
raise Puppet::Error.new("Got nil value for %s" % name)
|
||||
end
|
||||
if Puppet::Type.metaparam?(name)
|
||||
@parameters[name] = value
|
||||
# call the metaparam method
|
||||
self.send(("meta" + name.id2name + "="),value)
|
||||
elsif stateklass = self.class.validstate?(name)
|
||||
|
|
|
@ -4,14 +4,42 @@
|
|||
|
||||
require 'digest/md5'
|
||||
require 'etc'
|
||||
require 'uri'
|
||||
require 'fileutils'
|
||||
require 'puppet/type/state'
|
||||
require 'puppet/fileserver'
|
||||
|
||||
module Puppet
|
||||
# we first define all of the state that our file will use
|
||||
# because the objects must be defined for us to use them in our
|
||||
# definition of the file object
|
||||
class State
|
||||
class PFileType < Puppet::State
|
||||
require 'etc'
|
||||
@doc = "A read-only state to check the file type."
|
||||
@name = :type
|
||||
|
||||
def should=(value)
|
||||
raise Puppet::Error, ":type is read-only"
|
||||
end
|
||||
|
||||
def retrieve
|
||||
if stat = @parent.stat(true)
|
||||
@is = stat.ftype
|
||||
else
|
||||
@is = -1
|
||||
end
|
||||
|
||||
# so this state is never marked out of sync
|
||||
@should = @is
|
||||
end
|
||||
|
||||
|
||||
def sync
|
||||
raise Puppet::Error, ":type is read-only"
|
||||
end
|
||||
end
|
||||
|
||||
class PFileCreate < Puppet::State
|
||||
require 'etc'
|
||||
@doc = "Whether to create files that don't currently exist.
|
||||
|
@ -209,7 +237,7 @@ module Puppet
|
|||
if @is == -1
|
||||
# if they're copying, then we won't worry about the file
|
||||
# not existing yet
|
||||
unless @parent.state(:copy) or @parent.state(:create)
|
||||
unless @parent.state(:source) or @parent.state(:create)
|
||||
Puppet.warning "File %s does not exist -- cannot checksum" %
|
||||
@parent.name
|
||||
end
|
||||
|
@ -280,16 +308,16 @@ module Puppet
|
|||
|
||||
def retrieve
|
||||
# if we're not root, then we can't chown anyway
|
||||
unless Process.uid == 0
|
||||
@parent.delete(self.name)
|
||||
@should = nil
|
||||
@is = nil
|
||||
unless defined? @@notified
|
||||
Puppet.notice "Cannot manage ownership unless running as root"
|
||||
@@notified = true
|
||||
return
|
||||
end
|
||||
end
|
||||
# unless Process.uid == 0
|
||||
# @parent.delete(self.name)
|
||||
# @should = nil
|
||||
# @is = nil
|
||||
# unless defined? @@notified
|
||||
# Puppet.notice "Cannot manage ownership unless running as root"
|
||||
# @@notified = true
|
||||
# return
|
||||
# end
|
||||
# end
|
||||
|
||||
unless stat = @parent.stat(true)
|
||||
@is = -1
|
||||
|
@ -307,7 +335,9 @@ module Puppet
|
|||
Puppet.notice "Cannot manage ownership unless running as root"
|
||||
#@parent.delete(self.name)
|
||||
@@notified = true
|
||||
return
|
||||
end
|
||||
if @parent.state(:owner)
|
||||
@parent.delete(:owner)
|
||||
end
|
||||
raise Puppet::Error.new(
|
||||
"Cannot manage ownership unless running as root"
|
||||
|
@ -588,54 +618,172 @@ module Puppet
|
|||
end
|
||||
end
|
||||
|
||||
class PFileCopy < Puppet::State
|
||||
class PFileSource < Puppet::State
|
||||
attr_accessor :source, :local
|
||||
@doc = "Copy a file over the current file. Uses `checksum` to
|
||||
determine when a file should be copied. This is largely a support
|
||||
state for the `source` parameter, which is what should generally
|
||||
be used instead of `copy`."
|
||||
@name = :copy
|
||||
@name = :source
|
||||
|
||||
def desc2hash(line, params)
|
||||
args = {}
|
||||
|
||||
values = line.split("\t").collect { |value|
|
||||
if value =~ /^[0-9]+$/
|
||||
value.to_i
|
||||
else
|
||||
value
|
||||
end
|
||||
}
|
||||
|
||||
params.zip(values).each { |param, value|
|
||||
args[param] = value
|
||||
}
|
||||
|
||||
if args[:type] == "directory"
|
||||
args.delete(:checksum)
|
||||
end
|
||||
args
|
||||
end
|
||||
|
||||
def hash2child(hash, source, recurse)
|
||||
# "/" == self
|
||||
if hash[:name] == "/"
|
||||
if hash[:type] == "directory"
|
||||
else
|
||||
self[:source] = source
|
||||
end
|
||||
hash.each { |param, value|
|
||||
next if param == :name
|
||||
next if param == :type
|
||||
|
||||
unless self.state(param)
|
||||
self[param] = value
|
||||
end
|
||||
}
|
||||
if source =~ /Filesourcetest/
|
||||
p self
|
||||
end
|
||||
# we can now skip this object, and the rest is
|
||||
# pretty much related to children
|
||||
return
|
||||
end
|
||||
|
||||
name = File.join(self.name, hash[:name])
|
||||
if child = @children.find { |child|
|
||||
child.name == name }
|
||||
else # the child does not yet exist
|
||||
#hash.delete(:name)
|
||||
sum = nil
|
||||
if hash[:type] == "directory"
|
||||
hash[:create] = "directory"
|
||||
hash[:source] = @parameters[:source] + hash[:name]
|
||||
hash[:recurse] = recurse
|
||||
else
|
||||
hash[:source] = source + hash[:name]
|
||||
#sum = hash[:checksum]
|
||||
#hash.delete(:checksum)
|
||||
end
|
||||
hash.delete(:type)
|
||||
|
||||
name = hash[:name].sub(/^\//, '') # rm leading /
|
||||
hash.delete(:name)
|
||||
|
||||
Puppet.warning "Found new file %s under %s" %
|
||||
[name.inspect, self.name]
|
||||
self.newchild(name, hash)
|
||||
end
|
||||
end
|
||||
|
||||
def describe
|
||||
source = @source
|
||||
|
||||
sourceobj, path = @parent.uri2obj(source)
|
||||
|
||||
server = sourceobj.server
|
||||
|
||||
desc = server.describe(path)
|
||||
|
||||
args = {}
|
||||
Puppet::Type::PFile::PINPARAMS.zip(desc.split("\t")).each { |param, value|
|
||||
if value =~ /^[0-9]+$/
|
||||
value = value.to_i
|
||||
end
|
||||
args[param] = value
|
||||
}
|
||||
|
||||
return args
|
||||
end
|
||||
|
||||
def retrieve
|
||||
sum = nil
|
||||
if sum = @parent.state(:checksum)
|
||||
if sum.is
|
||||
if sum.is == -1
|
||||
sum.retrieve
|
||||
|
||||
@stats = self.describe
|
||||
|
||||
@stats.each { |stat, value|
|
||||
next if stat == :checksum
|
||||
next if stat == :type
|
||||
|
||||
unless @parent.argument?(stat)
|
||||
if state = @parent.state(stat)
|
||||
state.should = value
|
||||
else
|
||||
@parent[stat] = value
|
||||
end
|
||||
end
|
||||
}
|
||||
case @stats[:type]
|
||||
when "file":
|
||||
if sum = @parent.state(:checksum)
|
||||
if sum.is
|
||||
if sum.is == -1
|
||||
sum.retrieve
|
||||
end
|
||||
@is = sum.is
|
||||
else
|
||||
@is = -1
|
||||
end
|
||||
@is = sum.is
|
||||
else
|
||||
@is = -1
|
||||
end
|
||||
|
||||
@should = @stats[:checksum]
|
||||
|
||||
if state = @parent.state(:create)
|
||||
unless state.should == "file"
|
||||
Puppet.notice(
|
||||
"File %s had both create and source enabled" %
|
||||
@parent.name
|
||||
)
|
||||
@parent.delete(:create)
|
||||
end
|
||||
end
|
||||
when "directory":
|
||||
if state = @parent.state(:create)
|
||||
unless state.should == "directory"
|
||||
state.should = "directory"
|
||||
end
|
||||
else
|
||||
@parent[:create] = "directory"
|
||||
@parent.state(:create).retrieve
|
||||
end
|
||||
# we'll let the :create state do our work
|
||||
@should = true
|
||||
@is = true
|
||||
else
|
||||
@is = -1
|
||||
Puppet.err "Cannot use files of type %s as sources" %
|
||||
@stats[:type]
|
||||
@should = true
|
||||
@is = true
|
||||
end
|
||||
end
|
||||
|
||||
def should=(source)
|
||||
@local = true # redundant for now
|
||||
@source = source
|
||||
type = Puppet::Type.type(:file)
|
||||
|
||||
sourcesum = nil
|
||||
stat = File.stat(@source)
|
||||
case stat.ftype
|
||||
when "file":
|
||||
unless sourcesum = type[@source].state(:checksum).is
|
||||
raise Puppet::Error.new(
|
||||
"Could not retrieve checksum of source %s" %
|
||||
@source
|
||||
)
|
||||
end
|
||||
when "directory":
|
||||
raise Puppet::Error.new(
|
||||
"Somehow got told to copy dir %s" % @parent.name)
|
||||
else
|
||||
raise Puppet::Error.new(
|
||||
"Cannot use files of type %s as source" % stat.ftype)
|
||||
end
|
||||
|
||||
@should = sourcesum
|
||||
# stupid hack for now; it'll get overriden
|
||||
@should = source
|
||||
end
|
||||
|
||||
def sync
|
||||
|
@ -673,64 +821,140 @@ module Puppet
|
|||
@backed = true
|
||||
end
|
||||
|
||||
unless @stats[:type] == "file"
|
||||
raise Puppet::DevError, "Got told to copy non-file %s" %
|
||||
@parent.name
|
||||
end
|
||||
|
||||
sourceobj, path = @parent.uri2obj(@source)
|
||||
|
||||
contents = sourceobj.server.retrieve(path)
|
||||
|
||||
unless sourceobj.server.local
|
||||
contents = CGI.unescape(contents)
|
||||
end
|
||||
|
||||
if contents == ""
|
||||
Puppet.notice "Could not retrieve contents for %s" %
|
||||
@source
|
||||
end
|
||||
|
||||
begin
|
||||
if FileTest.exists?(@parent.name)
|
||||
if FileTest.exists?(@parent.name + bak)
|
||||
Puppet.warning "Deleting backup of %s" %
|
||||
@parent.name
|
||||
File.unlink(@parent.name + bak)
|
||||
end
|
||||
|
||||
# rename the existing one
|
||||
File.rename(
|
||||
@parent.name,
|
||||
@parent.name + ".puppet-bak"
|
||||
)
|
||||
# move the new file into place
|
||||
args = [@parent.name,
|
||||
File::CREAT | File::WRONLY | File::TRUNC]
|
||||
|
||||
# try to create it with the correct modes to start
|
||||
# we should also be changing our effective uid/gid, but...
|
||||
if @parent[:mode]
|
||||
args.push @parent[:mode]
|
||||
end
|
||||
File.open(*args) { |f|
|
||||
f.print contents
|
||||
}
|
||||
# if we've made a backup, then delete the old file
|
||||
if @backed
|
||||
#Puppet.err "Unlinking backup"
|
||||
File.unlink(@parent.name + bak)
|
||||
#else
|
||||
#Puppet.err "Not unlinking backup"
|
||||
end
|
||||
else
|
||||
# the easy case
|
||||
args = [@parent.name,
|
||||
File::CREAT | File::WRONLY | File::TRUNC]
|
||||
|
||||
# try to create it with the correct modes to start
|
||||
# we should also be changing our effective uid/gid, but...
|
||||
if @parent[:mode]
|
||||
args.push @parent[:mode]
|
||||
end
|
||||
File.open(*args) { |f|
|
||||
f.print contents
|
||||
}
|
||||
end
|
||||
rescue => detail
|
||||
# since they said they want a backup, let's error out
|
||||
# if we couldn't make one
|
||||
error = Puppet::Error.new("Could not copy %s to %s: %s" %
|
||||
[@source, @parent.name, detail.message])
|
||||
raise error
|
||||
end
|
||||
|
||||
#Puppet.notice "@is: %s; @should: %s" % [@is,@should]
|
||||
#Puppet.err "@is: %s; @should: %s" % [@is,@should]
|
||||
# okay, we've now got whatever backing up done we might need
|
||||
# so just copy the files over
|
||||
if @local
|
||||
stat = File.stat(@source)
|
||||
case stat.ftype
|
||||
when "file":
|
||||
begin
|
||||
if FileTest.exists?(@parent.name)
|
||||
# get the file here
|
||||
FileUtils.cp(@source, @parent.name + ".tmp")
|
||||
if FileTest.exists?(@parent.name + bak)
|
||||
Puppet.warning "Deleting backup of %s" %
|
||||
|
||||
f = false
|
||||
if f
|
||||
if @local
|
||||
stat = File.stat(@source)
|
||||
case stat.ftype
|
||||
when "file":
|
||||
begin
|
||||
if FileTest.exists?(@parent.name)
|
||||
# get the file here
|
||||
FileUtils.cp(@source, @parent.name + ".tmp")
|
||||
if FileTest.exists?(@parent.name + bak)
|
||||
Puppet.warning "Deleting backup of %s" %
|
||||
@parent.name
|
||||
File.unlink(@parent.name + bak)
|
||||
end
|
||||
# rename the existing one
|
||||
File.rename(
|
||||
@parent.name,
|
||||
@parent.name + ".puppet-bak"
|
||||
)
|
||||
# move the new file into place
|
||||
File.rename(
|
||||
@parent.name + ".tmp",
|
||||
@parent.name
|
||||
File.unlink(@parent.name + bak)
|
||||
)
|
||||
# if we've made a backup, then delete the old file
|
||||
if @backed
|
||||
#Puppet.err "Unlinking backup"
|
||||
File.unlink(@parent.name + bak)
|
||||
#else
|
||||
#Puppet.err "Not unlinking backup"
|
||||
end
|
||||
else
|
||||
# the easy case
|
||||
FileUtils.cp(@source, @parent.name)
|
||||
end
|
||||
# rename the existing one
|
||||
File.rename(
|
||||
@parent.name,
|
||||
@parent.name + ".puppet-bak"
|
||||
)
|
||||
# move the new file into place
|
||||
File.rename(
|
||||
@parent.name + ".tmp",
|
||||
@parent.name
|
||||
)
|
||||
# if we've made a backup, then delete the old file
|
||||
if @backed
|
||||
#Puppet.err "Unlinking backup"
|
||||
File.unlink(@parent.name + bak)
|
||||
#else
|
||||
#Puppet.err "Not unlinking backup"
|
||||
end
|
||||
else
|
||||
# the easy case
|
||||
FileUtils.cp(@source, @parent.name)
|
||||
rescue => detail
|
||||
# since they said they want a backup, let's error out
|
||||
# if we couldn't make one
|
||||
error = Puppet::Error.new("Could not copy %s to %s: %s" %
|
||||
[@source, @parent.name, detail.message])
|
||||
raise error
|
||||
end
|
||||
rescue => detail
|
||||
# since they said they want a backup, let's error out
|
||||
# if we couldn't make one
|
||||
error = Puppet::Error.new("Could not copy %s to %s: %s" %
|
||||
[@source, @parent.name, detail.message])
|
||||
raise error
|
||||
when "directory":
|
||||
raise Puppet::Error.new(
|
||||
"Somehow got told to copy directory %s" %
|
||||
@parent.name)
|
||||
when "link":
|
||||
dest = File.readlink(@source)
|
||||
Puppet::State::PFileLink.create(@dest,@parent.path)
|
||||
else
|
||||
raise Puppet::Error.new(
|
||||
"Cannot use files of type %s as source" % stat.ftype)
|
||||
end
|
||||
when "directory":
|
||||
raise Puppet::Error.new(
|
||||
"Somehow got told to copy directory %s" %
|
||||
@parent.name)
|
||||
when "link":
|
||||
dest = File.readlink(@source)
|
||||
Puppet::State::PFileLink.create(@dest,@parent.path)
|
||||
else
|
||||
raise Puppet::Error.new(
|
||||
"Cannot use files of type %s as source" % stat.ftype)
|
||||
raise Puppet::Error.new("Somehow got a non-local source")
|
||||
end
|
||||
else
|
||||
raise Puppet::Error.new("Somehow got a non-local source")
|
||||
end
|
||||
return :file_changed
|
||||
end
|
||||
|
@ -746,18 +970,19 @@ module Puppet
|
|||
@states = [
|
||||
Puppet::State::PFileCreate,
|
||||
Puppet::State::PFileChecksum,
|
||||
Puppet::State::PFileCopy,
|
||||
Puppet::State::PFileSource,
|
||||
Puppet::State::PFileUID,
|
||||
Puppet::State::PFileGroup,
|
||||
Puppet::State::PFileMode
|
||||
Puppet::State::PFileMode,
|
||||
Puppet::State::PFileType
|
||||
]
|
||||
|
||||
@parameters = [
|
||||
:path,
|
||||
:backup,
|
||||
:linkmaker,
|
||||
:recurse,
|
||||
:source,
|
||||
:recurse,
|
||||
:filebucket
|
||||
]
|
||||
|
||||
|
@ -782,7 +1007,7 @@ module Puppet
|
|||
*file* is supported as a protocol)."
|
||||
|
||||
@paramdoc[:filebucket] = "A repository for backing up files, including
|
||||
over the network. Argument must the name of an existing
|
||||
over the network. Argument must be the name of an existing
|
||||
filebucket."
|
||||
|
||||
@name = :file
|
||||
|
@ -790,11 +1015,12 @@ module Puppet
|
|||
|
||||
@depthfirst = false
|
||||
|
||||
if Process.uid == 0
|
||||
@@pinparams = [:mode, :owner, :group, :checksum]
|
||||
else
|
||||
@@pinparams = [:mode, :group, :checksum]
|
||||
end
|
||||
#if Process.uid == 0
|
||||
@@pinparams = [:mode, :type, :owner, :group, :checksum]
|
||||
PINPARAMS = [:mode, :type, :owner, :group, :checksum]
|
||||
#else
|
||||
# @@pinparams = [:mode, :type, :group, :checksum]
|
||||
#end
|
||||
|
||||
|
||||
def self.recursecompare(source,dest)
|
||||
|
@ -825,6 +1051,10 @@ module Puppet
|
|||
end
|
||||
end
|
||||
|
||||
def argument?(arg)
|
||||
@arghash.include?(arg)
|
||||
end
|
||||
|
||||
def initialize(hash)
|
||||
@arghash = self.argclean(hash)
|
||||
@arghash.delete(self.class.namevar)
|
||||
|
@ -882,13 +1112,13 @@ module Puppet
|
|||
end
|
||||
|
||||
args = @arghash.dup
|
||||
#args = {}
|
||||
|
||||
args[:path] = path
|
||||
|
||||
unless hash.include?(:source) # it's being manually overridden
|
||||
|
||||
if args.include?(:source)
|
||||
#Puppet.notice "Rewriting source for %s" % path
|
||||
Puppet.err "Rewriting source for %s" % path
|
||||
name = File.basename(path)
|
||||
dirname = args[:source]
|
||||
#Puppet.notice "Old: %s" % args[:source]
|
||||
|
@ -937,16 +1167,26 @@ module Puppet
|
|||
klass = Puppet::Type::PFile
|
||||
end
|
||||
if child = klass[path]
|
||||
#raise "Ruh-roh"
|
||||
unless @children.include?(child)
|
||||
raise Puppet::Error,
|
||||
"Planned child file %s already exists with parent %s" %
|
||||
[path, child.parent]
|
||||
end
|
||||
args.each { |var,value|
|
||||
next if var == :path
|
||||
next if var == :name
|
||||
child[var] = value
|
||||
# behave idempotently
|
||||
unless child[var] == value
|
||||
#Puppet.warning "%s is %s, not %s" % [var, child[var], value]
|
||||
child[var] = value
|
||||
end
|
||||
}
|
||||
else # create it anew
|
||||
#notice "Creating new file with args %s" % args.inspect
|
||||
begin
|
||||
child = klass.new(args)
|
||||
child.parent = self
|
||||
@children << child
|
||||
rescue Puppet::Error => detail
|
||||
Puppet.notice(
|
||||
"Cannot manage %s: %s" %
|
||||
|
@ -963,9 +1203,6 @@ module Puppet
|
|||
child = nil
|
||||
end
|
||||
end
|
||||
if child
|
||||
child.parent = self
|
||||
end
|
||||
return child
|
||||
end
|
||||
|
||||
|
@ -984,8 +1221,8 @@ module Puppet
|
|||
#Puppet.info "%s is already in memory" % @source
|
||||
if obj.managed?
|
||||
raise Puppet::Error.new(
|
||||
"You cannot currently use managed files as sources;" +
|
||||
"%s is managed" % path
|
||||
"You cannot currently use managed file %s as a source" %
|
||||
path.inspect
|
||||
)
|
||||
else
|
||||
# verify they're looking up the correct info
|
||||
|
@ -1031,18 +1268,29 @@ module Puppet
|
|||
return obj
|
||||
end
|
||||
|
||||
# pinning is like recursion, except that it's recursion across
|
||||
# the pinned file's tree, instead of our own
|
||||
# if recursion is turned off, then this whole thing is pretty easy
|
||||
def paramsource=(source)
|
||||
def disabledparamsource=(source)
|
||||
@parameters[:source] = source
|
||||
@arghash.delete(:source)
|
||||
@source = source
|
||||
|
||||
# verify we support the proto
|
||||
if @source =~ /^file:\/\/(\/.+)/
|
||||
@source = $1
|
||||
elsif @source =~ /(\w+):\/\/(\/.+)/
|
||||
if @source =~ /^\/(\/.+)/
|
||||
@sourcetype = "file"
|
||||
elsif @source =~ /^(\w):\/\/(\/.+)/
|
||||
@sourcetype = $1
|
||||
@source = $2
|
||||
else
|
||||
raise Puppet::Error, "Invalid source %s" % @source
|
||||
end
|
||||
|
||||
|
||||
case @sourcetype
|
||||
when "file":
|
||||
when "http", "https":
|
||||
if @parameters[:recurse]
|
||||
raise Puppet::Error.new("HTTP is not supported recursively")
|
||||
end
|
||||
else
|
||||
raise Puppet::Error.new("Protocol %s not supported" % $1)
|
||||
end
|
||||
|
||||
|
@ -1158,9 +1406,7 @@ module Puppet
|
|||
else # they have it but we don't
|
||||
fullname = File.join(self.name, name)
|
||||
if kid = self.newchild(name,:source => child.name)
|
||||
if @children.include?(kid)
|
||||
Puppet.notice "Child already included"
|
||||
else
|
||||
unless @children.include?(kid)
|
||||
self.push kid
|
||||
end
|
||||
end
|
||||
|
@ -1169,19 +1415,12 @@ module Puppet
|
|||
}
|
||||
|
||||
else
|
||||
self[:copy] = @sourceobj.name
|
||||
self[:source] = @sourceobj.name
|
||||
end
|
||||
end
|
||||
|
||||
def paramrecurse=(value)
|
||||
@parameters[:recurse] = value
|
||||
unless FileTest.exist?(self.name) and self.stat.directory?
|
||||
#Puppet.info "%s is not a directory; not recursing" %
|
||||
# self.name
|
||||
return
|
||||
end
|
||||
|
||||
recurse = value
|
||||
def recurse
|
||||
recurse = @parameters[:recurse]
|
||||
# we might have a string, rather than a number
|
||||
if recurse.is_a?(String)
|
||||
if recurse =~ /^[0-9]+$/
|
||||
|
@ -1194,6 +1433,24 @@ module Puppet
|
|||
|
||||
# are we at the end of the recursion?
|
||||
if recurse == 0
|
||||
Puppet.info "finished recursing"
|
||||
return
|
||||
end
|
||||
|
||||
if recurse.is_a?(Integer)
|
||||
recurse -= 1
|
||||
end
|
||||
|
||||
self.localrecurse(recurse)
|
||||
if @states.include?(:source)
|
||||
self.sourcerecurse(recurse)
|
||||
end
|
||||
end
|
||||
|
||||
def localrecurse(recurse)
|
||||
unless FileTest.exist?(self.name) and self.stat.directory?
|
||||
#Puppet.info "%s is not a directory; not recursing" %
|
||||
# self.name
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -1211,51 +1468,79 @@ module Puppet
|
|||
Dir.foreach(self.name) { |file|
|
||||
next if file =~ /^\.\.?/ # skip . and ..
|
||||
if child = self.newchild(file, :recurse => recurse)
|
||||
if @children.include?(child)
|
||||
Puppet.notice "Child already included"
|
||||
else
|
||||
unless @children.include?(child)
|
||||
self.push child
|
||||
added.push file
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# here's where we handle sources; it's special, because it can
|
||||
# require us to build a structure of files that don't yet exist
|
||||
if @parameters.include?(:source)
|
||||
unless FileTest.directory?(@parameters[:source])
|
||||
raise Puppet::Error("Cannot use file %s as a source for a dir" %
|
||||
@parameters[:source])
|
||||
end
|
||||
Dir.foreach(@parameters[:source]) { |file|
|
||||
next if file =~ /^\.\.?$/ # skip . and ..
|
||||
unless added.include?(file)
|
||||
Puppet.notice "Adding absent source-file %s" % file
|
||||
if child = self.newchild(file,
|
||||
:recurse => recurse,
|
||||
:source => File.join(self.name, file)
|
||||
)
|
||||
if @children.include?(child)
|
||||
Puppet.notice "Child already included"
|
||||
else
|
||||
self.push child
|
||||
added.push file
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
def sourcerecurse(recurse)
|
||||
source = @states[:source].source
|
||||
|
||||
sourceobj, path = uri2obj(source)
|
||||
|
||||
# we'll set this manually as necessary
|
||||
if @arghash.include?(:create)
|
||||
@arghash.delete(:create)
|
||||
end
|
||||
|
||||
# okay, we've got our source object; now we need to
|
||||
# build up a local file structure to match the remote
|
||||
# one
|
||||
|
||||
server = sourceobj.server
|
||||
sum = "md5"
|
||||
if state = self.state(:checksum)
|
||||
sum = state.checktype
|
||||
end
|
||||
r = false
|
||||
if recurse
|
||||
unless recurse == 0
|
||||
r = 1
|
||||
end
|
||||
end
|
||||
|
||||
#Puppet.warning "Listing path %s" % path.inspect
|
||||
desc = server.list(path, r)
|
||||
|
||||
#params = @@pinparams.dup
|
||||
#params.unshift(:name)
|
||||
desc.split("\n").each { |line|
|
||||
file, type = line.split("\t")
|
||||
next if file == "/"
|
||||
name = file.sub(/^\//, '')
|
||||
#Puppet.warning "child name is %s" % name
|
||||
args = {:source => source + file}
|
||||
if type == file
|
||||
args[:recurse] = nil
|
||||
end
|
||||
self.newchild(name, args)
|
||||
#self.newchild(hash, source, recurse)
|
||||
#hash2child(hash, source, recurse)
|
||||
}
|
||||
end
|
||||
|
||||
# a wrapper method to make sure the file exists before doing anything
|
||||
def retrieve
|
||||
if @states.include?(:source)
|
||||
@states[:source].retrieve
|
||||
end
|
||||
|
||||
if @parameters.include?(:recurse)
|
||||
#self[:recurse] = @parameters[:recurse]
|
||||
self.recurse
|
||||
end
|
||||
|
||||
unless stat = self.stat(true)
|
||||
Puppet.debug "File %s does not exist" % self.name
|
||||
Puppet.debug "rFile %s does not exist" % self.name
|
||||
@states.each { |name,state|
|
||||
state.is = -1
|
||||
}
|
||||
return
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -1264,8 +1549,6 @@ module Puppet
|
|||
begin
|
||||
@stat = File.stat(self.name)
|
||||
rescue Errno::ENOENT => error
|
||||
#Puppet.debug "Failed to stat %s: No such file or directory" %
|
||||
# [self.name]
|
||||
@stat = nil
|
||||
rescue => error
|
||||
Puppet.debug "Failed to stat %s: %s" %
|
||||
|
@ -1276,30 +1559,57 @@ module Puppet
|
|||
|
||||
return @stat
|
||||
end
|
||||
|
||||
def uri2obj(source)
|
||||
sourceobj = FileSource.new
|
||||
path = nil
|
||||
if source =~ /^\//
|
||||
source = "file://localhost/%s" % source
|
||||
sourceobj.mount = "localhost"
|
||||
sourceobj.local = true
|
||||
end
|
||||
begin
|
||||
uri = URI.parse(source)
|
||||
rescue => detail
|
||||
raise Puppet::Error, "Could not understand source %s: %s" %
|
||||
[source, detail.to_s]
|
||||
end
|
||||
|
||||
case uri.scheme
|
||||
when "file":
|
||||
sourceobj.server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
sourceobj.server.mount("/", "localhost")
|
||||
path = "/localhost" + uri.path
|
||||
when "puppet":
|
||||
args = { :Server => uri.host }
|
||||
if uri.port
|
||||
args[:Port] = uri.port
|
||||
end
|
||||
sourceobj.server = Puppet::NetworkClient.new(args)
|
||||
|
||||
tmp = uri.path
|
||||
if tmp =~ %r{^/(\w+)}
|
||||
sourceobj.mount = $1
|
||||
path = tmp.sub(%r{^/\w+},'') || "/"
|
||||
else
|
||||
raise Puppet::Error, "Invalid source path %s" % tmp
|
||||
end
|
||||
else
|
||||
raise Puppet::Error,
|
||||
"Got other recursive file proto %s" % uri.scheme
|
||||
return
|
||||
end
|
||||
|
||||
return [sourceobj, path.sub(/\/\//, '/')]
|
||||
end
|
||||
end # Puppet::Type::PFile
|
||||
end # Puppet::Type
|
||||
|
||||
class PFileSource
|
||||
attr_accessor :name
|
||||
|
||||
@sources = Hash.new(nil)
|
||||
|
||||
def PFileSource.[]=(name,sub)
|
||||
@sources[name] = sub
|
||||
end
|
||||
|
||||
def PFileSource.[](name)
|
||||
return @sources[name]
|
||||
end
|
||||
|
||||
def initialize(name)
|
||||
@name = name
|
||||
|
||||
if block_given?
|
||||
yield self
|
||||
end
|
||||
|
||||
PFileSource[name] = self
|
||||
end
|
||||
# the filesource class can't include the path, because the path
|
||||
# changes for every file instance
|
||||
class FileSource
|
||||
attr_accessor :mount, :root, :server, :local
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/sslcertificates.rb'
|
||||
require 'test/unit'
|
||||
require 'puppettest'
|
||||
|
||||
# so, what kind of things do we want to test?
|
||||
|
||||
# we don't need to test function, since we're confident in the
|
||||
# library tests. We do, however, need to test how things are actually
|
||||
# working in the language.
|
||||
|
||||
# so really, we want to do things like test that our ast is correct
|
||||
# and test whether we've got things in the right scopes
|
||||
|
||||
class TestCertMgr < Test::Unit::TestCase
|
||||
def setup
|
||||
Puppet[:loglevel] = :debug if __FILE__ == $0
|
||||
#@dir = File.join(Puppet[:certdir], "testing")
|
||||
@dir = "/tmp/puppetcertestingdir"
|
||||
Puppet[:ssldir] = @dir
|
||||
system("mkdir -p %s" % @dir)
|
||||
@@tmpfiles = [@dir]
|
||||
end
|
||||
|
||||
def mkPassFile()
|
||||
keyfile = File.join(@dir, "tmpkeyfile")
|
||||
@@tmpfiles << keyfile
|
||||
unless FileTest.exists?(@dir)
|
||||
system("mkdir -p %s" % @dir)
|
||||
end
|
||||
File.open(keyfile, "w", 0600) { |f|
|
||||
f.print "as;dklj23rlkjzdflij23wr"
|
||||
}
|
||||
|
||||
return keyfile
|
||||
end
|
||||
|
||||
def mkCA
|
||||
ca = nil
|
||||
Puppet[:ssldir] = @dir
|
||||
assert_nothing_raised {
|
||||
ca = Puppet::SSLCertificates::CA.new()
|
||||
}
|
||||
|
||||
return ca
|
||||
end
|
||||
|
||||
def teardown
|
||||
@@tmpfiles.each { |f|
|
||||
if FileTest.exists?(f)
|
||||
system("rm -rf %s" % f)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def testCreateSelfSignedCertificate
|
||||
cert = nil
|
||||
name = "testing"
|
||||
newcert = proc {
|
||||
Puppet::SSLCertificates::Certificate.new(
|
||||
:name => name,
|
||||
:selfsign => true
|
||||
)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert = newcert.call()
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert.mkselfsigned
|
||||
}
|
||||
|
||||
assert_raise(Puppet::Error) {
|
||||
cert.mkselfsigned
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.write
|
||||
}
|
||||
|
||||
assert(FileTest.exists?(cert.certfile))
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.delete
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
cert = newcert.call()
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert.mkselfsigned
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.delete
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def disabled_testCreateEncryptedSelfSignedCertificate
|
||||
cert = nil
|
||||
name = "testing"
|
||||
keyfile = mkPassFile
|
||||
assert_nothing_raised {
|
||||
cert = Puppet::SSLCertificates::Certificate.new(
|
||||
:name => name,
|
||||
:selfsign => true,
|
||||
:capass => keyfile
|
||||
)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert.mkselfsigned
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert.mkhash
|
||||
}
|
||||
|
||||
assert_raise(Puppet::Error) {
|
||||
cert.mkselfsigned
|
||||
}
|
||||
|
||||
assert(FileTest.exists?(cert.certfile))
|
||||
assert(FileTest.exists?(cert.hash))
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.delete
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.mkselfsigned
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.delete
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def testCreateCA
|
||||
ca = nil
|
||||
assert_nothing_raised {
|
||||
ca = Puppet::SSLCertificates::CA.new()
|
||||
}
|
||||
|
||||
# make the CA again and verify it doesn't fail because everything
|
||||
# still exists
|
||||
assert_nothing_raised {
|
||||
ca = Puppet::SSLCertificates::CA.new()
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def testSignCert
|
||||
ca = mkCA()
|
||||
|
||||
cert = nil
|
||||
assert_nothing_raised {
|
||||
cert = Puppet::SSLCertificates::Certificate.new(
|
||||
:name => "signedcertest",
|
||||
:state => "TN",
|
||||
:city => "Nashville",
|
||||
:country => "US",
|
||||
:email => "luke@madstop.com",
|
||||
:org => "Reductive",
|
||||
:ou => "Development",
|
||||
:encrypt => mkPassFile()
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.mkcsr
|
||||
}
|
||||
|
||||
signedcert = nil
|
||||
cacert = nil
|
||||
|
||||
assert_nothing_raised {
|
||||
signedcert, cacert = ca.sign(cert.csr)
|
||||
}
|
||||
|
||||
assert_instance_of(OpenSSL::X509::Certificate, signedcert)
|
||||
assert_instance_of(OpenSSL::X509::Certificate, cacert)
|
||||
|
||||
assert_nothing_raised {
|
||||
cert.cert = signedcert
|
||||
cert.cacert = cacert
|
||||
cert.write
|
||||
}
|
||||
#system("find %s" % Puppet[:ssldir])
|
||||
|
||||
output = nil
|
||||
assert_nothing_raised {
|
||||
output = %x{openssl verify -CApath #{Puppet[:certdir]} -purpose sslserver #{cert.certfile}}
|
||||
}
|
||||
|
||||
assert_equal($?,0)
|
||||
assert_equal("\n", output)
|
||||
end
|
||||
|
||||
def mkcert(hostname)
|
||||
cert = nil
|
||||
assert_nothing_raised {
|
||||
cert = Puppet::SSLCertificates::Certificate.new(:name => hostname)
|
||||
cert.mkcsr
|
||||
}
|
||||
|
||||
return cert
|
||||
end
|
||||
|
||||
|
||||
def test_interactiveca
|
||||
ca = nil
|
||||
Puppet[:ssldir] = "/tmp/puppetinteractivecatest"
|
||||
@@tmpfiles.push Puppet[:ssldir]
|
||||
|
||||
assert_nothing_raised {
|
||||
ca = Puppet::SSLCertificates::CA.new
|
||||
}
|
||||
|
||||
# basic initialization
|
||||
hostname = "test.hostname.com"
|
||||
cert = mkcert(hostname)
|
||||
|
||||
# create the csr
|
||||
csr = nil
|
||||
assert_nothing_raised {
|
||||
csr = cert.mkcsr
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
ca.storeclientcsr(csr)
|
||||
}
|
||||
|
||||
# store it
|
||||
pulledcsr = nil
|
||||
assert_nothing_raised {
|
||||
pulledcsr = ca.getclientcsr(hostname)
|
||||
}
|
||||
|
||||
assert_equal(csr.to_pem, pulledcsr.to_pem)
|
||||
|
||||
signedcert = nil
|
||||
assert_nothing_raised {
|
||||
signedcert, cacert = ca.sign(csr)
|
||||
}
|
||||
|
||||
assert_instance_of(OpenSSL::X509::Certificate, signedcert)
|
||||
newsignedcert = nil
|
||||
assert_nothing_raised {
|
||||
newsignedcert, cacert = ca.getclientcert(hostname)
|
||||
}
|
||||
|
||||
assert(newsignedcert)
|
||||
|
||||
assert_equal(signedcert.to_pem, newsignedcert.to_pem)
|
||||
end
|
||||
|
||||
def test_cafailures
|
||||
ca = mkCA()
|
||||
cert = cacert = nil
|
||||
assert_nothing_raised {
|
||||
cert, cacert = ca.getclientcert("nohost")
|
||||
}
|
||||
assert_nil(cert)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
# $ID: $
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/server'
|
||||
require 'puppet/sslcertificates'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
|
||||
# add the bin directory to our search path
|
||||
ENV["PATH"] += ":" + File.join($puppetbase, "bin")
|
||||
|
||||
# and then the library directories
|
||||
libdirs = $:.find_all { |dir|
|
||||
dir =~ /puppet/ or dir =~ /\.\./
|
||||
}
|
||||
ENV["RUBYLIB"] = libdirs.join(":")
|
||||
|
||||
class TestPuppetBin < Test::Unit::TestCase
|
||||
def setup
|
||||
end
|
||||
|
||||
def teardown
|
||||
end
|
||||
|
||||
def test_version
|
||||
output = nil
|
||||
assert_nothing_raised {
|
||||
output = %x{puppet --version}.chomp
|
||||
}
|
||||
assert(output == Puppet.version)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,90 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/server'
|
||||
require 'puppet/sslcertificates'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
|
||||
# $Id$
|
||||
|
||||
# ok, we have to add the bin directory to our search path
|
||||
ENV["PATH"] += ":" + File.join($puppetbase, "bin")
|
||||
|
||||
# and then the library directories
|
||||
libdirs = $:.find_all { |dir|
|
||||
dir =~ /puppet/ or dir =~ /\.\./
|
||||
}
|
||||
ENV["RUBYLIB"] = libdirs.join(":")
|
||||
|
||||
class TestPuppetCA < Test::Unit::TestCase
|
||||
def setup
|
||||
Puppet[:loglevel] = :debug if __FILE__ == $0
|
||||
@@tmpfiles = []
|
||||
end
|
||||
|
||||
def teardown
|
||||
@@tmpfiles.flatten.each { |file|
|
||||
if File.exists? file
|
||||
system("rm -rf %s" % file)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def mkcert(hostname)
|
||||
cert = nil
|
||||
assert_nothing_raised {
|
||||
cert = Puppet::SSLCertificates::Certificate.new(
|
||||
:name => hostname
|
||||
)
|
||||
cert.mkcsr
|
||||
}
|
||||
|
||||
return cert
|
||||
end
|
||||
|
||||
def test_signing
|
||||
ca = nil
|
||||
Puppet[:ssldir] = "/tmp/puppetcatest"
|
||||
@@tmpfiles << Puppet[:ssldir]
|
||||
Puppet[:autosign] = false
|
||||
assert_nothing_raised {
|
||||
ca = Puppet::CA.new()
|
||||
}
|
||||
#Puppet.warning "SSLDir is %s" % Puppet[:ssldir]
|
||||
#system("find %s" % Puppet[:ssldir])
|
||||
|
||||
cert = mkcert("host.test.com")
|
||||
resp = nil
|
||||
assert_nothing_raised {
|
||||
resp = ca.getcert(cert.csr.to_pem)
|
||||
}
|
||||
assert_equal(["",""], resp)
|
||||
#Puppet.warning "SSLDir is %s" % Puppet[:ssldir]
|
||||
#system("find %s" % Puppet[:ssldir])
|
||||
|
||||
output = nil
|
||||
assert_nothing_raised {
|
||||
output = %x{puppetca --list --ssldir=#{Puppet[:ssldir]} 2>&1}.chomp.split("\n")
|
||||
}
|
||||
#Puppet.warning "SSLDir is %s" % Puppet[:ssldir]
|
||||
#system("find %s" % Puppet[:ssldir])
|
||||
assert_equal($?,0)
|
||||
assert_equal(%w{host.test.com}, output)
|
||||
assert_nothing_raised {
|
||||
output = %x{puppetca --sign -a --ssldir=#{Puppet[:ssldir]}}.chomp.split("\n")
|
||||
}
|
||||
assert_equal($?,0)
|
||||
assert_equal([], output)
|
||||
assert_nothing_raised {
|
||||
output = %x{puppetca --list --ssldir=#{Puppet[:ssldir]}}.chomp.split("\n")
|
||||
}
|
||||
assert_equal($?,0)
|
||||
assert_equal([], output)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,88 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/server'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
require 'socket'
|
||||
require 'facter'
|
||||
|
||||
# $Id$
|
||||
|
||||
# ok, we have to add the bin directory to our search path
|
||||
ENV["PATH"] += ":" + File.join($puppetbase, "bin")
|
||||
|
||||
# and then the library directories
|
||||
libdirs = $:.find_all { |dir|
|
||||
dir =~ /puppet/ or dir =~ /\.\./
|
||||
}
|
||||
ENV["RUBYLIB"] = libdirs.join(":")
|
||||
|
||||
class TestPuppetDExe < Test::Unit::TestCase
|
||||
def setup
|
||||
Puppet[:loglevel] = :debug if __FILE__ == $0
|
||||
@@tmpfiles = []
|
||||
@@tmppids = []
|
||||
end
|
||||
|
||||
def teardown
|
||||
@@tmpfiles.flatten.each { |file|
|
||||
if File.exists? file
|
||||
system("rm -rf %s" % file)
|
||||
end
|
||||
}
|
||||
|
||||
@@tmppids.each { |pid|
|
||||
%x{kill -INT #{pid} 2>/dev/null}
|
||||
}
|
||||
end
|
||||
|
||||
def startmaster
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
output = nil
|
||||
assert_nothing_raised {
|
||||
output = %x{puppetmasterd --manifest #{file}}.chomp
|
||||
}
|
||||
assert($? == 0)
|
||||
@@tmppids << $?.pid
|
||||
assert_equal("", output)
|
||||
end
|
||||
|
||||
def stopmaster
|
||||
ps = Facter["ps"].value || "ps -ef"
|
||||
|
||||
pid = nil
|
||||
%x{#{ps}}.chomp.split(/\n/).each { |line|
|
||||
if line =~ /puppetmasterd/
|
||||
ary = line.split(" ")
|
||||
pid = ary[1].to_i
|
||||
end
|
||||
}
|
||||
assert(pid)
|
||||
|
||||
assert_nothing_raised {
|
||||
Process.kill("-INT", pid)
|
||||
}
|
||||
end
|
||||
|
||||
def test_normalstart
|
||||
startmaster
|
||||
output = nil
|
||||
assert_nothing_raised {
|
||||
output = %x{puppetd --server localhost}.chomp
|
||||
}
|
||||
assert($? == 0)
|
||||
assert_equal("", output)
|
||||
|
||||
assert_nothing_raised {
|
||||
socket = TCPSocket.new("127.0.0.1", Puppet[:masterport])
|
||||
socket.close
|
||||
}
|
||||
stopmaster
|
||||
end
|
||||
end
|
|
@ -0,0 +1,171 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/server'
|
||||
require 'puppet/daemon'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
require 'socket'
|
||||
require 'facter'
|
||||
|
||||
# $Id$
|
||||
|
||||
# ok, we have to add the bin directory to our search path
|
||||
ENV["PATH"] += ":" + File.join($puppetbase, "bin")
|
||||
|
||||
# and then the library directories
|
||||
libdirs = $:.find_all { |dir|
|
||||
dir =~ /puppet/ or dir =~ /\.\./
|
||||
}
|
||||
ENV["RUBYLIB"] = libdirs.join(":")
|
||||
|
||||
class TestPuppetMasterD < Test::Unit::TestCase
|
||||
def getcerts
|
||||
include Puppet::Daemon
|
||||
if self.readcerts
|
||||
return [@cert, @key, @cacert, @cacertfile]
|
||||
else
|
||||
raise "Couldn't read certs"
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
if __FILE__ == $0
|
||||
Puppet[:loglevel] = :debug
|
||||
end
|
||||
@@tmpfiles = []
|
||||
end
|
||||
|
||||
def startmasterd(args)
|
||||
output = nil
|
||||
cmd = "puppetmasterd %s" % args
|
||||
#if Puppet[:debug]
|
||||
# Puppet.debug "turning daemon debugging on"
|
||||
# cmd += " --debug"
|
||||
#end
|
||||
assert_nothing_raised {
|
||||
output = %x{puppetmasterd #{args}}.chomp
|
||||
}
|
||||
assert($? == 0)
|
||||
assert_equal("", output)
|
||||
end
|
||||
|
||||
def stopmasterd(running = true)
|
||||
ps = Facter["ps"].value || "ps -ef"
|
||||
|
||||
pid = nil
|
||||
%x{#{ps}}.chomp.split(/\n/).each { |line|
|
||||
if line =~ /puppetmasterd --manifest/
|
||||
ary = line.split(" ")
|
||||
pid = ary[1].to_i
|
||||
end
|
||||
}
|
||||
|
||||
# we default to mandating that it's running, but teardown
|
||||
# doesn't require that
|
||||
if running or pid
|
||||
assert(pid)
|
||||
|
||||
assert_nothing_raised {
|
||||
Process.kill("-INT", pid)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def teardown
|
||||
@@tmpfiles.flatten.each { |file|
|
||||
if File.exists?(file)
|
||||
system("rm -rf %s" % file)
|
||||
end
|
||||
}
|
||||
|
||||
stopmasterd(false)
|
||||
end
|
||||
|
||||
def test_normalstart
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
startmasterd("--manifest #{file}")
|
||||
|
||||
assert_nothing_raised {
|
||||
socket = TCPSocket.new("127.0.0.1", Puppet[:masterport])
|
||||
socket.close
|
||||
}
|
||||
|
||||
client = nil
|
||||
assert_nothing_raised() {
|
||||
client = XMLRPC::Client.new("localhost", "/RPC2", Puppet[:masterport],
|
||||
nil, nil, nil, nil, true, 5)
|
||||
}
|
||||
retval = nil
|
||||
|
||||
assert_nothing_raised() {
|
||||
retval = client.call("status.status", "")
|
||||
}
|
||||
assert_equal(1, retval)
|
||||
facts = {}
|
||||
Facter.each { |p,v|
|
||||
facts[p] = v
|
||||
}
|
||||
textfacts = CGI.escape(Marshal::dump(facts))
|
||||
assert_nothing_raised() {
|
||||
#Puppet.notice "calling status"
|
||||
#retval = client.call("status.status", "")
|
||||
retval = client.call("puppetmaster.getconfig", textfacts)
|
||||
}
|
||||
|
||||
objects = nil
|
||||
assert_nothing_raised {
|
||||
Marshal::load(CGI.unescape(retval))
|
||||
}
|
||||
#stopmasterd
|
||||
end
|
||||
|
||||
def disabled_test_sslconnection
|
||||
#file = File.join($puppetbase, "examples", "code", "head")
|
||||
#startmasterd("--manifest #{file}")
|
||||
|
||||
#assert_nothing_raised {
|
||||
# socket = TCPSocket.new("127.0.0.1", Puppet[:masterport])
|
||||
# socket.close
|
||||
#}
|
||||
|
||||
client = nil
|
||||
cert, key, cacert, cacertfile = getcerts()
|
||||
|
||||
assert_nothing_raised() {
|
||||
client = Net::HTTP.new("localhost", Puppet[:masterport])
|
||||
client.cert = cert
|
||||
client.key = key
|
||||
client.ca_file = cacertfile
|
||||
client.use_ssl = true
|
||||
client.start_immediately = true
|
||||
}
|
||||
retval = nil
|
||||
|
||||
assert_nothing_raised() {
|
||||
retval = client.nothing
|
||||
}
|
||||
assert_equal(1, retval)
|
||||
facts = {}
|
||||
Facter.each { |p,v|
|
||||
facts[p] = v
|
||||
}
|
||||
textfacts = CGI.escape(Marshal::dump(facts))
|
||||
assert_nothing_raised() {
|
||||
#Puppet.notice "calling status"
|
||||
#retval = client.call("status.status", "")
|
||||
retval = client.call("puppetmaster.getconfig", textfacts)
|
||||
}
|
||||
|
||||
objects = nil
|
||||
assert_nothing_raised {
|
||||
Marshal::load(CGI.unescape(retval))
|
||||
}
|
||||
#stopmasterd
|
||||
end
|
||||
end
|
|
@ -0,0 +1,264 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/parser/interpreter'
|
||||
require 'puppet/parser/parser'
|
||||
require 'puppet/client'
|
||||
require 'test/unit'
|
||||
require 'puppettest'
|
||||
|
||||
# so, what kind of things do we want to test?
|
||||
|
||||
# we don't need to test function, since we're confident in the
|
||||
# library tests. We do, however, need to test how things are actually
|
||||
# working in the language.
|
||||
|
||||
# so really, we want to do things like test that our ast is correct
|
||||
# and test whether we've got things in the right scopes
|
||||
|
||||
class TestScope < Test::Unit::TestCase
|
||||
def setup
|
||||
Puppet[:loglevel] = :debug if __FILE__ == $0
|
||||
end
|
||||
|
||||
def to_ary(hash)
|
||||
hash.collect { |key,value|
|
||||
[key,value]
|
||||
}
|
||||
end
|
||||
|
||||
def test_variables
|
||||
scope = nil
|
||||
over = "over"
|
||||
|
||||
scopes = []
|
||||
vars = []
|
||||
values = {}
|
||||
ovalues = []
|
||||
|
||||
10.times { |index|
|
||||
# slap some recursion in there
|
||||
scope = Puppet::Parser::Scope.new(scope)
|
||||
scopes.push scope
|
||||
|
||||
var = "var%s" % index
|
||||
value = rand(1000)
|
||||
ovalue = rand(1000)
|
||||
|
||||
ovalues.push ovalue
|
||||
|
||||
vars.push var
|
||||
values[var] = value
|
||||
|
||||
# set the variable in the current scope
|
||||
assert_nothing_raised {
|
||||
scope.setvar(var,value)
|
||||
}
|
||||
|
||||
# this should override previous values
|
||||
assert_nothing_raised {
|
||||
scope.setvar(over,ovalue)
|
||||
}
|
||||
|
||||
assert_equal(value,scope.lookupvar(var))
|
||||
|
||||
#puts "%s vars, %s scopes" % [vars.length,scopes.length]
|
||||
i = 0
|
||||
vars.zip(scopes) { |v,s|
|
||||
# this recurses all the way up the tree as necessary
|
||||
val = nil
|
||||
oval = nil
|
||||
|
||||
# look up the values using the bottom scope
|
||||
assert_nothing_raised {
|
||||
val = scope.lookupvar(v)
|
||||
oval = scope.lookupvar(over)
|
||||
}
|
||||
|
||||
# verify they're correct
|
||||
assert_equal(values[v],val)
|
||||
assert_equal(ovalue,oval)
|
||||
|
||||
# verify that we get the most recent value
|
||||
assert_equal(ovalue,scope.lookupvar(over))
|
||||
|
||||
# verify that they aren't available in upper scopes
|
||||
if parent = s.parent
|
||||
assert_raise(Puppet::ParseError) {
|
||||
parent.lookupvar(v)
|
||||
}
|
||||
|
||||
# and verify that the parent sees its correct value
|
||||
assert_equal(ovalues[i - 1],parent.lookupvar(over))
|
||||
end
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_declarative
|
||||
# set to declarative
|
||||
top = Puppet::Parser::Scope.new(nil,true)
|
||||
sub = Puppet::Parser::Scope.new(top)
|
||||
|
||||
assert_nothing_raised {
|
||||
top.setvar("test","value")
|
||||
}
|
||||
assert_raise(Puppet::ParseError) {
|
||||
top.setvar("test","other")
|
||||
}
|
||||
assert_nothing_raised {
|
||||
sub.setvar("test","later")
|
||||
}
|
||||
assert_raise(Puppet::ParseError) {
|
||||
top.setvar("test","yeehaw")
|
||||
}
|
||||
end
|
||||
|
||||
def test_notdeclarative
|
||||
# set to not declarative
|
||||
top = Puppet::Parser::Scope.new(nil,false)
|
||||
sub = Puppet::Parser::Scope.new(top)
|
||||
|
||||
assert_nothing_raised {
|
||||
top.setvar("test","value")
|
||||
}
|
||||
assert_nothing_raised {
|
||||
top.setvar("test","other")
|
||||
}
|
||||
assert_nothing_raised {
|
||||
sub.setvar("test","later")
|
||||
}
|
||||
assert_nothing_raised {
|
||||
sub.setvar("test","yayness")
|
||||
}
|
||||
end
|
||||
|
||||
def test_defaults
|
||||
scope = nil
|
||||
over = "over"
|
||||
|
||||
scopes = []
|
||||
vars = []
|
||||
values = {}
|
||||
ovalues = []
|
||||
|
||||
defs = Hash.new { |hash,key|
|
||||
hash[key] = Hash.new(nil)
|
||||
}
|
||||
|
||||
prevdefs = Hash.new { |hash,key|
|
||||
hash[key] = Hash.new(nil)
|
||||
}
|
||||
|
||||
params = %w{a list of parameters that could be used for defaults}
|
||||
|
||||
types = %w{a set of types that could be used to set defaults}
|
||||
|
||||
10.times { |index|
|
||||
scope = Puppet::Parser::Scope.new(scope)
|
||||
scopes.push scope
|
||||
|
||||
tmptypes = []
|
||||
|
||||
# randomly create defaults for a random set of types
|
||||
tnum = rand(5)
|
||||
tnum.times { |t|
|
||||
# pick a type
|
||||
#Puppet.debug "Type length is %s" % types.length
|
||||
#s = rand(types.length)
|
||||
#Puppet.debug "Type num is %s" % s
|
||||
#type = types[s]
|
||||
#Puppet.debug "Type is %s" % s
|
||||
type = types[rand(types.length)]
|
||||
if tmptypes.include?(type)
|
||||
Puppet.debug "Duplicate type %s" % type
|
||||
redo
|
||||
else
|
||||
tmptypes.push type
|
||||
end
|
||||
|
||||
Puppet.debug "type is %s" % type
|
||||
|
||||
d = {}
|
||||
|
||||
# randomly assign some parameters
|
||||
num = rand(4)
|
||||
num.times { |n|
|
||||
param = params[rand(params.length)]
|
||||
if d.include?(param)
|
||||
Puppet.debug "Duplicate param %s" % param
|
||||
redo
|
||||
else
|
||||
d[param] = rand(1000)
|
||||
end
|
||||
}
|
||||
|
||||
# and then add a consistent type
|
||||
d["always"] = rand(1000)
|
||||
|
||||
d.each { |var,val|
|
||||
defs[type][var] = val
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
scope.setdefaults(type,to_ary(d))
|
||||
}
|
||||
fdefs = nil
|
||||
assert_nothing_raised {
|
||||
fdefs = scope.lookupdefaults(type)
|
||||
}
|
||||
|
||||
# now, make sure that reassignment fails if we're
|
||||
# in declarative mode
|
||||
assert_raise(Puppet::ParseError) {
|
||||
scope.setdefaults(type,[%w{always funtest}])
|
||||
}
|
||||
|
||||
# assert that we have collected the same values
|
||||
assert_equal(defs[type],fdefs)
|
||||
|
||||
# now assert that our parent still finds the same defaults
|
||||
# it got last time
|
||||
if parent = scope.parent
|
||||
unless prevdefs[type].nil?
|
||||
assert_equal(prevdefs[type],parent.lookupdefaults(type))
|
||||
end
|
||||
end
|
||||
d.each { |var,val|
|
||||
prevdefs[type][var] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_strinterp
|
||||
scope = Puppet::Parser::Scope.new(nil)
|
||||
|
||||
assert_nothing_raised {
|
||||
scope.setvar("test","value")
|
||||
}
|
||||
val = nil
|
||||
assert_nothing_raised {
|
||||
val = scope.strinterp("string ${test}")
|
||||
}
|
||||
assert_equal("string value", val)
|
||||
|
||||
assert_nothing_raised {
|
||||
val = scope.strinterp("string ${test} ${test} ${test}")
|
||||
}
|
||||
assert_equal("string value value value", val)
|
||||
|
||||
assert_nothing_raised {
|
||||
val = scope.strinterp("string $test ${test} $test")
|
||||
}
|
||||
assert_equal("string value value value", val)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,317 @@
|
|||
#!/usr/bin/ruby -w
|
||||
|
||||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '..'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/parser/interpreter'
|
||||
require 'puppet/parser/parser'
|
||||
require 'puppet/client'
|
||||
require 'puppet/server'
|
||||
require 'test/unit'
|
||||
require 'puppettest'
|
||||
|
||||
# so, what kind of things do we want to test?
|
||||
|
||||
# we don't need to test function, since we're confident in the
|
||||
# library tests. We do, however, need to test how things are actually
|
||||
# working in the language.
|
||||
|
||||
# so really, we want to do things like test that our ast is correct
|
||||
# and test whether we've got things in the right scopes
|
||||
|
||||
class TestSnippets < Test::Unit::TestCase
|
||||
$snippetbase = File.join($puppetbase, "examples", "code", "snippets")
|
||||
|
||||
def file2ast(file)
|
||||
parser = Puppet::Parser::Parser.new()
|
||||
parser.file = file
|
||||
ast = parser.parse
|
||||
|
||||
return ast
|
||||
end
|
||||
|
||||
def snippet2ast(text)
|
||||
parser = Puppet::Parser::Parser.new()
|
||||
parser.string = text
|
||||
ast = parser.parse
|
||||
|
||||
return ast
|
||||
end
|
||||
|
||||
def client
|
||||
args = {
|
||||
:Listen => false
|
||||
}
|
||||
Puppet::Client.new(args)
|
||||
end
|
||||
|
||||
def ast2scope(ast)
|
||||
interp = Puppet::Parser::Interpreter.new(
|
||||
:ast => ast,
|
||||
:client => client()
|
||||
)
|
||||
scope = Puppet::Parser::Scope.new()
|
||||
ast.evaluate(scope)
|
||||
|
||||
return scope
|
||||
end
|
||||
|
||||
def scope2objs(scope)
|
||||
objs = scope.to_trans
|
||||
end
|
||||
|
||||
def snippet2scope(snippet)
|
||||
ast = snippet2ast(snippet)
|
||||
scope = ast2scope(ast)
|
||||
end
|
||||
|
||||
def snippet2objs(snippet)
|
||||
ast = snippet2ast(snippet)
|
||||
scope = ast2scope(ast)
|
||||
objs = scope2objs(scope)
|
||||
end
|
||||
|
||||
def states(type)
|
||||
states = []
|
||||
|
||||
type.buildstatehash
|
||||
type.validstates.each { |name,state|
|
||||
states.push name
|
||||
}
|
||||
|
||||
#if states.length == 0
|
||||
# raise "%s has no states" % type
|
||||
#end
|
||||
|
||||
states
|
||||
end
|
||||
|
||||
def metaparams(type)
|
||||
mparams = []
|
||||
Puppet::Type.eachmetaparam { |param|
|
||||
mparams.push param
|
||||
}
|
||||
|
||||
mparams
|
||||
end
|
||||
|
||||
def params(type)
|
||||
params = []
|
||||
type.parameters.each { |name,state|
|
||||
params.push name
|
||||
}
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def randthing(thing,type)
|
||||
list = self.send(thing,type)
|
||||
list[rand(list.length)]
|
||||
end
|
||||
|
||||
def randeach(type)
|
||||
[:states, :metaparams, :params].collect { |thing|
|
||||
randthing(thing,type)
|
||||
}
|
||||
end
|
||||
|
||||
@@snippets = {
|
||||
true => [
|
||||
%{File { mode => 755 }}
|
||||
],
|
||||
}
|
||||
|
||||
def disabled_test_defaults
|
||||
Puppet::Type.eachtype { |type|
|
||||
next if type.name == :puppet or type.name == :component
|
||||
|
||||
rands = randeach(type)
|
||||
|
||||
name = type.name.to_s.capitalize
|
||||
|
||||
[0..1, 0..2].each { |range|
|
||||
params = rands[range]
|
||||
paramstr = params.collect { |param|
|
||||
"%s => fake" % param
|
||||
}.join(", ")
|
||||
|
||||
str = "%s { %s }" % [name, paramstr]
|
||||
|
||||
scope = nil
|
||||
assert_nothing_raised {
|
||||
scope = snippet2scope(str)
|
||||
}
|
||||
|
||||
defaults = nil
|
||||
assert_nothing_raised {
|
||||
defaults = scope.lookupdefaults(name)
|
||||
}
|
||||
|
||||
p defaults
|
||||
|
||||
params.each { |param|
|
||||
puts "%s => '%s'" % [name,param]
|
||||
assert(defaults.include?(param))
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def setup
|
||||
Puppet[:loglevel] = :debug if __FILE__ == $0
|
||||
@@tmpfiles = []
|
||||
end
|
||||
|
||||
def teardown
|
||||
@@tmpfiles.flatten.each { |file|
|
||||
if FileTest.exists?(file)
|
||||
File.unlink(file)
|
||||
end
|
||||
}
|
||||
Puppet::Type.allclear
|
||||
end
|
||||
|
||||
# this is here in case no tests get defined; otherwise we get a warning
|
||||
def test_nothing
|
||||
end
|
||||
|
||||
def snippet_filecreate(trans)
|
||||
%w{a b c d}.each { |letter|
|
||||
file = "/tmp/create%stest" % letter
|
||||
Puppet.info "testing %s" % file
|
||||
assert(Puppet::Type::PFile[file])
|
||||
assert(FileTest.exists?(file))
|
||||
@@tmpfiles << file
|
||||
}
|
||||
%w{a b}.each { |letter|
|
||||
file = "/tmp/create%stest" % letter
|
||||
assert(File.stat(file).mode & 007777 == 0755)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
trans.rollback
|
||||
}
|
||||
%w{a b c d}.each { |letter|
|
||||
file = "/tmp/create%stest" % letter
|
||||
assert(! FileTest.exists?(file))
|
||||
}
|
||||
end
|
||||
|
||||
def snippet_simpledefaults(trans)
|
||||
file = "/tmp/defaulttest"
|
||||
@@tmpfiles << file
|
||||
assert(FileTest.exists?(file))
|
||||
assert(File.stat(file).mode & 007777 == 0755)
|
||||
|
||||
assert_nothing_raised {
|
||||
trans.rollback
|
||||
}
|
||||
assert(! FileTest.exists?(file))
|
||||
end
|
||||
|
||||
def snippet_simpleselector(trans)
|
||||
files = %w{a b c d}.collect { |letter|
|
||||
"/tmp/snippetselect%stest" % letter
|
||||
}
|
||||
@@tmpfiles << files
|
||||
|
||||
files.each { |file|
|
||||
assert(FileTest.exists?(file))
|
||||
assert(File.stat(file).mode & 007777 == 0755)
|
||||
@@tmpfiles << file
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
trans.rollback
|
||||
}
|
||||
files.each { |file|
|
||||
assert(! FileTest.exists?(file))
|
||||
}
|
||||
end
|
||||
|
||||
def snippet_classpathtest(trans)
|
||||
file = "/tmp/classtest"
|
||||
@@tmpfiles << file
|
||||
|
||||
assert(FileTest.exists?(file))
|
||||
|
||||
obj = nil
|
||||
assert_nothing_raised {
|
||||
obj = Puppet::Type::PFile[file]
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
assert_equal(%w{puppet[top] testing[testingname] component[componentname] /tmp/classtest}, obj.path)
|
||||
#Puppet.err obj.path
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
trans.rollback
|
||||
}
|
||||
assert(! FileTest.exists?(file))
|
||||
end
|
||||
|
||||
def snippet_argumentdefaults(trans)
|
||||
file1 = "/tmp/argumenttest1"
|
||||
file2 = "/tmp/argumenttest2"
|
||||
#@@tmpfiles << file
|
||||
|
||||
assert(FileTest.exists?(file1))
|
||||
assert(File.stat(file1).mode & 007777 == 0755)
|
||||
|
||||
assert(FileTest.exists?(file2))
|
||||
assert(File.stat(file2).mode & 007777 == 0644)
|
||||
end
|
||||
|
||||
def disabled_snippet_dirchmod(trans)
|
||||
dirs = %w{a b}.collect { |letter|
|
||||
"/tmp/dirchmodtest%s" % letter
|
||||
}
|
||||
|
||||
@@tmpfiles << dirs
|
||||
|
||||
dirs.each { |dir|
|
||||
assert(FileTest.directory?(dir))
|
||||
}
|
||||
|
||||
assert(File.stat("/tmp/dirchmodtesta").mode & 007777 == 0755)
|
||||
assert(File.stat("/tmp/dirchmodtestb").mode & 007777 == 0700)
|
||||
|
||||
assert_nothing_raised {
|
||||
trans.rollback
|
||||
}
|
||||
end
|
||||
|
||||
# XXX this is the answer
|
||||
Dir.entries($snippetbase).sort.each { |file|
|
||||
next if file =~ /^\./
|
||||
|
||||
mname = "snippet_" + file
|
||||
if self.method_defined?(mname)
|
||||
#eval("alias %s %s" % [testname, mname])
|
||||
testname = ("test_" + mname).intern
|
||||
self.send(:define_method, testname) {
|
||||
# first parse the file
|
||||
server = Puppet::Master.new(
|
||||
:File => File.join($snippetbase, file),
|
||||
:Local => true
|
||||
)
|
||||
client = Puppet::Client.new(
|
||||
:Server => server,
|
||||
:Cache => false
|
||||
)
|
||||
|
||||
assert(client.local)
|
||||
client.getconfig()
|
||||
trans = client.config()
|
||||
self.send(mname, trans)
|
||||
}
|
||||
mname = mname.intern
|
||||
#eval("alias %s %s" % [testname, mname])
|
||||
end
|
||||
}
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '..'
|
||||
$:.unshift '../../lib'
|
||||
$puppetbase = "../../../../language/trunk/"
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet/metric'
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/parser/lexer'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
|
||||
# $Id$
|
||||
|
||||
#%q{service("telnet") = \{
|
||||
# port => "23",
|
||||
# protocol => "tcp",
|
||||
# name => "telnet",
|
||||
#\}
|
||||
#} => [[:NAME, "service"], [:LPAREN, "("], [:DQUOTE, "\""], [:NAME, "telnet"], [:DQUOTE, "\""], [:RPAREN, ")"], [:EQUALS, "="], [:lbrace, "{"], [:NAME, "port"], [:FARROW, "=>"], [:DQUOTE, "\""], [:NAME, "23"], [:DQUOTE, "\""], [:COMMA, ","], [:NAME, "protocol"], [:FARROW, "=>"], [:DQUOTE, "\""], [:NAME, "tcp"], [:DQUOTE, "\""], [:COMMA, ","], [:NAME, "name"], [:FARROW, "=>"], [:DQUOTE, "\""], [:NAME, "telnet"], [:DQUOTE, "\""], [:COMMA, ","], [:RBRACE, "}"]]
|
||||
|
||||
class TestLexer < Test::Unit::TestCase
|
||||
def setup
|
||||
Puppet[:loglevel] = :debug if __FILE__ == $0
|
||||
@lexer = Puppet::Parser::Lexer.new()
|
||||
end
|
||||
|
||||
def test_simple_lex
|
||||
strings = {
|
||||
%q{\\} => [[:BACKSLASH,"\\"],[false,false]],
|
||||
%q{simplest scanner test} => [[:NAME,"simplest"],[:NAME,"scanner"],[:NAME,"test"],[false,false]],
|
||||
%q{returned scanner test
|
||||
} => [[:NAME,"returned"],[:NAME,"scanner"],[:NAME,"test"],[false,false]]
|
||||
}
|
||||
strings.each { |str,ary|
|
||||
@lexer.string = str
|
||||
assert_equal(
|
||||
ary,
|
||||
@lexer.fullscan()
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
def test_quoted_strings
|
||||
strings = {
|
||||
%q{a simple "scanner" test
|
||||
} => [[:NAME,"a"],[:NAME,"simple"],[:QTEXT,"scanner"],[:NAME,"test"],[false,false]],
|
||||
%q{a harder "scanner test"
|
||||
} => [[:NAME,"a"],[:NAME,"harder"],[:QTEXT,"scanner test"],[false,false]],
|
||||
%q{a hardest "scanner \"test\""
|
||||
} => [[:NAME,"a"],[:NAME,"hardest"],[:QTEXT,'scanner "test"'],[false,false]],
|
||||
%q{function("call")} => [[:NAME,"function"],[:LPAREN,"("],[:QTEXT,'call'],[:RPAREN,")"],[false,false]]
|
||||
}
|
||||
strings.each { |str,array|
|
||||
@lexer.string = str
|
||||
assert_equal(
|
||||
array,
|
||||
@lexer.fullscan()
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
def test_errors
|
||||
strings = %w{
|
||||
^
|
||||
@
|
||||
}
|
||||
strings.each { |str|
|
||||
@lexer.string = str
|
||||
assert_raise(RuntimeError) {
|
||||
@lexer.fullscan()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_more_error
|
||||
assert_raise(TypeError) {
|
||||
@lexer.fullscan()
|
||||
}
|
||||
end
|
||||
|
||||
def test_files
|
||||
textfiles() { |file|
|
||||
@lexer.file = file
|
||||
assert_nothing_raised() {
|
||||
@lexer.fullscan()
|
||||
}
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
end
|
||||
|
||||
def test_strings
|
||||
names = %w{this is a bunch of names}
|
||||
types = %w{Many Different Words A Word}
|
||||
words = %w{differently Cased words A a}
|
||||
|
||||
names.each { |t|
|
||||
@lexer.string = t
|
||||
assert_equal(
|
||||
[[:NAME,t],[false,false]],
|
||||
@lexer.fullscan
|
||||
)
|
||||
}
|
||||
types.each { |t|
|
||||
@lexer.string = t
|
||||
assert_equal(
|
||||
[[:TYPE,t],[false,false]],
|
||||
@lexer.fullscan
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,55 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/parser/parser'
|
||||
require 'test/unit'
|
||||
require 'puppettest'
|
||||
|
||||
# $Id$
|
||||
|
||||
class TestParser < Test::Unit::TestCase
|
||||
# hmmm
|
||||
# this is complicated, because we store references to the created
|
||||
# objects in a central store
|
||||
def setup
|
||||
Puppet[:loglevel] = :debug if __FILE__ == $0
|
||||
Puppet[:parseonly] = true
|
||||
#@lexer = Puppet::Parser::Lexer.new()
|
||||
@parser = Puppet::Parser::Parser.new()
|
||||
end
|
||||
|
||||
def test_each_file
|
||||
textfiles { |file|
|
||||
Puppet.debug("parsing %s" % file) if __FILE__ == $0
|
||||
assert_nothing_raised() {
|
||||
@parser.file = file
|
||||
@parser.parse
|
||||
}
|
||||
|
||||
Puppet::Type.eachtype { |type|
|
||||
type.each { |obj|
|
||||
assert(obj.file)
|
||||
assert(obj.name)
|
||||
assert(obj.line)
|
||||
}
|
||||
}
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
end
|
||||
|
||||
def test_failers
|
||||
failers { |file|
|
||||
Puppet.debug("parsing failer %s" % file) if __FILE__ == $0
|
||||
assert_raise(Puppet::ParseError) {
|
||||
@parser.file = file
|
||||
@parser.parse
|
||||
}
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '..'
|
||||
$:.unshift '../../lib'
|
||||
$puppetbase = "../../../../language/trunk/"
|
||||
$puppetbase = ".."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
|
@ -11,8 +11,7 @@ require 'test/unit'
|
|||
|
||||
class TestPuppetDefaults < Test::Unit::TestCase
|
||||
@@dirs = %w{rrddir puppetconf puppetvar logdir statedir}
|
||||
@@files = %w{logfile checksumfile
|
||||
manifest masterlog}
|
||||
@@files = %w{logfile checksumfile manifest masterlog}
|
||||
@@normals = %w{puppetport masterport server}
|
||||
@@booleans = %w{rrdgraph noop}
|
||||
|
||||
|
@ -40,17 +39,19 @@ class TestPuppetDefaults < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def testContained
|
||||
confdir = Regexp.new(Puppet[:puppetconf])
|
||||
vardir = Regexp.new(Puppet[:puppetvar])
|
||||
[@@dirs,@@files].flatten.each { |param|
|
||||
value = Puppet[param]
|
||||
if __FILE__ == $0
|
||||
def disabled_testContained
|
||||
confdir = Regexp.new(Puppet[:puppetconf])
|
||||
vardir = Regexp.new(Puppet[:puppetvar])
|
||||
[@@dirs,@@files].flatten.each { |param|
|
||||
value = Puppet[param]
|
||||
|
||||
unless value =~ confdir or value =~ vardir
|
||||
assert_nothing_raised { raise "%s is in wrong dir: %s" %
|
||||
[param,value] }
|
||||
end
|
||||
}
|
||||
unless value =~ confdir or value =~ vardir
|
||||
assert_nothing_raised { raise "%s is in wrong dir: %s" %
|
||||
[param,value] }
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def testArgumentTypes
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/ca'
|
||||
require 'puppet/sslcertificates'
|
||||
require 'openssl'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
|
||||
# $Id$
|
||||
|
||||
if ARGV.length > 0 and ARGV[0] == "short"
|
||||
$short = true
|
||||
else
|
||||
$short = false
|
||||
end
|
||||
|
||||
class TestCA < Test::Unit::TestCase
|
||||
def setup
|
||||
if __FILE__ == $0
|
||||
Puppet[:loglevel] = :debug
|
||||
#paths = Puppet::Type.type(:service).searchpath
|
||||
#paths.push "%s/examples/root/etc/init.d" % $puppetbase
|
||||
#Puppet::Type.type(:service).setpath(paths)
|
||||
end
|
||||
|
||||
@@tmpfiles = []
|
||||
end
|
||||
|
||||
def teardown
|
||||
Puppet::Type.allclear
|
||||
print "\n\n" if Puppet[:debug]
|
||||
|
||||
@@tmpfiles.each { |file|
|
||||
if FileTest.exists?(file)
|
||||
system("rm -rf %s" % file)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_autocertgeneration
|
||||
ssldir = "/tmp/testcertdir"
|
||||
@@tmpfiles.push ssldir
|
||||
assert_nothing_raised {
|
||||
Puppet[:autosign] = true
|
||||
Puppet[:ssldir] = ssldir
|
||||
}
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
ca = nil
|
||||
|
||||
assert_nothing_raised {
|
||||
ca = Puppet::CA.new()
|
||||
}
|
||||
|
||||
key = nil
|
||||
csr = nil
|
||||
cert = nil
|
||||
hostname = "test.domain.com"
|
||||
assert_nothing_raised {
|
||||
cert = Puppet::SSLCertificates::Certificate.new(
|
||||
:name => "test.domain.com"
|
||||
)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert.mkcsr
|
||||
}
|
||||
|
||||
certtext = nil
|
||||
cacerttext = nil
|
||||
assert_nothing_raised {
|
||||
certtext, cacerttext = ca.getcert(cert.csr.to_s)
|
||||
}
|
||||
|
||||
assert_instance_of(String, certtext)
|
||||
assert_instance_of(String, cacerttext)
|
||||
x509 = nil
|
||||
assert_nothing_raised {
|
||||
x509 = OpenSSL::X509::Certificate.new(certtext)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
OpenSSL::X509::Certificate.new(cacerttext)
|
||||
}
|
||||
|
||||
# and pull it again, just to make sure we're getting the same thing
|
||||
newtext = nil
|
||||
assert_nothing_raised {
|
||||
newtext, cacerttext = ca.getcert(cert.csr.to_s)
|
||||
}
|
||||
|
||||
assert_equal(certtext,newtext)
|
||||
end
|
||||
|
||||
def test_storeAndSign
|
||||
ssldir = "/tmp/testcertdir"
|
||||
@@tmpfiles.push ssldir
|
||||
assert_nothing_raised {
|
||||
Puppet[:ssldir] = ssldir
|
||||
Puppet[:autosign] = false
|
||||
}
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
ca = nil
|
||||
caserv = nil
|
||||
assert_nothing_raised {
|
||||
caserv = Puppet::CA.new()
|
||||
}
|
||||
assert_nothing_raised {
|
||||
ca = caserv.ca
|
||||
}
|
||||
|
||||
key = nil
|
||||
csr = nil
|
||||
cert = nil
|
||||
hostname = "test.domain.com"
|
||||
assert_nothing_raised {
|
||||
cert = Puppet::SSLCertificates::Certificate.new(
|
||||
:name => "anothertest.domain.com"
|
||||
)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert.mkcsr
|
||||
}
|
||||
|
||||
certtext = nil
|
||||
assert_nothing_raised {
|
||||
certtext, cacerttext = caserv.getcert(cert.csr.to_s)
|
||||
}
|
||||
|
||||
assert_equal("", certtext)
|
||||
|
||||
x509 = nil
|
||||
assert_nothing_raised {
|
||||
x509, cacert = ca.sign(cert.csr)
|
||||
}
|
||||
cert.cert = x509
|
||||
assert_nothing_raised {
|
||||
cert.write
|
||||
}
|
||||
|
||||
assert(File.exists?(cert.certfile))
|
||||
|
||||
newtext = nil
|
||||
assert_nothing_raised {
|
||||
newtext, cacerttext = caserv.getcert(cert.csr.to_s)
|
||||
}
|
||||
|
||||
assert(newtext)
|
||||
end
|
||||
|
||||
def cycleautosign
|
||||
ssldir = "/tmp/testcertdir"
|
||||
autosign = "/tmp/autosign"
|
||||
@@tmpfiles.push ssldir
|
||||
@@tmpfiles.push autosign
|
||||
assert_nothing_raised {
|
||||
Puppet[:ssldir] = ssldir
|
||||
}
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
caserv = nil
|
||||
|
||||
assert_nothing_raised {
|
||||
caserv = Puppet::CA.new()
|
||||
}
|
||||
|
||||
key = nil
|
||||
csr = nil
|
||||
cert = nil
|
||||
hostname = "test.domain.com"
|
||||
assert_nothing_raised {
|
||||
cert = Puppet::SSLCertificates::Certificate.new(
|
||||
:name => "test.domain.com"
|
||||
)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
cert.mkcsr
|
||||
}
|
||||
|
||||
certtext = nil
|
||||
assert_nothing_raised {
|
||||
certtext = caserv.getcert(cert.csr.to_s)
|
||||
}
|
||||
|
||||
x509 = nil
|
||||
assert_nothing_raised {
|
||||
x509 = OpenSSL::X509::Certificate.new(certtext)
|
||||
}
|
||||
|
||||
assert(File.exists?(cert.certfile))
|
||||
|
||||
newtext = nil
|
||||
assert_nothing_raised {
|
||||
newtext = caserv.getcert(cert.csr.to_s)
|
||||
}
|
||||
|
||||
assert_equal(certtext,newtext)
|
||||
end
|
||||
|
||||
def test_autosign
|
||||
autosign = "/tmp/autosign"
|
||||
Puppet[:autosign] = "/tmp/autosign"
|
||||
@@tmpfiles << autosign
|
||||
File.open(autosign, "w") { |f|
|
||||
f.puts "hostmatch.domain.com"
|
||||
f.puts ".+.other.com"
|
||||
f.puts "hostname.+"
|
||||
}
|
||||
|
||||
caserv = nil
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
assert_nothing_raised {
|
||||
caserv = Puppet::CA.new()
|
||||
}
|
||||
|
||||
assert(caserv.autosign?("hostmatch.domain.com"))
|
||||
assert(caserv.autosign?("fakehost.other.com"))
|
||||
assert(caserv.autosign?("hostname.rahtest.boo"))
|
||||
assert(caserv.autosign?("hostname.com")) # a tricky one
|
||||
assert(!caserv.autosign?("kirby.reductivelabs.com"))
|
||||
assert(!caserv.autosign?("culain.domain.com"))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,386 @@
|
|||
if __FILE__ == $0
|
||||
if Dir.getwd =~ /test\/server$/
|
||||
Dir.chdir("..")
|
||||
end
|
||||
|
||||
$:.unshift '../lib'
|
||||
$:.unshift '../../../library/trunk/lib/'
|
||||
$:.unshift '../../../library/trunk/test/'
|
||||
$puppetbase = ".."
|
||||
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/fileserver'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
|
||||
class TestFileServer < TestPuppet
|
||||
def setup
|
||||
if __FILE__ == $0
|
||||
Puppet[:loglevel] = :debug
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def mkrandomdirs(dir, depth, width)
|
||||
assert_nothing_raised {
|
||||
Dir.mkdir(dir)
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def test_namefailures
|
||||
server = nil
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
assert_raise(Puppet::FileServerError) {
|
||||
server.mount("/tmp", "invalid+name")
|
||||
}
|
||||
|
||||
assert_raise(Puppet::FileServerError) {
|
||||
server.mount("/tmp", "invalid-name")
|
||||
}
|
||||
|
||||
assert_raise(Puppet::FileServerError) {
|
||||
server.mount("/tmp", "invalid name")
|
||||
}
|
||||
|
||||
assert_raise(Puppet::FileServerError) {
|
||||
server.mount("/tmp", "")
|
||||
}
|
||||
end
|
||||
|
||||
def test_listroot
|
||||
server = nil
|
||||
testdir = "/tmp/remotefilecopying"
|
||||
tmpfile = File.join(testdir, "tmpfile")
|
||||
assert_nothing_raised {
|
||||
Dir.mkdir(testdir)
|
||||
File.open(tmpfile, "w") { |f|
|
||||
3.times { f.puts rand(100) }
|
||||
}
|
||||
@@tmpfiles << testdir
|
||||
}
|
||||
|
||||
file = nil
|
||||
checks = Puppet::FileServer::CHECKPARAMS
|
||||
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount(testdir, "test")
|
||||
}
|
||||
|
||||
list = nil
|
||||
assert_nothing_raised {
|
||||
list = server.list("/test/", true)
|
||||
}
|
||||
|
||||
assert(list =~ /tmpfile/)
|
||||
|
||||
assert_nothing_raised {
|
||||
list = server.list("/test", true)
|
||||
}
|
||||
assert(list =~ /tmpfile/)
|
||||
|
||||
end
|
||||
|
||||
def test_getfilelist
|
||||
server = nil
|
||||
testdir = "/tmp/remotefilecopying"
|
||||
#subdir = "testingyo"
|
||||
#subpath = File.join(testdir, "testingyo")
|
||||
#dir = File.join(testdir, subdir)
|
||||
tmpfile = File.join(testdir, "tmpfile")
|
||||
assert_nothing_raised {
|
||||
Dir.mkdir(testdir)
|
||||
#Dir.mkdir(subpath)
|
||||
File.open(tmpfile, "w") { |f|
|
||||
3.times { f.puts rand(100) }
|
||||
}
|
||||
@@tmpfiles << testdir
|
||||
}
|
||||
|
||||
file = nil
|
||||
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount(testdir, "test")
|
||||
}
|
||||
|
||||
list = nil
|
||||
sfile = "/test/tmpfile"
|
||||
assert_nothing_raised {
|
||||
list = server.list(sfile, true)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
file = Puppet::Type::PFile[tmpfile]
|
||||
}
|
||||
|
||||
output = "/\tfile"
|
||||
|
||||
assert_equal(output, list)
|
||||
assert(list !~ /\t\t/)
|
||||
|
||||
list.split("\n").each { |line|
|
||||
assert(line !~ %r{remotefile})
|
||||
}
|
||||
contents = File.read(tmpfile)
|
||||
|
||||
ret = nil
|
||||
assert_nothing_raised {
|
||||
ret = server.retrieve(sfile)
|
||||
}
|
||||
|
||||
assert_equal(contents, ret)
|
||||
end
|
||||
|
||||
def test_seenewfiles
|
||||
server = nil
|
||||
testdir = "/tmp/remotefilecopying"
|
||||
oldfile = File.join(testdir, "oldfile")
|
||||
newfile = File.join(testdir, "newfile")
|
||||
assert_nothing_raised {
|
||||
Dir.mkdir(testdir)
|
||||
File.open(oldfile, "w") { |f|
|
||||
3.times { f.puts rand(100) }
|
||||
}
|
||||
@@tmpfiles << testdir
|
||||
}
|
||||
|
||||
file = nil
|
||||
checks = Puppet::FileServer::CHECKPARAMS
|
||||
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount(testdir, "test")
|
||||
}
|
||||
|
||||
list = nil
|
||||
sfile = "/test/"
|
||||
assert_nothing_raised {
|
||||
list = server.list(sfile, true)
|
||||
}
|
||||
|
||||
File.open(newfile, "w") { |f|
|
||||
3.times { f.puts rand(100) }
|
||||
}
|
||||
|
||||
newlist = nil
|
||||
assert_nothing_raised {
|
||||
newlist = server.list(sfile, true)
|
||||
}
|
||||
|
||||
assert(list != newlist)
|
||||
|
||||
assert(newlist =~ /newfile/)
|
||||
end
|
||||
|
||||
def test_mountroot
|
||||
server = nil
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount("/", "root")
|
||||
}
|
||||
|
||||
testdir = "/tmp/remotefilecopying"
|
||||
oldfile = File.join(testdir, "oldfile")
|
||||
assert_nothing_raised {
|
||||
Dir.mkdir(testdir)
|
||||
File.open(oldfile, "w") { |f|
|
||||
3.times { f.puts rand(100) }
|
||||
}
|
||||
@@tmpfiles << testdir
|
||||
}
|
||||
|
||||
list = nil
|
||||
assert_nothing_raised {
|
||||
list = server.list("/root/" + testdir, true)
|
||||
}
|
||||
|
||||
assert(list =~ /oldfile/)
|
||||
end
|
||||
|
||||
def test_recursionlevels
|
||||
server = nil
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
basedir = "/tmp/remotefilecopying"
|
||||
testdir = "%s/with/some/sub/directories/for/the/purposes/of/testing" % basedir
|
||||
oldfile = File.join(testdir, "oldfile")
|
||||
assert_nothing_raised {
|
||||
system("mkdir -p %s" % testdir)
|
||||
File.open(oldfile, "w") { |f|
|
||||
3.times { f.puts rand(100) }
|
||||
}
|
||||
@@tmpfiles << basedir
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount(basedir, "test")
|
||||
}
|
||||
|
||||
list = nil
|
||||
assert_nothing_raised {
|
||||
list = server.list("/test/with", false)
|
||||
}
|
||||
|
||||
assert(list !~ /\n/)
|
||||
|
||||
[0, 1, 2].each { |num|
|
||||
assert_nothing_raised {
|
||||
list = server.list("/test/with", num)
|
||||
}
|
||||
|
||||
count = 0
|
||||
#p list
|
||||
while list =~ /\n/
|
||||
list.sub!(/\n/, '')
|
||||
count += 1
|
||||
end
|
||||
assert_equal(num, count)
|
||||
}
|
||||
end
|
||||
|
||||
def test_listedpath
|
||||
server = nil
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
basedir = "/tmp/remotefilecopying"
|
||||
testdir = "%s/with/some/sub/directories/for/testing" % basedir
|
||||
oldfile = File.join(testdir, "oldfile")
|
||||
assert_nothing_raised {
|
||||
system("mkdir -p %s" % testdir)
|
||||
File.open(oldfile, "w") { |f|
|
||||
3.times { f.puts rand(100) }
|
||||
}
|
||||
@@tmpfiles << basedir
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount(basedir, "localhost")
|
||||
}
|
||||
|
||||
list = nil
|
||||
assert_nothing_raised {
|
||||
list = server.list("/localhost/with", false)
|
||||
}
|
||||
|
||||
assert(list !~ /with/)
|
||||
|
||||
assert_nothing_raised {
|
||||
list = server.list("/localhost/with/some/sub", true)
|
||||
}
|
||||
|
||||
assert(list !~ /sub/)
|
||||
end
|
||||
|
||||
def test_widelists
|
||||
server = nil
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
basedir = "/tmp/remotefilecopying"
|
||||
dirs = %w{a set of directories}
|
||||
assert_nothing_raised {
|
||||
Dir.mkdir(basedir)
|
||||
dirs.each { |dir|
|
||||
Dir.mkdir(File.join(basedir, dir))
|
||||
}
|
||||
@@tmpfiles << basedir
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount(basedir, "localhost")
|
||||
}
|
||||
|
||||
list = nil
|
||||
assert_nothing_raised {
|
||||
list = server.list("/localhost/", 1).split("\n")
|
||||
}
|
||||
|
||||
assert_equal(dirs.length + 1, list.length)
|
||||
end
|
||||
|
||||
def test_describe
|
||||
server = nil
|
||||
testdir = "/tmp/remotefilecopying"
|
||||
assert_nothing_raised {
|
||||
Dir.mkdir(testdir)
|
||||
@@tmpfiles << testdir
|
||||
%w{a b c d e}.each { |l|
|
||||
name = File.join(testdir, "file%s" % name)
|
||||
File.open(name, "w") { |f|
|
||||
f.puts rand(100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file = nil
|
||||
checks = Puppet::FileServer::CHECKPARAMS
|
||||
|
||||
assert_nothing_raised {
|
||||
server = Puppet::FileServer.new(
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
server.mount(testdir, "test")
|
||||
}
|
||||
|
||||
list = nil
|
||||
sfile = "/test/"
|
||||
assert_nothing_raised {
|
||||
list = server.list(sfile, true)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
list.split("\n").each { |line|
|
||||
file, type = line.split("\t")
|
||||
|
||||
desc = server.describe(sfile + file)
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# $Id$
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
if __FILE__ == $0
|
||||
if Dir.getwd =~ /test\/server$/
|
||||
Dir.chdir("..")
|
||||
#puts "Unfortunately, you must be in the test dir to run this test."
|
||||
#puts "Yes, I know it's different than all of the others."
|
||||
#exit
|
||||
end
|
||||
|
||||
$:.unshift '../lib'
|
||||
$:.unshift '../../../library/trunk/lib/'
|
||||
$:.unshift '../../../library/trunk/test/'
|
||||
$puppetbase = ".."
|
||||
|
||||
end
|
||||
|
||||
#if __FILE__ == $0
|
||||
# $:.unshift '../../lib'
|
||||
# $:.unshift '../../../../library/trunk/lib/'
|
||||
# $:.unshift '../../../../library/trunk/test/'
|
||||
# $puppetbase = "../.."
|
||||
#end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/master'
|
||||
require 'puppet/client'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
|
||||
class TestMaster < Test::Unit::TestCase
|
||||
def setup
|
||||
if __FILE__ == $0
|
||||
Puppet[:loglevel] = :debug
|
||||
end
|
||||
|
||||
@@tmpfiles = []
|
||||
end
|
||||
|
||||
def stopservices
|
||||
if stype = Puppet::Type.type(:service)
|
||||
stype.each { |service|
|
||||
service[:running] = false
|
||||
service.sync
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def teardown
|
||||
Puppet::Type.allclear
|
||||
print "\n\n\n\n" if Puppet[:debug]
|
||||
|
||||
@@tmpfiles.each { |file|
|
||||
if FileTest.exists?(file)
|
||||
system("rm -rf %s" % file)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_files
|
||||
Puppet[:debug] = true if __FILE__ == $0
|
||||
Puppet[:puppetconf] = "/tmp/servertestingdir"
|
||||
@@tmpfiles << Puppet[:puppetconf]
|
||||
textfiles { |file|
|
||||
Puppet.debug("parsing %s" % file)
|
||||
server = nil
|
||||
client = nil
|
||||
threads = []
|
||||
port = 8080
|
||||
master = nil
|
||||
assert_nothing_raised() {
|
||||
# this is the default server setup
|
||||
master = Puppet::Master.new(
|
||||
:File => file,
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
client = Puppet::Client.new(
|
||||
:Server => master
|
||||
)
|
||||
}
|
||||
|
||||
# pull our configuration
|
||||
assert_nothing_raised() {
|
||||
client.getconfig
|
||||
stopservices
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
client.getconfig
|
||||
stopservices
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
client.getconfig
|
||||
stopservices
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_defaultmanifest
|
||||
Puppet[:debug] = true if __FILE__ == $0
|
||||
Puppet[:puppetconf] = "/tmp/servertestingdir"
|
||||
@@tmpfiles << Puppet[:puppetconf]
|
||||
textfiles { |file|
|
||||
Puppet[:manifest] = file
|
||||
client = nil
|
||||
master = nil
|
||||
assert_nothing_raised() {
|
||||
# this is the default server setup
|
||||
master = Puppet::Master.new(
|
||||
:File => file,
|
||||
:Local => true
|
||||
)
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
client = Puppet::Client.new(
|
||||
:Server => master
|
||||
)
|
||||
}
|
||||
|
||||
# pull our configuration
|
||||
assert_nothing_raised() {
|
||||
client.getconfig
|
||||
stopservices
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# $Id$
|
||||
|
|
@ -0,0 +1,364 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift '../../../../library/trunk/lib/'
|
||||
$:.unshift '../../../../library/trunk/test/'
|
||||
$puppetbase = "../.."
|
||||
end
|
||||
#if __FILE__ == $0
|
||||
# $:.unshift '../lib'
|
||||
# $:.unshift '../../../library/trunk/lib/'
|
||||
# $:.unshift '../../../library/trunk/test/'
|
||||
# $puppetbase = ".."
|
||||
#
|
||||
#
|
||||
# if Dir.getwd !~ /test$/
|
||||
# puts "Unfortunately, you must be in the test dir to run this test."
|
||||
# puts "Yes, I know it's different than all of the others."
|
||||
# exit
|
||||
# end
|
||||
#end
|
||||
|
||||
require 'puppet'
|
||||
require 'cgi'
|
||||
require 'puppet/server'
|
||||
require 'facter'
|
||||
require 'puppet/client'
|
||||
require 'xmlrpc/client'
|
||||
require 'test/unit'
|
||||
require 'puppettest.rb'
|
||||
|
||||
# $Id$
|
||||
|
||||
if ARGV.length > 0 and ARGV[0] == "short"
|
||||
$short = true
|
||||
else
|
||||
$short = false
|
||||
end
|
||||
|
||||
class TestServer < Test::Unit::TestCase
|
||||
def setup
|
||||
if __FILE__ == $0
|
||||
Puppet[:loglevel] = :debug
|
||||
#paths = Puppet::Type.type(:service).searchpath
|
||||
#paths.push "%s/examples/root/etc/init.d" % $puppetbase
|
||||
#Puppet::Type.type(:service).setpath(paths)
|
||||
end
|
||||
|
||||
@@tmpfiles = []
|
||||
@@tmppids = []
|
||||
end
|
||||
|
||||
def stopservices
|
||||
if stype = Puppet::Type.type(:service)
|
||||
stype.each { |service|
|
||||
service[:running] = false
|
||||
service.sync
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def teardown
|
||||
Puppet::Type.allclear
|
||||
print "\n\n\n\n" if Puppet[:debug]
|
||||
|
||||
@@tmpfiles.each { |file|
|
||||
if FileTest.exists?(file)
|
||||
system("rm -rf %s" % file)
|
||||
end
|
||||
}
|
||||
@@tmppids.each { |pid|
|
||||
system("kill -INT %s" % pid)
|
||||
}
|
||||
end
|
||||
|
||||
def test_start
|
||||
server = nil
|
||||
Puppet[:ssldir] = "/tmp/serverstarttesting"
|
||||
Puppet[:autosign] = true
|
||||
@@tmpfiles << "/tmp/serverstarttesting"
|
||||
port = 8081
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
assert_nothing_raised() {
|
||||
server = Puppet::Server.new(
|
||||
:Port => port,
|
||||
:Handlers => {
|
||||
:CA => {}, # so that certs autogenerate
|
||||
:Master => {
|
||||
:File => file,
|
||||
},
|
||||
:Status => nil
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
sthread = nil
|
||||
assert_nothing_raised() {
|
||||
trap(:INT) { server.shutdown }
|
||||
sthread = Thread.new {
|
||||
server.start
|
||||
}
|
||||
}
|
||||
sleep 1
|
||||
assert_nothing_raised {
|
||||
server.shutdown
|
||||
}
|
||||
assert_nothing_raised {
|
||||
sthread.join
|
||||
}
|
||||
end
|
||||
|
||||
# disabled because i can't find a good way to test client connecting
|
||||
# i'll have to test the external executables
|
||||
def disabled_test_connect_with_threading
|
||||
server = nil
|
||||
Puppet[:ssldir] = "/tmp/serverconnecttesting"
|
||||
Puppet[:autosign] = true
|
||||
@@tmpfiles << "/tmp/serverconnecttesting"
|
||||
threads = []
|
||||
port = 8080
|
||||
server = nil
|
||||
Thread.abort_on_exception = true
|
||||
assert_nothing_raised() {
|
||||
server = Puppet::Server.new(
|
||||
:Port => port,
|
||||
:Handlers => {
|
||||
:CA => {}, # so that certs autogenerate
|
||||
:Status => nil
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
sthread = Thread.new {
|
||||
assert_nothing_raised() {
|
||||
#trap(:INT) { server.shutdown; Kernel.exit! }
|
||||
trap(:INT) { server.shutdown }
|
||||
server.start
|
||||
}
|
||||
}
|
||||
|
||||
sleep(3)
|
||||
client = nil
|
||||
assert_nothing_raised() {
|
||||
client = XMLRPC::Client.new("localhost", "/RPC2", port, nil, nil,
|
||||
nil, nil, true, 3)
|
||||
}
|
||||
retval = nil
|
||||
|
||||
clthread = Thread.new {
|
||||
assert_nothing_raised() {
|
||||
Puppet.notice "calling status"
|
||||
retval = client.call("status.status", "")
|
||||
}
|
||||
}
|
||||
assert_not_nil(clthread.join(5))
|
||||
|
||||
assert_equal(1, retval)
|
||||
assert_nothing_raised {
|
||||
#system("kill -INT %s" % serverpid)
|
||||
server.shutdown
|
||||
}
|
||||
|
||||
assert_not_nil(sthread.join(5))
|
||||
|
||||
#Process.wait
|
||||
end
|
||||
|
||||
# disabled because i can't find a good way to test client connecting
|
||||
# i'll have to test the external executables
|
||||
def test_connect_with_fork
|
||||
server = nil
|
||||
Puppet[:ssldir] = "/tmp/serverconnecttesting"
|
||||
Puppet[:autosign] = true
|
||||
@@tmpfiles << "/tmp/serverconnecttesting"
|
||||
serverpid = nil
|
||||
port = 8080
|
||||
assert_nothing_raised() {
|
||||
server = Puppet::Server.new(
|
||||
:Port => port,
|
||||
:Handlers => {
|
||||
:CA => {}, # so that certs autogenerate
|
||||
:Status => nil
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
serverpid = fork {
|
||||
assert_nothing_raised() {
|
||||
#trap(:INT) { server.shutdown; Kernel.exit! }
|
||||
trap(:INT) { server.shutdown }
|
||||
server.start
|
||||
}
|
||||
}
|
||||
@@tmppids << serverpid
|
||||
|
||||
sleep(3)
|
||||
client = nil
|
||||
assert_nothing_raised() {
|
||||
client = XMLRPC::Client.new("localhost", "/RPC2", port, nil, nil,
|
||||
nil, nil, true, 3)
|
||||
}
|
||||
retval = nil
|
||||
|
||||
assert_nothing_raised() {
|
||||
Puppet.notice "calling status"
|
||||
retval = client.call("status.status")
|
||||
}
|
||||
|
||||
assert_equal(1, retval)
|
||||
#assert_nothing_raised {
|
||||
# system("kill -INT %s" % serverpid)
|
||||
# #server.shutdown
|
||||
#}
|
||||
|
||||
#Process.wait
|
||||
end
|
||||
|
||||
# disabled because i can't find a good way to test client connecting
|
||||
# i'll have to test the external executables
|
||||
def test_zzgetconfig_with_fork
|
||||
server = nil
|
||||
Puppet[:ssldir] = "/tmp/serverconfigtesting"
|
||||
Puppet[:autosign] = true
|
||||
@@tmpfiles << "/tmp/serverconfigtesting"
|
||||
serverpid = nil
|
||||
port = 8082
|
||||
file = File.join($puppetbase, "examples", "code", "head")
|
||||
assert_nothing_raised() {
|
||||
server = Puppet::Server.new(
|
||||
:Port => port,
|
||||
:Handlers => {
|
||||
:CA => {}, # so that certs autogenerate
|
||||
:Master => {
|
||||
:File => file
|
||||
},
|
||||
:Status => nil
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
serverpid = fork {
|
||||
assert_nothing_raised() {
|
||||
#trap(:INT) { server.shutdown; Kernel.exit! }
|
||||
trap(:INT) { server.shutdown }
|
||||
server.start
|
||||
}
|
||||
}
|
||||
@@tmppids << serverpid
|
||||
|
||||
sleep(3)
|
||||
client = nil
|
||||
|
||||
# first use a puppet client object
|
||||
assert_nothing_raised() {
|
||||
client = Puppet::Client.new(
|
||||
:Server => "localhost",
|
||||
:Port => port
|
||||
)
|
||||
}
|
||||
retval = nil
|
||||
|
||||
assert_nothing_raised() {
|
||||
Puppet.notice "calling status"
|
||||
retval = client.getconfig
|
||||
}
|
||||
|
||||
# then use a raw rpc client
|
||||
assert_nothing_raised() {
|
||||
client = XMLRPC::Client.new("localhost", "/RPC2", port, nil, nil,
|
||||
nil, nil, true, 3)
|
||||
}
|
||||
retval = nil
|
||||
|
||||
facts = CGI.escape(Marshal.dump(Puppet::Client.facts))
|
||||
assert_nothing_raised() {
|
||||
Puppet.notice "calling status"
|
||||
retval = client.call("puppetmaster.getconfig", facts)
|
||||
}
|
||||
|
||||
#assert_equal(1, retval)
|
||||
end
|
||||
|
||||
# disabled because clients can't seem to connect from in the same process
|
||||
def disabled_test_files
|
||||
Puppet[:debug] = true if __FILE__ == $0
|
||||
Puppet[:puppetconf] = "/tmp/servertestingdir"
|
||||
Puppet[:autosign] = true
|
||||
@@tmpfiles << Puppet[:puppetconf]
|
||||
textfiles { |file|
|
||||
Puppet.debug("parsing %s" % file)
|
||||
server = nil
|
||||
client = nil
|
||||
threads = []
|
||||
port = 8080
|
||||
assert_nothing_raised() {
|
||||
# this is the default server setup
|
||||
server = Puppet::Server.new(
|
||||
:Port => port,
|
||||
:Handlers => {
|
||||
:CA => {}, # so that certs autogenerate
|
||||
:Master => {
|
||||
:File => file,
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
client = Puppet::Client.new(
|
||||
:Server => "localhost",
|
||||
:Port => port
|
||||
)
|
||||
}
|
||||
|
||||
# start the server
|
||||
assert_nothing_raised() {
|
||||
trap(:INT) { server.shutdown }
|
||||
threads << Thread.new {
|
||||
server.start
|
||||
}
|
||||
}
|
||||
|
||||
# start the client
|
||||
#assert_nothing_raised() {
|
||||
# threads << Thread.new {
|
||||
# client.start
|
||||
# }
|
||||
#}
|
||||
|
||||
sleep(1)
|
||||
# pull our configuration
|
||||
assert_nothing_raised() {
|
||||
client.getconfig
|
||||
stopservices
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
client.getconfig
|
||||
stopservices
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
client.getconfig
|
||||
stopservices
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
|
||||
# and shut them both down
|
||||
assert_nothing_raised() {
|
||||
[server].each { |thing|
|
||||
thing.shutdown
|
||||
}
|
||||
}
|
||||
|
||||
# make sure everything's complete before we stop
|
||||
assert_nothing_raised() {
|
||||
threads.each { |thr|
|
||||
thr.join
|
||||
}
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
stopservices
|
||||
}
|
||||
Puppet::Type.allclear
|
||||
}
|
||||
end
|
||||
end
|
13
test/test
13
test/test
|
@ -7,14 +7,13 @@
|
|||
|
||||
$:.unshift '.'
|
||||
$:.unshift '../lib'
|
||||
$:.unshift '../../../language/trunk/lib/'
|
||||
|
||||
# if we're not in the library trunk, then add that to the lib search path
|
||||
if Dir.getwd !~ %r{puppet/library}
|
||||
$:.unshift '../../../library/trunk/lib/'
|
||||
$:.unshift '../../../language/trunk/lib/'
|
||||
$:.unshift '../../../library/trunk/test/'
|
||||
end
|
||||
#if Dir.getwd !~ %r{puppet/library}
|
||||
# $:.unshift '../../../library/trunk/lib/'
|
||||
# $:.unshift '../../../language/trunk/lib/'
|
||||
# $:.unshift '../../../library/trunk/test/'
|
||||
#end
|
||||
|
||||
require 'puppettest.rb'
|
||||
|
||||
|
@ -37,7 +36,7 @@ result.each { |opt,arg|
|
|||
end
|
||||
}
|
||||
|
||||
$puppetbase = "../../../language/trunk"
|
||||
$puppetbase = ".."
|
||||
|
||||
suites = nil
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
if __FILE__ == $0
|
||||
$:.unshift '..'
|
||||
$:.unshift '../../lib'
|
||||
$:.unshift "../../../../language/trunk/lib"
|
||||
$puppetbase = "../../../../language/trunk"
|
||||
end
|
||||
|
||||
|
@ -67,7 +68,7 @@ class TestFile < Test::Unit::TestCase
|
|||
Puppet::Storage.clear
|
||||
end
|
||||
|
||||
def test_zzowner
|
||||
def test_owner
|
||||
file = mktestfile()
|
||||
|
||||
users = {}
|
||||
|
@ -137,6 +138,9 @@ class TestFile < Test::Unit::TestCase
|
|||
us[uid] = name
|
||||
users.each { |uid, name|
|
||||
# just make sure we don't try to manage users
|
||||
assert_nothing_raised() {
|
||||
file.sync
|
||||
}
|
||||
assert_nothing_raised() {
|
||||
file[:owner] = name
|
||||
}
|
||||
|
@ -151,7 +155,7 @@ class TestFile < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_zzgroup
|
||||
def test_group
|
||||
file = mktestfile()
|
||||
[%x{groups}.chomp.split(/ /), Process.groups].flatten.each { |group|
|
||||
assert_nothing_raised() {
|
||||
|
@ -493,6 +497,8 @@ class TestFile < Test::Unit::TestCase
|
|||
trans.evaluate
|
||||
}
|
||||
|
||||
assert(FileTest.exists?(todir))
|
||||
|
||||
clearstorage
|
||||
Puppet::Type.allclear
|
||||
end
|
||||
|
@ -518,7 +524,7 @@ class TestFile < Test::Unit::TestCase
|
|||
return [fromdir,todir]
|
||||
end
|
||||
|
||||
def test_complex_sources_twice
|
||||
def test_zzzcomplex_sources_twice
|
||||
fromdir, todir = run_complex_sources
|
||||
assert_trees_equal(fromdir,todir)
|
||||
recursive_source_test(fromdir, todir)
|
||||
|
@ -528,6 +534,7 @@ class TestFile < Test::Unit::TestCase
|
|||
def test_sources_with_deleted_destfiles
|
||||
fromdir, todir = run_complex_sources
|
||||
# then delete some files
|
||||
assert(FileTest.exists?(todir))
|
||||
delete_random_files(todir)
|
||||
|
||||
# and run
|
||||
|
@ -539,6 +546,7 @@ class TestFile < Test::Unit::TestCase
|
|||
|
||||
def test_sources_with_readonly_destfiles
|
||||
fromdir, todir = run_complex_sources
|
||||
assert(FileTest.exists?(todir))
|
||||
readonly_random_files(todir)
|
||||
recursive_source_test(fromdir, todir)
|
||||
|
||||
|
@ -549,6 +557,7 @@ class TestFile < Test::Unit::TestCase
|
|||
def test_sources_with_modified_dest_files
|
||||
fromdir, todir = run_complex_sources
|
||||
|
||||
assert(FileTest.exists?(todir))
|
||||
# then modify some files
|
||||
modify_random_files(todir)
|
||||
|
||||
|
@ -560,6 +569,7 @@ class TestFile < Test::Unit::TestCase
|
|||
|
||||
def test_sources_with_added_destfiles
|
||||
fromdir, todir = run_complex_sources
|
||||
assert(FileTest.exists?(todir))
|
||||
# and finally, add some new files
|
||||
add_random_files(todir)
|
||||
|
||||
|
@ -582,4 +592,84 @@ class TestFile < Test::Unit::TestCase
|
|||
# and make sure they're still equal
|
||||
assert_trees_equal(fromdir,todir)
|
||||
end
|
||||
|
||||
def test_filetype_retrieval
|
||||
file = nil
|
||||
assert_nothing_raised {
|
||||
file = Puppet::Type::PFile.new(
|
||||
:name => "/tmp",
|
||||
:check => :type
|
||||
)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
file.evaluate
|
||||
}
|
||||
|
||||
assert_equal("directory", file.state(:type).is)
|
||||
|
||||
assert_nothing_raised {
|
||||
file = Puppet::Type::PFile.new(
|
||||
:name => "/etc/passwd",
|
||||
:check => :type
|
||||
)
|
||||
}
|
||||
|
||||
assert_nothing_raised {
|
||||
file.evaluate
|
||||
}
|
||||
|
||||
assert_equal("file", file.state(:type).is)
|
||||
|
||||
assert_raise(Puppet::Error) {
|
||||
file[:type] = "directory"
|
||||
}
|
||||
|
||||
assert(file.insync?)
|
||||
|
||||
assert_raise(Puppet::Error) {
|
||||
file.sync
|
||||
}
|
||||
end
|
||||
|
||||
def test_RecursionWithAddedFiles
|
||||
basedir = "/tmp/recursionplussaddedfiles"
|
||||
Dir.mkdir(basedir)
|
||||
@@tmpfiles << basedir
|
||||
file1 = File.join(basedir, "file1")
|
||||
file2 = File.join(basedir, "file2")
|
||||
subdir1 = File.join(basedir, "subdir1")
|
||||
file3 = File.join(subdir1, "file")
|
||||
File.open(file1, "w") { |f| 3.times { f.print rand(100) } }
|
||||
rootobj = nil
|
||||
assert_nothing_raised {
|
||||
rootobj = Puppet::Type::PFile.new(
|
||||
:name => basedir,
|
||||
:recurse => true,
|
||||
:check => %w{type owner}
|
||||
)
|
||||
|
||||
rootobj.evaluate
|
||||
}
|
||||
|
||||
klass = Puppet::Type::PFile
|
||||
assert(klass[basedir])
|
||||
assert(klass[file1])
|
||||
assert_nil(klass[file2])
|
||||
|
||||
File.open(file2, "w") { |f| 3.times { f.print rand(100) } }
|
||||
|
||||
assert_nothing_raised {
|
||||
rootobj.evaluate
|
||||
}
|
||||
assert(klass[file2])
|
||||
|
||||
Dir.mkdir(subdir1)
|
||||
File.open(file3, "w") { |f| 3.times { f.print rand(100) } }
|
||||
|
||||
assert_nothing_raised {
|
||||
rootobj.evaluate
|
||||
}
|
||||
assert(klass[file3])
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче