summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Berry <paul@puppetlabs.com>2010-11-10 16:05:15 -0800
committerPaul Berry <paul@puppetlabs.com>2010-11-10 16:06:04 -0800
commit2b8e834fcbc548a221b4cd02ee7200fa4f6c2c78 (patch)
treed7c11657d0bfd44488b235c95819f62f7431b949
parent7236a33d6c5c9fbb0f46ffd7826965dbaae6a39b (diff)
parent275a224ee245577c4213b3a21bf1e98301740a4e (diff)
downloadpuppet-2b8e834fcbc548a221b4cd02ee7200fa4f6c2c78.tar.gz
puppet-2b8e834fcbc548a221b4cd02ee7200fa4f6c2c78.tar.xz
puppet-2b8e834fcbc548a221b4cd02ee7200fa4f6c2c78.zip
Merge branch 'next'
This marks the end of the agile iteration from 11/3-11/10.
-rw-r--r--CHANGELOG9
-rwxr-xr-xext/cert_inspector140
-rwxr-xr-xext/envpuppet80
-rw-r--r--ext/puppet-load.rb88
-rw-r--r--lib/puppet/defaults.rb19
-rw-r--r--lib/puppet/indirector/facts/rest.rb2
-rwxr-xr-xlib/puppet/network/handler/fileserver.rb2
-rw-r--r--lib/puppet/parser/ast/resource.rb7
-rw-r--r--lib/puppet/parser/compiler.rb4
-rw-r--r--lib/puppet/parser/lexer.rb3
-rw-r--r--lib/puppet/provider/service/launchd.rb2
-rw-r--r--lib/puppet/resource.rb10
-rw-r--r--lib/puppet/resource/type.rb31
-rw-r--r--lib/puppet/type/service.rb2
-rwxr-xr-xlib/puppet/type/tidy.rb10
-rw-r--r--lib/puppet/util/monkey_patches.rb8
-rw-r--r--lib/puppet/util/reference.rb2
-rwxr-xr-xspec/unit/application/agent_spec.rb41
-rwxr-xr-xspec/unit/parser/ast/resource_spec.rb238
-rwxr-xr-xspec/unit/parser/compiler_spec.rb16
-rwxr-xr-xspec/unit/parser/lexer_spec.rb1
-rwxr-xr-xspec/unit/resource/type_spec.rb26
-rwxr-xr-xspec/unit/type/service_spec.rb4
-rwxr-xr-xspec/unit/type/tidy_spec.rb3
-rw-r--r--tasks/rake/git_workflow.rake13
25 files changed, 568 insertions, 193 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 1a28fd8e6..e708b2b6b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,14 @@
+2.6.3rc2
+========
+76ac1f8 Fixed #5112 - Launchd Service broke in 2.6.2 with OS X 10.4 Clients.
+776ea2a Fixed #5137 - Removed no longer required TOC references
+31118fe Kludge for #5048 -- serialization compatibility with 0.25.x
+65ef24e (#4534/#4778) -- Normalize parameterized classes
+3b53bfc Fix for #5022 -- Escaped newlines should be elided
+
2.6.3rc1
========
+e3fc5b9 Updated CHANGELOG and version for 2.6.3rc1
3c56705 Fix for #4832 -- Making PSON handle arbitrary binary data
e232770 Minimal fix for #4975 -- only call chage when managing password age rules
a090e86 Fix for #4963 -- Use correct commands for password expiry on solaris
diff --git a/ext/cert_inspector b/ext/cert_inspector
new file mode 100755
index 000000000..1effcaa04
--- /dev/null
+++ b/ext/cert_inspector
@@ -0,0 +1,140 @@
+#!/usr/bin/env ruby
+require 'openssl'
+
+class X509Collector
+ include Enumerable
+
+ def initialize
+ @collected_data = {}
+ end
+
+ def interpret_contents(contents)
+ cls = case contents.split("\n")[0]
+ when /BEGIN X509 CRL/ then OpenSSL::X509::CRL
+ when /BEGIN CERTIFICATE REQUEST/ then OpenSSL::X509::Request
+ when /BEGIN CERTIFICATE/ then OpenSSL::X509::Certificate
+ when /BEGIN RSA (PRIVATE|PUBLIC) KEY/ then OpenSSL::PKey::RSA
+ else return nil
+ end
+ cls.new(contents)
+ rescue
+ nil
+ end
+
+ def expected_non_x509_files
+ ['inventory.txt', 'ca.pass', 'serial']
+ end
+
+ def investigate_path(path)
+ if File.directory?(path)
+ Dir.foreach(path) do |x|
+ next if ['.', '..'].include? x
+ investigate_path File.join(path, x)
+ end
+ else
+ contents = File.read path
+ meaning = interpret_contents contents
+ unless meaning || expected_non_x509_files.include?(File.basename(path))
+ puts "WARNING: file #{path.inspect} could not be interpreted"
+ end
+ @collected_data[path] = meaning if meaning
+ end
+ end
+
+ def each(&block)
+ @collected_data.each(&block)
+ end
+
+ def extract_public_key_info(path, meaning)
+ case meaning
+ when OpenSSL::PKey::RSA
+ if meaning.private?
+ [meaning.public_key, 2, path]
+ else
+ [meaning, 3, path]
+ end
+ when OpenSSL::X509::Certificate
+ [meaning.public_key, 0, meaning.subject.to_s]
+ when OpenSSL::X509::Request
+ [meaning.public_key, 1, meaning.subject.to_s]
+ end
+ end
+
+ def who_signed(meaning, key_names, keys)
+ signing_key = keys.find { |key| meaning.verify(key) }
+ if signing_key then "#{key_names[signing_key.to_s]}" else "???" end
+ end
+
+ def explain(meaning, key_names, keys)
+ case meaning
+ when OpenSSL::PKey::RSA
+ if meaning.private?
+ "Private key for #{key_names[meaning.public_key.to_s]}"
+ else
+ "Public key for #{key_names[meaning.public_key.to_s]}"
+ end
+ when OpenSSL::X509::Certificate
+ signature_desc = who_signed(meaning, key_names, keys)
+ "Certificate assigning name #{meaning.subject.to_s} to #{key_names[meaning.public_key.to_s]}\n serial number #{meaning.serial}\n issued by #{meaning.issuer.to_s}\n signed by #{signature_desc}"
+ when OpenSSL::X509::Request
+ signature_desc = who_signed(meaning, key_names, keys)
+ "Certificate request for #{meaning.subject.to_s} having key #{key_names[meaning.public_key.to_s]}\n signed by #{signature_desc}"
+ when OpenSSL::X509::CRL
+ signature_desc = who_signed(meaning, key_names, keys)
+ revoked_serial_numbers = meaning.revoked.map { |r| r.serial }
+ revoked_desc = if revoked_serial_numbers.count > 0 then "serial numbers #{revoked_serial_numbers.inspect}" else "nothing" end
+ "Certificate revocation list revoking #{revoked_desc}\n issued by #{meaning.issuer.to_s}\n signed by #{signature_desc}"
+ else
+ "Unknown"
+ end
+ end
+
+ # Yield unique public keys, with a canonical name for each.
+ def collect_public_keys
+ key_data = {} # pem => (priority, name, public_key)
+ @collected_data.collect do |path, meaning|
+ begin
+ next unless public_key_info = extract_public_key_info(path, meaning)
+ public_key, priority, name = public_key_info
+ pem = public_key.to_s
+ existing_priority, existing_name, existing_public_key = key_data[pem]
+ next if existing_priority and existing_priority < priority
+ key_data[pem] = priority, name, public_key
+ rescue
+ puts "exception!"
+ end
+ end
+ name_to_key_hash = {}
+ key_data.each do |pem, data|
+ priority, name, public_key = data
+ if name_to_key_hash[name]
+ suffix_num = 2
+ while name_to_key_hash[name + " (#{suffix_num})"]
+ suffix_num += 1
+ end
+ name = name + " (#{suffix_num})"
+ end
+ name_to_key_hash[name] = public_key
+ end
+ key_names = {}
+ keys = []
+ name_to_key_hash.each do |name, public_key|
+ key_names[public_key.to_s] = "key<#{name}>"
+ keys << public_key
+ end
+ [key_names, keys]
+ end
+end
+
+collector = X509Collector.new
+ARGV.each do |path|
+ collector.investigate_path(path)
+end
+key_names, keys = collector.collect_public_keys
+collector.map do |path, meaning|
+ [collector.explain(meaning, key_names, keys), path]
+end.sort.each do |description, path|
+ puts "#{path}:"
+ puts " #{description}"
+ puts
+end
diff --git a/ext/envpuppet b/ext/envpuppet
new file mode 100755
index 000000000..d921a19b8
--- /dev/null
+++ b/ext/envpuppet
@@ -0,0 +1,80 @@
+#! /bin/bash
+#
+# Jeff McCune <jeff@puppetlabs.com>
+# 2010-10-20
+#
+# Copyright (c) 2010, Puppet Labs
+# License: BSD 3-clause license
+#
+# This script provides a simple way to execute puppet and related tools
+# directly from a git clone of the upstream repositories. This allows you to
+# quickly switch branches and test different versions of code without much
+# friction.
+#
+# NOTE: There may be issues if puppet, facter, etc... are already installed
+# into RUBY's site_ruby directory. If you run into strange problems, make sure
+# the correct ruby libraries are being loaded...
+#
+# Sample Usage:
+# =============
+# cd ~/src
+# git clone git://github.com/puppetlabs/puppet.git
+# git clone git://github.com/puppetlabs/facter.git
+# pushd puppet
+# git checkout tags/2.6.1
+# popd
+# pushd facter
+# git checkout tags/1.5.8
+# export ENVPUPPET_BASEDIR=/home/jeff/src
+# envpuppet puppet --version
+# 2.6.1
+# envpuppet facter --version
+# 1.5.8
+
+set -e
+set -u
+
+if test -d puppet -o -d facter; then
+ echo " WARNING!"
+ echo " Strange things happen if puppet or facter are in the"
+ echo " current working directory"
+ echo " (import errors from ruby are a prime example)"
+ echo " WARNING!"
+ echo ""
+ echo "I suggest changing to ~ or /tmp or something..."
+ echo ""
+ echo "Sleeping 2 seconds."
+ echo ""
+ sleep 2
+fi
+
+# Set this to where you check out puppet and facter
+: ${ENVPUPPET_BASEDIR:="${HOME}/src"}
+
+# git://github.com/reductivelabs/puppet.git
+mypath="${ENVPUPPET_BASEDIR}/puppet/sbin:${ENVPUPPET_BASEDIR}/puppet/bin"
+myrubylib="${ENVPUPPET_BASEDIR}/puppet/lib"
+
+# git://github.com/reductivelabs/facter.git
+mypath="${mypath}:${ENVPUPPET_BASEDIR}/facter/bin"
+myrubylib="${myrubylib}:${ENVPUPPET_BASEDIR}/facter/lib"
+
+# http://github.com/jamtur01/puppet-scaffold.git
+mypath="${mypath}:${ENVPUPPET_BASEDIR}/puppet-scaffold/bin"
+myrubylib="${myrubylib}:${ENVPUPPET_BASEDIR}/puppet-scaffold/lib"
+
+# http://github.com/puppetlabs/puppet-module-tool.git
+# Also known as "pmt" Will become "puppet module"
+mypath="${mypath}:${ENVPUPPET_BASEDIR}/puppet-module-tool/bin"
+myrubylib="${myrubylib}:${ENVPUPPET_BASEDIR}/puppet-module-tool/lib"
+
+# Use the existing environment, if present.
+# Default to no value to prevent unbound variable issues
+mypath="${mypath}:${PATH:-}"
+myrubylib="${myrubylib}:${RUBYLIB:-}"
+
+# Trim any trailing colons from the path list.
+export PATH="${mypath%%:}"
+export RUBYLIB="${myrubylib%%:}"
+
+exec "$@"
diff --git a/ext/puppet-load.rb b/ext/puppet-load.rb
index 110282d01..35bee6ef8 100644
--- a/ext/puppet-load.rb
+++ b/ext/puppet-load.rb
@@ -14,7 +14,7 @@
#
# puppet-load [-d|--debug] [--concurrency <num>] [--repeat <num>] [-V|--version] [-v|--verbose]
# [--node <host.domain.com>] [--facts <factfile>] [--cert <certfile>] [--key <keyfile>]
-# [--server <server.domain.com>]
+# [--factsdir <factsdir>] [--server <server.domain.com>]
#
# = Description
#
@@ -35,8 +35,9 @@
# Set the puppet master hostname or IP address..
#
# node::
-# Set the fully-qualified domain name of the client. This is only used for
-# certificate purposes, but can be used to override the discovered hostname.
+# Set the fully-qualified domain name of the client. This option can be given multiple
+# times. In this case puppet-load will ask for catalog compilation of all the given nodes
+# on a round robin way.
#
# help::
# Print this help message
@@ -46,6 +47,11 @@
# file as found in the clientyaml directory. If none are provided, puppet-load
# will look by itself using Puppet facts indirector.
#
+# factsdir::
+# Specify a directory where the yaml facts files can be found. If provided puppet-load
+# will look up facts in this directory. If not found it will resort to using Puppet Facts
+# indirector.
+#
# cert::
# This option is mandatory. It should be set to the cert PEM file that will be used
# to quthenticate the client connections.
@@ -70,8 +76,9 @@
#
# = Example usage
#
+# SINGLE NODE:
# 1) On the master host, generate a new certificate and private key for our test host:
-# puppet ca --generate puppet-load.domain.com [*]
+# puppet ca --generate puppet-load.domain.com
#
# 2) Copy the cert and key to the puppet-load host (which can be the same as the master one)
#
@@ -81,7 +88,7 @@
# allow $1
# allow puppet-load.domain.com
#
-# 4) launch the master
+# 4) launch the master(s)
#
# 5) Prepare or get a fact file. One way to get one is to look on the master in $vardir/yaml/ for the host
# you want to simulate.
@@ -89,12 +96,30 @@
# 5) launch puppet-load
# puppet-load -debug --node server.domain.com --server master.domain.com --facts server.domain.com.yaml --concurrency 2 --repeat 20
#
-# [*]: unfortunately at this stage Puppet trusts the certname of the connecting node more than
-# than the node name request paramater. It means that the master will compile
-# the puppet-load node and not the --node given.
+# MULTIPLE NODES:
+# 1) On the master host, generate a new certificate and private key for our test host:
+# puppet ca --generate puppet-load.domain.com
+#
+# 2) Copy the cert and key to the puppet-load host (which can be the same as the master one)
+#
+# 3) On the master host edit or create the auth.conf so that the catalog ACL match:
+# path ~ ^/catalog/([^/]+)$
+# method find
+# allow $1
+# allow puppet-load.domain.com
+#
+# 4) launch the master(s)
+#
+# 5) Prepare or get a fact file. One way to get one is to look on the master in $vardir/yaml/ for the host
+# you want to simulate.
+#
+# 5) launch puppet-load
+# puppet-load -debug --node server1.domain.com --node server2.domain.com --node server3.domain.com \
+# --server master.domain.com --factsdir /var/lib/puppet/yaml/facts --concurrency 2 --repeat 20
+#
+# puppet-load will load facts file in the --factsdir directory based on the node name.
#
# = TODO
-# * Allow to simulate any different nodes
# * More output stats for error connections (ie report errors, HTTP code...)
#
#
@@ -115,6 +140,7 @@ $cmdargs = [
[ "--concurrency", "-c", GetoptLong::REQUIRED_ARGUMENT ],
[ "--node", "-n", GetoptLong::REQUIRED_ARGUMENT ],
[ "--facts", GetoptLong::REQUIRED_ARGUMENT ],
+ [ "--factsdir", GetoptLong::REQUIRED_ARGUMENT ],
[ "--repeat", "-r", GetoptLong::REQUIRED_ARGUMENT ],
[ "--cert", "-C", GetoptLong::REQUIRED_ARGUMENT ],
[ "--key", "-k", GetoptLong::REQUIRED_ARGUMENT ],
@@ -131,14 +157,15 @@ Puppet::Util::Log.newdestination(:console)
times = {}
def read_facts(file)
- YAML.load(File.read(file))
+ Puppet.debug("reading facts from: #{file}")
+ fact = YAML.load(File.read(file))
end
result = GetoptLong.new(*$cmdargs)
$args = {}
-$options = {:repeat => 1, :concurrency => 1, :pause => false, :cert => nil, :key => nil, :timeout => 180, :masterport => 8140}
+$options = {:repeat => 1, :concurrency => 1, :pause => false, :cert => nil, :key => nil, :timeout => 180, :masterport => 8140, :node => [], :factsdir => nil}
begin
result.each { |opt,arg|
@@ -151,7 +178,9 @@ begin
exit(14)
end
when "--node"
- $options[:node] = arg
+ $options[:node] << arg
+ when "--factsdir"
+ $options[:factsdir] = arg
when "--server"
$options[:server] = arg
when "--masterport"
@@ -192,21 +221,24 @@ unless $options[:cert] and $options[:key]
raise "--cert and --key are mandatory to authenticate the client"
end
-unless $options[:facts] and facts = read_facts($options[:facts])
- unless facts = Puppet::Node::Facts.find($options[:node])
- raise "Could not find facts for %s" % $options[:node]
- end
-end
+parameters = []
-unless $options[:node]
+unless $options[:node].size > 0
raise "--node is a mandatory argument. It tells to the master what node to compile"
end
-facts.values["fqdn"] = $options[:node]
-facts.values["hostname"] = $options[:node].sub(/\..+/, '')
-facts.values["domain"] = $options[:node].sub(/^[^.]+\./, '')
+$options[:node].each do |node|
+ factfile = $options[:factsdir] ? File.join($options[:factsdir], node + ".yaml") : $options[:facts]
+ unless fact = read_facts(factfile) or fact = Puppet::Node::Facts.find(node)
+ raise "Could not find facts for %s" % node
+ end
+ fact.values["fqdn"] = node
+ fact.values["hostname"] = node.sub(/\..+/, '')
+ fact.values["domain"] = node.sub(/^[^.]+\./, '')
+
+ parameters << {:facts_format => "b64_zlib_yaml", :facts => CGI.escape(fact.render(:b64_zlib_yaml))}
+end
-parameters = {:facts_format => "b64_zlib_yaml", :facts => CGI.escape(facts.render(:b64_zlib_yaml))}
class RequestPool
include EventMachine::Deferrable
@@ -233,17 +265,21 @@ class RequestPool
end
def spawn_request(index)
- EventMachine::HttpRequest.new("https://#{$options[:server]}:#{$options[:masterport]}/production/catalog/#{$options[:node]}").get(
+ @times[index] = Time.now
+ @sizes[index] = 0
+ nodeidx = index % $options[:node].size
+ node = $options[:node][nodeidx]
+ EventMachine::HttpRequest.new("https://#{$options[:server]}:#{$options[:masterport]}/production/catalog/#{node}").get(
:port => $options[:masterport],
- :query => @parameters,
+ :query => @parameters[nodeidx],
:timeout => $options[:timeout],
:head => { "Accept" => "pson, yaml, b64_zlib_yaml, marshal, dot, raw", "Accept-Encoding" => "gzip, deflate" },
:ssl => { :private_key_file => $options[:key],
:cert_chain_file => $options[:cert],
:verify_peer => false } ) do
- Puppet.debug("starting client #{index}")
@times[index] = Time.now
@sizes[index] = 0
+ Puppet.debug("starting client #{index} for #{node}")
end
end
@@ -268,7 +304,7 @@ class RequestPool
}
conn.errback {
- Puppet.debug("Client #{index} finished with an error: #{conn.response.error}")
+ Puppet.debug("Client #{index} finished with an error: #{conn.error}")
@times[index] = Time.now - @times[index]
@responses[:failed].push(conn)
check_progress
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index c7bebf8f5..7ae553827 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -115,7 +115,16 @@ module Puppet
:node_terminus => ["plain", "Where to find information about nodes."],
:catalog_terminus => ["compiler", "Where to get node catalogs. This is useful to change if, for instance,
you'd like to pre-compile catalogs and store them in memcached or some other easily-accessed store."],
- :facts_terminus => [Puppet.application_name.to_s == "master" ? 'yaml' : 'facter', "The node facts terminus."],
+ :facts_terminus => {
+ :default => Puppet.application_name.to_s == "master" ? 'yaml' : 'facter',
+ :desc => "The node facts terminus.",
+ :hook => proc do |value|
+ require 'puppet/node/facts'
+ if value.to_s == "rest"
+ Puppet::Node::Facts.cache_class = :yaml
+ end
+ end
+ },
:inventory_terminus => [ "$facts_terminus", "Should usually be the same as the facts terminus" ],
:httplog => { :default => "$logdir/http.log",
:owner => "root",
@@ -579,11 +588,17 @@ module Puppet
end
},
:report_server => ["$server",
- "The server to which to send transaction reports."
+ "The server to send transaction reports to."
],
:report_port => ["$masterport",
"The port to communicate with the report_server."
],
+ :inventory_server => ["$server",
+ "The server to send facts to."
+ ],
+ :inventory_port => ["$masterport",
+ "The port to communicate with the inventory_server."
+ ],
:report => [false,
"Whether to send reports after every transaction."
],
diff --git a/lib/puppet/indirector/facts/rest.rb b/lib/puppet/indirector/facts/rest.rb
index 07491fc77..e2afa14b2 100644
--- a/lib/puppet/indirector/facts/rest.rb
+++ b/lib/puppet/indirector/facts/rest.rb
@@ -3,4 +3,6 @@ require 'puppet/indirector/rest'
class Puppet::Node::Facts::Rest < Puppet::Indirector::REST
desc "Find and save facts about nodes over HTTP via REST."
+ use_server_setting(:inventory_server)
+ use_port_setting(:inventory_port)
end
diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb
index 27b913ab9..8844ab990 100755
--- a/lib/puppet/network/handler/fileserver.rb
+++ b/lib/puppet/network/handler/fileserver.rb
@@ -4,9 +4,11 @@ require 'webrick/httpstatus'
require 'cgi'
require 'delegate'
require 'sync'
+require 'xmlrpc/server'
require 'puppet/file_serving'
require 'puppet/file_serving/metadata'
+require 'puppet/network/handler'
class Puppet::Network::Handler
AuthStoreError = Puppet::AuthStoreError
diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb
index bd15d9935..ce3c499c5 100644
--- a/lib/puppet/parser/ast/resource.rb
+++ b/lib/puppet/parser/ast/resource.rb
@@ -53,10 +53,11 @@ class Resource < AST::Branch
:strict => true
)
- # And then store the resource in the compiler.
- # At some point, we need to switch all of this to return
- # resources instead of storing them like this.
+ if resource.resource_type.is_a? Puppet::Resource::Type
+ resource.resource_type.instantiate_resource(scope, resource)
+ end
scope.compiler.add_resource(scope, resource)
+ scope.compiler.evaluate_classes([resource_title],scope,false) if fully_qualified_type == 'class'
resource
end
}
diff --git a/lib/puppet/parser/compiler.rb b/lib/puppet/parser/compiler.rb
index e1227e753..c60e1d4fb 100644
--- a/lib/puppet/parser/compiler.rb
+++ b/lib/puppet/parser/compiler.rb
@@ -144,7 +144,7 @@ class Puppet::Parser::Compiler
if klass = scope.find_hostclass(name)
found << name and next if scope.class_scope(klass)
- resource = klass.mk_plain_resource(scope)
+ resource = klass.ensure_in_catalog(scope)
# If they've disabled lazy evaluation (which the :include function does),
# then evaluate our resource immediately.
@@ -220,7 +220,7 @@ class Puppet::Parser::Compiler
# Create a resource to model this node, and then add it to the list
# of resources.
- resource = astnode.mk_plain_resource(topscope)
+ resource = astnode.ensure_in_catalog(topscope)
resource.evaluate
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index 9036d652e..31d39ae2f 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -522,13 +522,14 @@ class Puppet::Parser::Lexer
# backslash; the caret is there to match empty strings
str = @scanner.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]/) or lex_error "Unclosed quote after '#{last}' in '#{rest}'"
@line += str.count("\n") # literal carriage returns add to the line count.
- str.gsub!(/\\(.)/) {
+ str.gsub!(/\\(.)/m) {
ch = $1
if escapes.include? ch
case ch
when 'n'; "\n"
when 't'; "\t"
when 's'; " "
+ when "\n": ''
else ch
end
else
diff --git a/lib/puppet/provider/service/launchd.rb b/lib/puppet/provider/service/launchd.rb
index b296e0a38..1632edabf 100644
--- a/lib/puppet/provider/service/launchd.rb
+++ b/lib/puppet/provider/service/launchd.rb
@@ -56,7 +56,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
# Read a plist, whether its format is XML or in Apple's "binary1"
# format.
def self.read_plist(path)
- Plist::parse_xml(plutil('-convert', 'xml1', '-o', '-', path))
+ Plist::parse_xml(plutil('-convert', 'xml1', '-o', '/dev/stdout', path))
end
# returns a label => path map for either all jobs, or just a single
diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb
index 39803b077..7dea270e8 100644
--- a/lib/puppet/resource.rb
+++ b/lib/puppet/resource.rb
@@ -154,6 +154,14 @@ class Puppet::Resource
end
end
+ # This stub class is only needed for serialization compatibility with 0.25.x
+ class Reference
+ attr_accessor :type,:title
+ def initialize(type,title)
+ @type,@title = type,title
+ end
+ end
+
# Create our resource.
def initialize(type, title = nil, attributes = {})
@parameters = {}
@@ -180,6 +188,8 @@ class Puppet::Resource
tag(self.type)
tag(self.title) if valid_tag?(self.title)
+ @reference = Reference.new(@type,@title) # for serialization compatibility with 0.25.x
+
raise ArgumentError, "Invalid resource type #{type}" if strict? and ! resource_type
end
diff --git a/lib/puppet/resource/type.rb b/lib/puppet/resource/type.rb
index 3edf286bb..77824845d 100644
--- a/lib/puppet/resource/type.rb
+++ b/lib/puppet/resource/type.rb
@@ -140,21 +140,15 @@ class Puppet::Resource::Type
end
end
- # Make an instance of our resource type. This is only possible
- # for those classes and nodes that don't have any arguments, and is
- # only useful for things like the 'include' function.
- def mk_plain_resource(scope)
+ # Make an instance of the resource type, and place it in the catalog
+ # if it isn't in the catalog already. This is only possible for
+ # classes and nodes. No parameters are be supplied--if this is a
+ # parameterized class, then all parameters take on their default
+ # values.
+ def ensure_in_catalog(scope)
type == :definition and raise ArgumentError, "Cannot create resources for defined resource types"
resource_type = type == :hostclass ? :class : :node
- # Make sure our parent class has been evaluated, if we have one.
- if parent
- parent_resource = scope.catalog.resource(resource_type, parent)
- unless parent_resource
- parent_type(scope).mk_plain_resource(scope)
- end
- end
-
# Do nothing if the resource already exists; this makes sure we don't
# get multiple copies of the class resource, which helps provide the
# singleton nature of classes.
@@ -163,11 +157,22 @@ class Puppet::Resource::Type
end
resource = Puppet::Parser::Resource.new(resource_type, name, :scope => scope, :source => self)
+ instantiate_resource(scope, resource)
scope.compiler.add_resource(scope, resource)
- scope.catalog.tag(*resource.tags)
resource
end
+ def instantiate_resource(scope, resource)
+ # Make sure our parent class has been evaluated, if we have one.
+ if parent && !scope.catalog.resource(resource.type, parent)
+ parent_type(scope).ensure_in_catalog(scope)
+ end
+
+ if ['Class', 'Node'].include? resource.type
+ scope.catalog.tag(*resource.tags)
+ end
+ end
+
def name
return @name unless @name.is_a?(Regexp)
@name.source.downcase.gsub(/[^-\w:.]/,'').sub(/^\.+/,'')
diff --git a/lib/puppet/type/service.rb b/lib/puppet/type/service.rb
index c00f02789..786a50448 100644
--- a/lib/puppet/type/service.rb
+++ b/lib/puppet/type/service.rb
@@ -100,6 +100,8 @@ module Puppet
looked for in the process table."
newvalues(:true, :false)
+
+ defaultto :true
end
newparam(:name) do
desc "The name of the service to run. This name is used to find
diff --git a/lib/puppet/type/tidy.rb b/lib/puppet/type/tidy.rb
index 65cc077cf..93a7e96cf 100755
--- a/lib/puppet/type/tidy.rb
+++ b/lib/puppet/type/tidy.rb
@@ -141,15 +141,17 @@ Puppet::Type.newtype(:tidy) do
newparam(:size) do
desc "Tidy files whose size is equal to or greater than
the specified size. Unqualified values are in kilobytes, but
- *b*, *k*, and *m* can be appended to specify *bytes*, *kilobytes*,
- and *megabytes*, respectively. Only the first character is
- significant, so the full word can also be used."
+ *b*, *k*, *m*, *g*, and *t* can be appended to specify *bytes*,
+ *kilobytes*, *megabytes*, *gigabytes*, and *terabytes*, respectively.
+ Only the first character is significant, so the full word can also
+ be used."
@@sizeconvertors = {
:b => 0,
:k => 1,
:m => 2,
- :g => 3
+ :g => 3,
+ :t => 4
}
def convert(unit, multi)
diff --git a/lib/puppet/util/monkey_patches.rb b/lib/puppet/util/monkey_patches.rb
index 6b5af8350..bdce5ec1d 100644
--- a/lib/puppet/util/monkey_patches.rb
+++ b/lib/puppet/util/monkey_patches.rb
@@ -48,3 +48,11 @@ if RUBY_VERSION == '1.8.7'
end
end
+class Object
+ # ActiveSupport 2.3.x mixes in a dangerous method
+ # that can cause rspec to fork bomb
+ # and other strange things like that.
+ def daemonize
+ raise NotImplementedError, "Kernel.daemonize is too dangerous, please don't try to use it."
+ end
+end
diff --git a/lib/puppet/util/reference.rb b/lib/puppet/util/reference.rb
index 99458aa57..ab201cde4 100644
--- a/lib/puppet/util/reference.rb
+++ b/lib/puppet/util/reference.rb
@@ -32,7 +32,6 @@ class Puppet::Util::Reference
section = reference(name) or raise "Could not find section #{name}"
depth = section.depth if section.depth < depth
end
- text = "* TOC text.\n{:toc}\n\n"
end
def self.pdf(text)
@@ -141,7 +140,6 @@ class Puppet::Util::Reference
# First the header
text = h(@title, 1)
text += "\n\n**This page is autogenerated; any changes will get overwritten** *(last generated on #{Time.now.to_s})*\n\n"
- text += "* TOC Text.\n{:toc}\n\n" if withcontents
text += @header
diff --git a/spec/unit/application/agent_spec.rb b/spec/unit/application/agent_spec.rb
index 54726c185..8fc98b8c1 100755
--- a/spec/unit/application/agent_spec.rb
+++ b/spec/unit/application/agent_spec.rb
@@ -6,6 +6,7 @@ require 'puppet/agent'
require 'puppet/application/agent'
require 'puppet/network/server'
require 'puppet/daemon'
+require 'puppet/network/handler'
describe Puppet::Application::Agent do
before :each do
@@ -13,6 +14,7 @@ describe Puppet::Application::Agent do
@puppetd.stubs(:puts)
@daemon = stub_everything 'daemon'
Puppet::Daemon.stubs(:new).returns(@daemon)
+ Puppet[:daemonize] = false
@agent = stub_everything 'agent'
Puppet::Agent.stubs(:new).returns(@agent)
@puppetd.preinit
@@ -175,11 +177,7 @@ describe Puppet::Application::Agent do
@puppetd.options.stubs(:[])
Puppet.stubs(:info)
FileTest.stubs(:exists?).returns(true)
- Puppet.stubs(:[])
- Puppet.stubs(:[]=)
- Puppet.stubs(:[]).with(:libdir).returns("/dev/null/lib")
- Puppet.settings.stubs(:print_config?)
- Puppet.settings.stubs(:print_config)
+ Puppet[:libdir] = "/dev/null/lib"
Puppet::SSL::Host.stubs(:ca_location=)
Puppet::Transaction::Report.stubs(:terminus_class=)
Puppet::Resource::Catalog.stubs(:terminus_class=)
@@ -192,7 +190,7 @@ describe Puppet::Application::Agent do
describe "with --test" do
before :each do
- Puppet.settings.stubs(:handlearg)
+ #Puppet.settings.stubs(:handlearg)
@puppetd.options.stubs(:[]=)
end
@@ -207,8 +205,9 @@ describe Puppet::Application::Agent do
@puppetd.setup_test
end
it "should set options[:onetime] to true" do
- Puppet.expects(:[]=).with(:onetime,true)
+ Puppet[:onetime] = false
@puppetd.setup_test
+ Puppet[:onetime].should == true
end
it "should set options[:detailed_exitcodes] to true" do
@puppetd.options.expects(:[]=).with(:detailed_exitcodes,true)
@@ -264,7 +263,7 @@ describe Puppet::Application::Agent do
it "should print puppet config if asked to in Puppet config" do
@puppetd.stubs(:exit)
- Puppet.settings.stubs(:print_configs?).returns(true)
+ Puppet[:configprint] = "pluginsync"
Puppet.settings.expects(:print_configs)
@@ -272,14 +271,14 @@ describe Puppet::Application::Agent do
end
it "should exit after printing puppet config if asked to in Puppet config" do
- Puppet.settings.stubs(:print_configs?).returns(true)
+ Puppet[:configprint] = "pluginsync"
lambda { @puppetd.setup }.should raise_error(SystemExit)
end
it "should set a central log destination with --centrallogs" do
@puppetd.options.stubs(:[]).with(:centrallogs).returns(true)
- Puppet.stubs(:[]).with(:server).returns("puppet.reductivelabs.com")
+ Puppet[:server] = "puppet.reductivelabs.com"
Puppet::Util::Log.stubs(:newdestination).with(:syslog)
Puppet::Util::Log.expects(:newdestination).with("puppet.reductivelabs.com")
@@ -313,8 +312,9 @@ describe Puppet::Application::Agent do
end
it "should change the catalog_terminus setting to 'rest'" do
- Puppet.expects(:[]=).with(:catalog_terminus, :rest)
+ Puppet[:catalog_terminus] = :foo
@puppetd.setup
+ Puppet[:catalog_terminus].should == :rest
end
it "should tell the catalog handler to use cache" do
@@ -324,9 +324,10 @@ describe Puppet::Application::Agent do
end
it "should change the facts_terminus setting to 'facter'" do
- Puppet.expects(:[]=).with(:facts_terminus, :facter)
+ Puppet[:facts_terminus] = :foo
@puppetd.setup
+ Puppet[:facts_terminus].should == :facter
end
it "should create an agent" do
@@ -374,7 +375,7 @@ describe Puppet::Application::Agent do
end
it "should daemonize if needed" do
- Puppet.stubs(:[]).with(:daemonize).returns(true)
+ Puppet[:daemonize] = true
@daemon.expects(:daemonize)
@@ -397,7 +398,7 @@ describe Puppet::Application::Agent do
end
it "should setup listen if told to and not onetime" do
- Puppet.stubs(:[]).with(:listen).returns(true)
+ Puppet[:listen] = true
@puppetd.options.stubs(:[]).with(:onetime).returns(false)
@puppetd.expects(:setup_listen)
@@ -407,7 +408,7 @@ describe Puppet::Application::Agent do
describe "when setting up listen" do
before :each do
- Puppet.stubs(:[]).with(:authconfig).returns('auth')
+ Puppet[:authconfig] = 'auth'
FileTest.stubs(:exists?).with('auth').returns(true)
File.stubs(:exist?).returns(true)
@puppetd.options.stubs(:[]).with(:serve).returns([])
@@ -419,7 +420,7 @@ describe Puppet::Application::Agent do
it "should exit if no authorization file" do
Puppet.stubs(:err)
- FileTest.stubs(:exists?).with('auth').returns(false)
+ FileTest.stubs(:exists?).with(Puppet[:authconfig]).returns(false)
@puppetd.expects(:exit)
@@ -440,9 +441,9 @@ describe Puppet::Application::Agent do
end
it "should use puppet default port" do
- Puppet.stubs(:[]).with(:puppetport).returns(:port)
+ Puppet[:puppetport] = 32768
- Puppet::Network::Server.expects(:new).with { |args| args[:port] == :port }
+ Puppet::Network::Server.expects(:new).with { |args| args[:port] == 32768 }
@puppetd.setup_listen
end
@@ -521,7 +522,7 @@ describe Puppet::Application::Agent do
end
it "should exit with report's computed exit status" do
- Puppet.stubs(:[]).with(:noop).returns(false)
+ Puppet[:noop] = false
report = stub 'report', :exit_status => 666
@agent.stubs(:run).returns(report)
@puppetd.expects(:exit).with(666)
@@ -530,7 +531,7 @@ describe Puppet::Application::Agent do
end
it "should always exit with 0 if --noop" do
- Puppet.stubs(:[]).with(:noop).returns(true)
+ Puppet[:noop] = true
report = stub 'report', :exit_status => 666
@agent.stubs(:run).returns(report)
@puppetd.expects(:exit).with(0)
diff --git a/spec/unit/parser/ast/resource_spec.rb b/spec/unit/parser/ast/resource_spec.rb
index a8e783256..3ed7b3e08 100755
--- a/spec/unit/parser/ast/resource_spec.rb
+++ b/spec/unit/parser/ast/resource_spec.rb
@@ -5,134 +5,180 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
describe Puppet::Parser::AST::Resource do
ast = Puppet::Parser::AST
- before :each do
- @title = Puppet::Parser::AST::String.new(:value => "mytitle")
- @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
- @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
- @scope.stubs(:resource).returns(stub_everything)
- @instance = ast::ResourceInstance.new(:title => @title, :parameters => ast::ASTArray.new(:children => []))
- @resource = ast::Resource.new(:type => "file", :instances => ast::ASTArray.new(:children => [@instance]))
- @resource.stubs(:qualified_type).returns("Resource")
- end
+ describe "for builtin types" do
+ before :each do
+ @title = Puppet::Parser::AST::String.new(:value => "mytitle")
+ @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
+ @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
+ @scope.stubs(:resource).returns(stub_everything)
+ @instance = ast::ResourceInstance.new(:title => @title, :parameters => ast::ASTArray.new(:children => []))
+ @resource = ast::Resource.new(:type => "file", :instances => ast::ASTArray.new(:children => [@instance]))
+ @resource.stubs(:qualified_type).returns("Resource")
+ end
- it "should evaluate all its parameters" do
- param = stub 'param'
- param.expects(:safeevaluate).with(@scope).returns Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", :source => stub("source"))
- @instance.stubs(:parameters).returns [param]
+ it "should evaluate all its parameters" do
+ param = stub 'param'
+ param.expects(:safeevaluate).with(@scope).returns Puppet::Parser::Resource::Param.new(:name => "myparam", :value => "myvalue", :source => stub("source"))
+ @instance.stubs(:parameters).returns [param]
- @resource.evaluate(@scope)
- end
+ @resource.evaluate(@scope)
+ end
- it "should evaluate its title" do
- @resource.evaluate(@scope)[0].title.should == "mytitle"
- end
+ it "should evaluate its title" do
+ @resource.evaluate(@scope)[0].title.should == "mytitle"
+ end
+
+ it "should flatten the titles array" do
+ titles = []
+ %w{one two}.each do |title|
+ titles << Puppet::Parser::AST::String.new(:value => title)
+ end
- it "should flatten the titles array" do
- titles = []
- %w{one two}.each do |title|
- titles << Puppet::Parser::AST::String.new(:value => title)
+ array = Puppet::Parser::AST::ASTArray.new(:children => titles)
+
+ @instance.title = array
+ result = @resource.evaluate(@scope).collect { |r| r.title }
+ result.should be_include("one")
+ result.should be_include("two")
end
- array = Puppet::Parser::AST::ASTArray.new(:children => titles)
+ it "should create and return one resource objects per title" do
+ titles = []
+ %w{one two}.each do |title|
+ titles << Puppet::Parser::AST::String.new(:value => title)
+ end
- @instance.title = array
- result = @resource.evaluate(@scope).collect { |r| r.title }
- result.should be_include("one")
- result.should be_include("two")
- end
+ array = Puppet::Parser::AST::ASTArray.new(:children => titles)
- it "should create and return one resource objects per title" do
- titles = []
- %w{one two}.each do |title|
- titles << Puppet::Parser::AST::String.new(:value => title)
+ @instance.title = array
+ result = @resource.evaluate(@scope).collect { |r| r.title }
+ result.should be_include("one")
+ result.should be_include("two")
end
- array = Puppet::Parser::AST::ASTArray.new(:children => titles)
+ it "should implicitly iterate over instances" do
+ new_title = Puppet::Parser::AST::String.new(:value => "other_title")
+ new_instance = ast::ResourceInstance.new(:title => new_title, :parameters => ast::ASTArray.new(:children => []))
+ @resource.instances.push(new_instance)
+ @resource.evaluate(@scope).collect { |r| r.title }.should == ["mytitle", "other_title"]
+ end
- @instance.title = array
- result = @resource.evaluate(@scope).collect { |r| r.title }
- result.should be_include("one")
- result.should be_include("two")
- end
+ it "should handover resources to the compiler" do
+ titles = []
+ %w{one two}.each do |title|
+ titles << Puppet::Parser::AST::String.new(:value => title)
+ end
- it "should implicitly iterate over instances" do
- new_title = Puppet::Parser::AST::String.new(:value => "other_title")
- new_instance = ast::ResourceInstance.new(:title => new_title, :parameters => ast::ASTArray.new(:children => []))
- @resource.instances.push(new_instance)
- @resource.evaluate(@scope).collect { |r| r.title }.should == ["mytitle", "other_title"]
- end
+ array = Puppet::Parser::AST::ASTArray.new(:children => titles)
- it "should handover resources to the compiler" do
- titles = []
- %w{one two}.each do |title|
- titles << Puppet::Parser::AST::String.new(:value => title)
+ @instance.title = array
+ result = @resource.evaluate(@scope)
+
+ result.each do |res|
+ @compiler.catalog.resource(res.ref).should be_instance_of(Puppet::Parser::Resource)
+ end
end
- array = Puppet::Parser::AST::ASTArray.new(:children => titles)
+ it "should generate virtual resources if it is virtual" do
+ @resource.virtual = true
+
+ result = @resource.evaluate(@scope)
+ result[0].should be_virtual
+ end
- @instance.title = array
- result = @resource.evaluate(@scope)
+ it "should generate virtual and exported resources if it is exported" do
+ @resource.exported = true
- result.each do |res|
- @compiler.catalog.resource(res.ref).should be_instance_of(Puppet::Parser::Resource)
+ result = @resource.evaluate(@scope)
+ result[0].should be_virtual
+ result[0].should be_exported
end
- end
- it "should generate virtual resources if it is virtual" do
- @resource.virtual = true
- result = @resource.evaluate(@scope)
- result[0].should be_virtual
- end
+ # Related to #806, make sure resources always look up the full path to the resource.
+ describe "when generating qualified resources" do
+ before do
+ @scope = Puppet::Parser::Scope.new :compiler => Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
+ @parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
+ ["one", "one::two", "three"].each do |name|
+ @parser.environment.known_resource_types.add(Puppet::Resource::Type.new(:definition, name, {}))
+ end
+ @twoscope = @scope.newscope(:namespace => "one")
+ @twoscope.resource = @scope.resource
+ end
- it "should generate virtual and exported resources if it is exported" do
- @resource.exported = true
+ def resource(type, params = nil)
+ params ||= Puppet::Parser::AST::ASTArray.new(:children => [])
+ instance = Puppet::Parser::AST::ResourceInstance.new(
+ :title => Puppet::Parser::AST::String.new(:value => "myresource"), :parameters => params)
+ Puppet::Parser::AST::Resource.new(:type => type,
+ :instances => Puppet::Parser::AST::ASTArray.new(:children => [instance]))
+ end
- result = @resource.evaluate(@scope)
- result[0].should be_virtual
- result[0].should be_exported
- end
+ it "should be able to generate resources with fully qualified type information" do
+ resource("two").evaluate(@twoscope)[0].type.should == "One::Two"
+ end
- # Related to #806, make sure resources always look up the full path to the resource.
- describe "when generating qualified resources" do
- before do
- @scope = Puppet::Parser::Scope.new :compiler => Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
- @parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
- ["one", "one::two", "three"].each do |name|
- @parser.environment.known_resource_types.add(Puppet::Resource::Type.new(:definition, name, {}))
+ it "should be able to generate resources with unqualified type information" do
+ resource("one").evaluate(@twoscope)[0].type.should == "One"
end
- @twoscope = @scope.newscope(:namespace => "one")
- @twoscope.resource = @scope.resource
- end
- def resource(type, params = nil)
- params ||= Puppet::Parser::AST::ASTArray.new(:children => [])
- instance = Puppet::Parser::AST::ResourceInstance.new(
- :title => Puppet::Parser::AST::String.new(:value => "myresource"), :parameters => params)
- Puppet::Parser::AST::Resource.new(:type => type,
- :instances => Puppet::Parser::AST::ASTArray.new(:children => [instance]))
- end
+ it "should correctly generate resources that can look up builtin types" do
+ resource("file").evaluate(@twoscope)[0].type.should == "File"
+ end
- it "should be able to generate resources with fully qualified type information" do
- resource("two").evaluate(@twoscope)[0].type.should == "One::Two"
- end
+ it "should correctly generate resources that can look up defined classes by title" do
+ @scope.known_resource_types.add_hostclass Puppet::Resource::Type.new(:hostclass, "Myresource", {})
+ @scope.compiler.stubs(:evaluate_classes)
+ res = resource("class").evaluate(@twoscope)[0]
+ res.type.should == "Class"
+ res.title.should == "Myresource"
+ end
- it "should be able to generate resources with unqualified type information" do
- resource("one").evaluate(@twoscope)[0].type.should == "One"
+ it "should evaluate parameterized classes when they are instantiated" do
+ @scope.known_resource_types.add_hostclass Puppet::Resource::Type.new(:hostclass, "Myresource", {})
+ @scope.compiler.expects(:evaluate_classes).with(['myresource'],@twoscope,false)
+ resource("class").evaluate(@twoscope)[0]
+ end
+
+ it "should fail for resource types that do not exist" do
+ lambda { resource("nosuchtype").evaluate(@twoscope) }.should raise_error(Puppet::ParseError)
+ end
end
+ end
- it "should correctly generate resources that can look up builtin types" do
- resource("file").evaluate(@twoscope)[0].type.should == "File"
+ describe "for class resources" do
+ before do
+ @title = Puppet::Parser::AST::String.new(:value => "classname")
+ @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
+ @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
+ @scope.stubs(:resource).returns(stub_everything)
+ @instance = ast::ResourceInstance.new(:title => @title, :parameters => ast::ASTArray.new(:children => []))
+ @resource = ast::Resource.new(:type => "Class", :instances => ast::ASTArray.new(:children => [@instance]))
+ @resource.stubs(:qualified_type).returns("Resource")
+ @type = Puppet::Resource::Type.new(:hostclass, "classname")
+ @compiler.known_resource_types.add(@type)
end
- it "should correctly generate resources that can look up defined classes by title" do
- @scope.known_resource_types.add_hostclass Puppet::Resource::Type.new(:hostclass, "Myresource", {})
- res = resource("class").evaluate(@twoscope)[0]
- res.type.should == "Class"
- res.title.should == "Myresource"
+ it "should instantiate the class" do
+ @compiler.stubs(:evaluate_classes)
+ result = @resource.evaluate(@scope)
+ result.length.should == 1
+ result.first.ref.should == "Class[Classname]"
+ @compiler.catalog.resource("Class[Classname]").should equal result.first
end
- it "should fail for resource types that do not exist" do
- lambda { resource("nosuchtype").evaluate(@twoscope) }.should raise_error(Puppet::ParseError)
+ it "should cause its parent to be evaluated" do
+ parent_type = Puppet::Resource::Type.new(:hostclass, "parentname")
+ @compiler.stubs(:evaluate_classes)
+ @compiler.known_resource_types.add(parent_type)
+ @type.parent = "parentname"
+ result = @resource.evaluate(@scope)
+ result.length.should == 1
+ result.first.ref.should == "Class[Classname]"
+ @compiler.catalog.resource("Class[Classname]").should equal result.first
+ @compiler.catalog.resource("Class[Parentname]").should be_instance_of(Puppet::Parser::Resource)
end
+
end
+
end
diff --git a/spec/unit/parser/compiler_spec.rb b/spec/unit/parser/compiler_spec.rb
index 22d52f257..95f3853e2 100755
--- a/spec/unit/parser/compiler_spec.rb
+++ b/spec/unit/parser/compiler_spec.rb
@@ -580,7 +580,7 @@ describe Puppet::Parser::Compiler do
it "should evaluate each class" do
@compiler.catalog.stubs(:tag)
- @class.expects(:mk_plain_resource).with(@scope)
+ @class.expects(:ensure_in_catalog).with(@scope)
@scope.stubs(:class_scope).with(@class)
@compiler.evaluate_classes(%w{myclass}, @scope)
@@ -591,7 +591,7 @@ describe Puppet::Parser::Compiler do
@resource.expects(:evaluate).never
- @class.expects(:mk_plain_resource).returns(@resource)
+ @class.expects(:ensure_in_catalog).returns(@resource)
@scope.stubs(:class_scope).with(@class)
@compiler.evaluate_classes(%w{myclass}, @scope)
@@ -601,7 +601,7 @@ describe Puppet::Parser::Compiler do
@compiler.catalog.stubs(:tag)
@resource.expects(:evaluate)
- @class.expects(:mk_plain_resource).returns(@resource)
+ @class.expects(:ensure_in_catalog).returns(@resource)
@scope.stubs(:class_scope).with(@class)
@compiler.evaluate_classes(%w{myclass}, @scope, false)
@@ -638,7 +638,7 @@ describe Puppet::Parser::Compiler do
@scope.stubs(:class_scope).with(@class)
Puppet::Parser::Resource.stubs(:new).returns(@resource)
- @class.stubs :mk_plain_resource
+ @class.stubs :ensure_in_catalog
@compiler.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass}
end
end
@@ -678,7 +678,7 @@ describe Puppet::Parser::Compiler do
@compiler.known_resource_types.stubs(:node).with("c").returns(node_class)
node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node"
- node_class.expects(:mk_plain_resource).returns(node_resource)
+ node_class.expects(:ensure_in_catalog).returns(node_resource)
@compiler.compile
end
@@ -688,7 +688,7 @@ describe Puppet::Parser::Compiler do
@compiler.known_resource_types.stubs(:node).with("default").returns(node_class)
node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil, :type => "node"
- node_class.expects(:mk_plain_resource).returns(node_resource)
+ node_class.expects(:ensure_in_catalog).returns(node_resource)
@compiler.compile
end
@@ -698,7 +698,7 @@ describe Puppet::Parser::Compiler do
@compiler.known_resource_types.stubs(:node).with("c").returns(node_class)
node_resource = stub 'node resource', :ref => "Node[c]", :type => "node"
- node_class.expects(:mk_plain_resource).returns(node_resource)
+ node_class.expects(:ensure_in_catalog).returns(node_resource)
node_resource.expects(:evaluate)
@@ -707,7 +707,7 @@ describe Puppet::Parser::Compiler do
it "should set the node's scope as the top scope" do
node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node"
- node_class = stub 'node', :name => "c", :mk_plain_resource => node_resource
+ node_class = stub 'node', :name => "c", :ensure_in_catalog => node_resource
@compiler.known_resource_types.stubs(:node).with("c").returns(node_class)
diff --git a/spec/unit/parser/lexer_spec.rb b/spec/unit/parser/lexer_spec.rb
index 2d67bf357..d52add399 100755
--- a/spec/unit/parser/lexer_spec.rb
+++ b/spec/unit/parser/lexer_spec.rb
@@ -424,6 +424,7 @@ describe Puppet::Parser::Lexer,"when lexing strings" do
%q{'single quoted string with an escaped "\\\\"'} => [[:STRING,'single quoted string with an escaped "\\\\"']],
%q{"string with an escaped '\\"'"} => [[:STRING,"string with an escaped '\"'"]],
%q{"string with an escaped '\\$'"} => [[:STRING,"string with an escaped '$'"]],
+ %Q{"string with a line ending with a backslash: \\\nfoo"} => [[:STRING,"string with a line ending with a backslash: foo"]],
%q{"string with $v (but no braces)"} => [[:DQPRE,"string with "],[:VARIABLE,'v'],[:DQPOST,' (but no braces)']],
%q["string with ${v} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,'v'],[:DQPOST,' in braces']],
%q["string with ${qualified::var} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,'qualified::var'],[:DQPOST,' in braces']],
diff --git a/spec/unit/resource/type_spec.rb b/spec/unit/resource/type_spec.rb
index 7701e55d5..ef45712e6 100755
--- a/spec/unit/resource/type_spec.rb
+++ b/spec/unit/resource/type_spec.rb
@@ -579,29 +579,29 @@ describe Puppet::Resource::Type do
end
it "should create a resource instance" do
- @top.mk_plain_resource(@scope).should be_instance_of(Puppet::Parser::Resource)
+ @top.ensure_in_catalog(@scope).should be_instance_of(Puppet::Parser::Resource)
end
it "should set its resource type to 'class' when it is a hostclass" do
- Puppet::Resource::Type.new(:hostclass, "top").mk_plain_resource(@scope).type.should == "Class"
+ Puppet::Resource::Type.new(:hostclass, "top").ensure_in_catalog(@scope).type.should == "Class"
end
it "should set its resource type to 'node' when it is a node" do
- Puppet::Resource::Type.new(:node, "top").mk_plain_resource(@scope).type.should == "Node"
+ Puppet::Resource::Type.new(:node, "top").ensure_in_catalog(@scope).type.should == "Node"
end
it "should fail when it is a definition" do
- lambda { Puppet::Resource::Type.new(:definition, "top").mk_plain_resource(@scope) }.should raise_error(ArgumentError)
+ lambda { Puppet::Resource::Type.new(:definition, "top").ensure_in_catalog(@scope) }.should raise_error(ArgumentError)
end
it "should add the created resource to the scope's catalog" do
- @top.mk_plain_resource(@scope)
+ @top.ensure_in_catalog(@scope)
@compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
end
it "should evaluate the parent class if one exists" do
- @middle.mk_plain_resource(@scope)
+ @middle.ensure_in_catalog(@scope)
@compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
end
@@ -609,40 +609,40 @@ describe Puppet::Resource::Type do
it "should fail to evaluate if a parent class is defined but cannot be found" do
othertop = Puppet::Resource::Type.new :hostclass, "something", :parent => "yay"
@code.add othertop
- lambda { othertop.mk_plain_resource(@scope) }.should raise_error(Puppet::ParseError)
+ lambda { othertop.ensure_in_catalog(@scope) }.should raise_error(Puppet::ParseError)
end
it "should not create a new resource if one already exists" do
@compiler.catalog.expects(:resource).with(:class, "top").returns("something")
@compiler.catalog.expects(:add_resource).never
- @top.mk_plain_resource(@scope)
+ @top.ensure_in_catalog(@scope)
end
it "should return the existing resource when not creating a new one" do
@compiler.catalog.expects(:resource).with(:class, "top").returns("something")
@compiler.catalog.expects(:add_resource).never
- @top.mk_plain_resource(@scope).should == "something"
+ @top.ensure_in_catalog(@scope).should == "something"
end
it "should not create a new parent resource if one already exists and it has a parent class" do
- @top.mk_plain_resource(@scope)
+ @top.ensure_in_catalog(@scope)
top_resource = @compiler.catalog.resource(:class, "top")
- @middle.mk_plain_resource(@scope)
+ @middle.ensure_in_catalog(@scope)
@compiler.catalog.resource(:class, "top").should equal(top_resource)
end
# #795 - tag before evaluation.
it "should tag the catalog with the resource tags when it is evaluated" do
- @middle.mk_plain_resource(@scope)
+ @middle.ensure_in_catalog(@scope)
@compiler.catalog.should be_tagged("middle")
end
it "should tag the catalog with the parent class tags when it is evaluated" do
- @middle.mk_plain_resource(@scope)
+ @middle.ensure_in_catalog(@scope)
@compiler.catalog.should be_tagged("top")
end
diff --git a/spec/unit/type/service_spec.rb b/spec/unit/type/service_spec.rb
index 0958a69fa..77628670a 100755
--- a/spec/unit/type/service_spec.rb
+++ b/spec/unit/type/service_spec.rb
@@ -66,6 +66,10 @@ describe Puppet::Type.type(:service), "when validating attribute values" do
Puppet::Type.type(:service).new(:name => "yay", :hasstatus => :false)
end
+ it "should specify :true as the default value of hasstatus" do
+ Puppet::Type.type(:service).new(:name => "yay")[:hasstatus].should == :true
+ end
+
it "should support :true as a value to :hasrestart" do
Puppet::Type.type(:service).new(:name => "yay", :hasrestart => :true)
end
diff --git a/spec/unit/type/tidy_spec.rb b/spec/unit/type/tidy_spec.rb
index 11edbfbf3..1573ead1b 100755
--- a/spec/unit/type/tidy_spec.rb
+++ b/spec/unit/type/tidy_spec.rb
@@ -110,7 +110,8 @@ describe tidy do
:b => 0,
:kb => 1,
:mb => 2,
- :gb => 3
+ :gb => 3,
+ :tb => 4
}
convertors.each do |unit, multiple|
diff --git a/tasks/rake/git_workflow.rake b/tasks/rake/git_workflow.rake
index b2f96c603..c275bba3f 100644
--- a/tasks/rake/git_workflow.rake
+++ b/tasks/rake/git_workflow.rake
@@ -103,10 +103,21 @@ task :mail_patches do
# Create all of the patches
sh "git format-patch -C -M -s -n --subject-prefix='PATCH/puppet' #{parent}..HEAD"
+ # Add info to the patches
+ additional_info = "Local-branch: #{branch}\n"
+ files = Dir.glob("00*.patch")
+ files.each do |file|
+ contents = File.read(file)
+ contents.sub!(/^---$/, "#{additional_info}---")
+ File.open(file, 'w') do |file_handle|
+ file_handle.print contents
+ end
+ end
+
# And then mail them out.
# If we've got more than one patch, add --compose
- if Dir.glob("00*.patch").length > 1
+ if files.length > 1
compose = "--compose"
else
compose = ""