summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Lewis <nick@puppetlabs.com>2011-07-25 17:02:24 -0700
committerNick Lewis <nick@puppetlabs.com>2011-07-25 17:02:24 -0700
commitb13427b56d8529731d0334d420b24a592ecb43ea (patch)
tree1d2f89907e6136bea2ace8e84a57966779af89d1
parent043c3e87c882d38b9708b6e215425a9935f74769 (diff)
parent8baa4897e777f9515dc1663317f432ace3067bae (diff)
downloadpuppet-b13427b56d8529731d0334d420b24a592ecb43ea.tar.gz
puppet-b13427b56d8529731d0334d420b24a592ecb43ea.tar.xz
puppet-b13427b56d8529731d0334d420b24a592ecb43ea.zip
Merge branch '2.7.x'
Conflicts: lib/puppet/type/file/source.rb spec/unit/resource/catalog_spec.rb
-rw-r--r--CHANGELOG5
-rw-r--r--conf/redhat/puppet.spec47
-rw-r--r--lib/puppet/application/certificate.rb5
-rw-r--r--lib/puppet/application/face_base.rb3
-rw-r--r--lib/puppet/application/inspect.rb7
-rw-r--r--lib/puppet/face/certificate.rb26
-rw-r--r--lib/puppet/face/certificate_request.rb20
-rw-r--r--lib/puppet/face/certificate_revocation_list.rb12
-rw-r--r--lib/puppet/indirector/face.rb24
-rw-r--r--lib/puppet/indirector/report/processor.rb2
-rw-r--r--lib/puppet/interface.rb4
-rw-r--r--lib/puppet/interface/action.rb82
-rw-r--r--lib/puppet/interface/face_collection.rb50
-rw-r--r--lib/puppet/resource/catalog.rb9
-rwxr-xr-xlib/puppet/type/file/source.rb3
-rw-r--r--lib/puppet/type/service.rb44
-rwxr-xr-xspec/lib/puppet/face/1.0.0/huzzah.rb8
-rwxr-xr-xspec/lib/puppet/face/huzzah.rb1
-rw-r--r--spec/lib/puppet/face/huzzah/obsolete.rb6
-rwxr-xr-xspec/unit/application/face_base_spec.rb1
-rwxr-xr-xspec/unit/application/inspect_spec.rb5
-rwxr-xr-xspec/unit/face/certificate_spec.rb20
-rwxr-xr-xspec/unit/indirector/face_spec.rb4
-rwxr-xr-xspec/unit/indirector/report/processor_spec.rb12
-rwxr-xr-xspec/unit/interface/action_spec.rb51
-rwxr-xr-xspec/unit/interface/face_collection_spec.rb42
-rwxr-xr-xspec/unit/interface_spec.rb9
-rwxr-xr-xspec/unit/resource/catalog_spec.rb61
28 files changed, 405 insertions, 158 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 423bc6b5e..de4c5addd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,8 @@
+2.7.2rc2
+===
+8ec0804 (#8301) Red Hat spec file for 2.7.2rc1 won't work
+2263be6 (#5108) Update service type docs for new hasstatus default
+
2.7.2rc1
===
902c414 Update configurer_spec.rb to work with Ruby 1.8.5
diff --git a/conf/redhat/puppet.spec b/conf/redhat/puppet.spec
index 7a586655b..06a4b57b7 100644
--- a/conf/redhat/puppet.spec
+++ b/conf/redhat/puppet.spec
@@ -6,12 +6,12 @@
Name: puppet
Version: 2.7.2
-Release: 0.1.rc1%{?dist}
+Release: 0.2.rc1%{?dist}
Summary: A network tool for managing many disparate systems
-License: Apache 2.0
+License: ASL 2.0
URL: http://puppetlabs.com
Source0: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}rc1.tar.gz
-#Source1: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}.tar.gz.asc
+Source1: http://puppetlabs.com/downloads/%{name}/%{name}-%{version}rc1.tar.gz.asc
Group: System Environment/Base
@@ -110,7 +110,7 @@ touch %{buildroot}%{_sysconfdir}/puppet/puppetmasterd.conf
touch %{buildroot}%{_sysconfdir}/puppet/puppetca.conf
touch %{buildroot}%{_sysconfdir}/puppet/puppetd.conf
-# Install the ext/ directory to %{_datadir}/%{name}
+# Install the ext/ directory to %%{_datadir}/%%{name}
install -d %{buildroot}%{_datadir}/%{name}
cp -a ext/ %{buildroot}%{_datadir}/%{name}
# emacs and vim bits are installed elsewhere
@@ -136,7 +136,7 @@ echo "D /var/run/%{name} 0755 %{name} %{name} -" > \
%files
%defattr(-, root, root, 0755)
-%doc CHANGELOG COPYING LICENSE README.md README.queueing examples
+%doc CHANGELOG LICENSE README.md examples
%{_bindir}/pi
%{_bindir}/puppet
%{_bindir}/ralsh
@@ -172,6 +172,34 @@ echo "D /var/run/%{name} 0755 %{name} %{name} -" > \
%{_mandir}/man8/puppetd.8.gz
%{_mandir}/man8/ralsh.8.gz
%{_mandir}/man8/puppetdoc.8.gz
+%{_mandir}/man8/puppet-agent.8.gz
+%{_mandir}/man8/puppet-apply.8.gz
+%{_mandir}/man8/puppet-catalog.8.gz
+%{_mandir}/man8/puppet-describe.8.gz
+%{_mandir}/man8/puppet-cert.8.gz
+%{_mandir}/man8/puppet-certificate.8.gz
+%{_mandir}/man8/puppet-certificate_request.8.gz
+%{_mandir}/man8/puppet-certificate_revocation_list.8.gz
+%{_mandir}/man8/puppet-config.8.gz
+%{_mandir}/man8/puppet-device.8.gz
+%{_mandir}/man8/puppet-doc.8.gz
+%{_mandir}/man8/puppet-facts.8.gz
+%{_mandir}/man8/puppet-file.8.gz
+%{_mandir}/man8/puppet-filebucket.8.gz
+%{_mandir}/man8/puppet-help.8.gz
+%{_mandir}/man8/puppet-inspect.8.gz
+%{_mandir}/man8/puppet-key.8.gz
+%{_mandir}/man8/puppet-kick.8.gz
+%{_mandir}/man8/puppet-man.8.gz
+%{_mandir}/man8/puppet-node.8.gz
+%{_mandir}/man8/puppet-parser.8.gz
+%{_mandir}/man8/puppet-plugin.8.gz
+%{_mandir}/man8/puppet-queue.8.gz
+%{_mandir}/man8/puppet-report.8.gz
+%{_mandir}/man8/puppet-resource.8.gz
+%{_mandir}/man8/puppet-resource_type.8.gz
+%{_mandir}/man8/puppet-secret_agent.8.gz
+%{_mandir}/man8/puppet-status.8.gz
%files server
%defattr(-, root, root, 0755)
@@ -187,6 +215,7 @@ echo "D /var/run/%{name} 0755 %{name} %{name} -" > \
%{_mandir}/man8/puppetmasterd.8.gz
%{_mandir}/man8/puppetrun.8.gz
%{_mandir}/man8/puppetqd.8.gz
+%{_mandir}/man8/puppet-master.8.gz
# Fixed uid/gid were assigned in bz 472073 (Fedora), 471918 (RHEL-5),
# and 471919 (RHEL-4)
@@ -253,7 +282,11 @@ fi
rm -rf %{buildroot}
%changelog
-* Wed Jul 06 2011 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.2-0.1rc1
+* Wed Jul 06 2011 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.2-0.2.rc1
+- Clean up rpmlint errors
+- Put man pages in correct package
+
+* Wed Jul 06 2011 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.2-0.1.rc1
- Update to 2.7.2rc1
* Tue Jun 21 2011 Michael Stahnke <stahnma@puppetlabs.com> - 2.6.9-1
@@ -326,7 +359,7 @@ rm -rf %{buildroot}
- Update to 0.25.0
- Fix permissions on /var/log/puppet (#495096)
- Install emacs mode and vim syntax files (#491437)
-- Install ext/ directory in %%{_datadir}/%{name} (/usr/share/puppet)
+- Install ext/ directory in %%{_datadir}/%%{name} (/usr/share/puppet)
* Mon May 04 2009 Todd Zullinger <tmz@pobox.com> - 0.25.0-0.1.beta1
- Update to 0.25.0beta1
diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb
index eacb830b2..de5b2c499 100644
--- a/lib/puppet/application/certificate.rb
+++ b/lib/puppet/application/certificate.rb
@@ -2,11 +2,6 @@ require 'puppet/application/indirection_base'
class Puppet::Application::Certificate < Puppet::Application::IndirectionBase
def setup
- unless options[:ca_location]
- raise ArgumentError, "You must have a CA location specified;\n" +
- "use --ca-location to specify the location (remote, local, only)"
- end
-
location = Puppet::SSL::Host.ca_location
if location == :local && !Puppet::SSL::CertificateAuthority.ca?
self.class.run_mode("master")
diff --git a/lib/puppet/application/face_base.rb b/lib/puppet/application/face_base.rb
index ea5ba4aaf..a111518f1 100644
--- a/lib/puppet/application/face_base.rb
+++ b/lib/puppet/application/face_base.rb
@@ -100,7 +100,8 @@ class Puppet::Application::FaceBase < Puppet::Application
# action object it represents; if this is an invalid action name that
# will be nil, and handled later.
action_name = item.to_sym
- @action = @face.get_action(action_name)
+ @action = Puppet::Face.find_action(@face.name, action_name)
+ @face = @action.face if @action
end
end
diff --git a/lib/puppet/application/inspect.rb b/lib/puppet/application/inspect.rb
index 30865cfc1..b5a4ac872 100644
--- a/lib/puppet/application/inspect.rb
+++ b/lib/puppet/application/inspect.rb
@@ -1,6 +1,4 @@
-require 'puppet'
require 'puppet/application'
-require 'puppet/file_bucket/dipper'
class Puppet::Application::Inspect < Puppet::Application
@@ -98,6 +96,11 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
Puppet::Resource::Catalog.indirection.terminus_class = :yaml
end
+ def preinit
+ require 'puppet'
+ require 'puppet/file_bucket/dipper'
+ end
+
def run_command
benchmark(:notice, "Finished inspection") do
retrieval_starttime = Time.now
diff --git a/lib/puppet/face/certificate.rb b/lib/puppet/face/certificate.rb
index 9a306da37..8019b6bea 100644
--- a/lib/puppet/face/certificate.rb
+++ b/lib/puppet/face/certificate.rb
@@ -6,7 +6,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
license "Apache 2 license; see COPYING"
summary "Provide access to the CA for certificate management."
- description <<-'EOT'
+ description <<-EOT
This subcommand interacts with a local or remote Puppet certificate
authority. Currently, its behavior is not a full superset of `puppet
cert`; specifically, it is unable to mimic puppet cert's "clean" option,
@@ -15,8 +15,9 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
EOT
option "--ca-location LOCATION" do
+ required
summary "Which certificate authority to use (local or remote)."
- description <<-'EOT'
+ description <<-EOT
Whether to act on the local certificate authority or one provided by a
remote puppet master. Allowed values are 'local' and 'remote.'
@@ -24,6 +25,9 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
EOT
before_action do |action, args, options|
+ unless [:remote, :local, :only].include? options[:ca_location].to_sym
+ raise ArgumentError, "Valid values for ca-location are 'remote', 'local', 'only'."
+ end
Puppet::SSL::Host.ca_location = options[:ca_location].to_sym
end
end
@@ -32,7 +36,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
summary "Generate a new certificate signing request."
arguments "<host>"
returns "Nothing."
- description <<-'EOT'
+ description <<-EOT
Generates and submits a certificate signing request (CSR) for the
specified host. This CSR will then have to be signed by a user
with the proper authorization on the certificate authority.
@@ -41,7 +45,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
primarily useful for requesting certificates for individual users and
external applications.
EOT
- examples <<-'EOT'
+ examples <<-EOT
Request a certificate for "somenode" from the site's CA:
$ puppet certificate generate somenode.puppetlabs.lan --ca-location remote
@@ -56,7 +60,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
action :list do
summary "List all certificate signing requests."
- returns <<-'EOT'
+ returns <<-EOT
An array of #inspect output from CSR objects. This output is
currently messy, but does contain the names of nodes requesting
certificates. This action returns #inspect strings even when used
@@ -73,10 +77,10 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
action :sign do
summary "Sign a certificate signing request for HOST."
arguments "<host>"
- returns <<-'EOT'
+ returns <<-EOT
A string that appears to be (but isn't) an x509 certificate.
EOT
- examples <<-'EOT'
+ examples <<-EOT
Sign somenode.puppetlabs.lan's certificate:
$ puppet certificate sign somenode.puppetlabs.lan --ca-location remote
@@ -93,9 +97,9 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
find = get_action(:find)
find.summary "Retrieve a certificate."
find.arguments "<host>"
- find.returns <<-'EOT'
- An x509 SSL certificate. You will usually want to render this as a
- string (--render-as s).
+ find.render_as = :s
+ find.returns <<-EOT
+ An x509 SSL certificate.
Note that this action has a side effect of caching a copy of the
certificate in Puppet's `ssldir`.
@@ -105,7 +109,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do
destroy.summary "Delete a certificate."
destroy.arguments "<host>"
destroy.returns "Nothing."
- destroy.description <<-'EOT'
+ destroy.description <<-EOT
Deletes a certificate. This action currently only works on the local CA.
EOT
diff --git a/lib/puppet/face/certificate_request.rb b/lib/puppet/face/certificate_request.rb
index 774821f12..cf342d51a 100644
--- a/lib/puppet/face/certificate_request.rb
+++ b/lib/puppet/face/certificate_request.rb
@@ -5,7 +5,7 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do
license "Apache 2 license; see COPYING"
summary "Manage certificate requests."
- description <<-'EOT'
+ description <<-EOT
This subcommand retrieves and submits certificate signing requests (CSRs).
EOT
@@ -15,14 +15,12 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do
find = get_action(:find)
find.summary "Retrieve a single CSR."
find.arguments "<host>"
- find.returns <<-'EOT'
+ find.render_as = :s
+ find.returns <<-EOT
A single certificate request. When used from the Ruby API, returns a
Puppet::SSL::CertificateRequest object.
-
- RENDERING ISSUES: In most cases, you will want to render this as a string
- ('--render-as s').
EOT
- find.examples <<-'EOT'
+ find.examples <<-EOT
Retrieve a single CSR from the puppet master's CA:
$ puppet certificate_request find somenode.puppetlabs.lan --terminus rest
@@ -31,10 +29,10 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do
search = get_action(:search)
search.summary "Retrieve all outstanding CSRs."
search.arguments "<dummy_text>"
- search.returns <<-'EOT'
- A list of certificate requests; be sure to to render this as a string
- ('--render-as s'). When used from the Ruby API, returns an array of
- Puppet::SSL::CertificateRequest objects.
+ search.render_as = :s
+ search.returns <<-EOT
+ A list of certificate requests. When used from the Ruby API, returns an
+ array of Puppet::SSL::CertificateRequest objects.
EOT
search.short_description <<-EOT
Retrieves all outstanding certificate signing requests. Due to a known bug,
@@ -44,7 +42,7 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do
Although this action always returns all CSRs, it requires a dummy search
key; this is a known bug.
EOT
- search.examples <<-'EOT'
+ search.examples <<-EOT
Retrieve all CSRs from the local CA (similar to 'puppet cert list'):
$ puppet certificate_request search x --terminus ca
diff --git a/lib/puppet/face/certificate_revocation_list.rb b/lib/puppet/face/certificate_revocation_list.rb
index f58368f75..022323b29 100644
--- a/lib/puppet/face/certificate_revocation_list.rb
+++ b/lib/puppet/face/certificate_revocation_list.rb
@@ -5,7 +5,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do
license "Apache 2 license; see COPYING"
summary "Manage the list of revoked certificates."
- description <<-'EOT'
+ description <<-EOT
This subcommand is primarily for retrieving the certificate revocation
list from the CA.
EOT
@@ -13,12 +13,10 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do
find = get_action(:find)
find.summary "Retrieve the certificate revocation list."
find.arguments "<dummy_text>"
- find.returns <<-'EOT'
+ find.render_as = :s
+ find.returns <<-EOT
The certificate revocation list. When used from the Ruby API: returns an
OpenSSL::X509::CRL object.
-
- RENDERING ISSUES: this should usually be rendered as a string
- ('--render-as s').
EOT
find.short_description <<-EOT
Retrieves the certificate revocation list. Due to a known bug, this action
@@ -28,7 +26,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do
Although this action always returns the CRL from the specified terminus, it
requires a dummy argument; this is a known bug.
EOT
- find.examples <<-'EXAMPLES'
+ find.examples <<-EXAMPLES
Retrieve a copy of the puppet master's CRL:
$ puppet certificate_revocation_list find crl --terminus rest
@@ -38,7 +36,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do
destroy.summary "Delete the certificate revocation list."
destroy.arguments "<dummy_text>"
destroy.returns "Nothing."
- destroy.description <<-'EOT'
+ destroy.description <<-EOT
Deletes the certificate revocation list. This cannot be done over REST, but
it is possible to delete the locally cached copy or the local CA's copy of
the CRL.
diff --git a/lib/puppet/indirector/face.rb b/lib/puppet/indirector/face.rb
index ead3f4b46..adb6b688b 100644
--- a/lib/puppet/indirector/face.rb
+++ b/lib/puppet/indirector/face.rb
@@ -48,16 +48,26 @@ class Puppet::Indirector::Face < Puppet::Face
return result
end
+ option "--extra HASH" do
+ summary "Extra arguments to pass to the indirection request"
+ description <<-end
+ A terminus can take additional arguments to refine the operation, which
+ are passed as an arbitrary hash to the back-end. Anything passed as
+ the extra value is just send direct to the back-end.
+ end
+ default_to do Hash.new end
+ end
+
action :destroy do
summary "Delete an object."
arguments "<key>"
- when_invoked { |key, options| call_indirection_method(:destroy, key, options) }
+ when_invoked {|key, options| call_indirection_method :destroy, key, options[:extra] }
end
action :find do
summary "Retrieve an object by name."
arguments "<key>"
- when_invoked { |key, options| call_indirection_method(:find, key, options) }
+ when_invoked {|key, options| call_indirection_method :find, key, options[:extra] }
end
action :save do
@@ -68,13 +78,13 @@ class Puppet::Indirector::Face < Puppet::Face
currently accept data from STDIN, save actions cannot currently be invoked
from the command line.
EOT
- when_invoked { |key, options| call_indirection_method(:save, key, options) }
+ when_invoked {|key, options| call_indirection_method :save, key, options[:extra] }
end
action :search do
summary "Search for an object or retrieve multiple objects."
arguments "<query>"
- when_invoked { |key, options| call_indirection_method(:search, key, options) }
+ when_invoked {|key, options| call_indirection_method :search, key, options[:extra] }
end
# Print the configuration for the current terminus class
@@ -86,11 +96,11 @@ class Puppet::Indirector::Face < Puppet::Face
run mode with the '--mode' option.
EOT
- when_invoked do |*args|
+ when_invoked do |options|
if t = indirection.terminus_class
- puts "Run mode '#{Puppet.run_mode.name}': #{t}"
+ "Run mode '#{Puppet.run_mode.name}': #{t}"
else
- $stderr.puts "No default terminus class for run mode '#{Puppet.run_mode.name}'"
+ "No default terminus class for run mode '#{Puppet.run_mode.name}'"
end
end
end
diff --git a/lib/puppet/indirector/report/processor.rb b/lib/puppet/indirector/report/processor.rb
index 88fe4b487..81b379eb8 100644
--- a/lib/puppet/indirector/report/processor.rb
+++ b/lib/puppet/indirector/report/processor.rb
@@ -20,9 +20,11 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
# LAK:NOTE This isn't necessarily the best design, but it's backward
# compatible and that's good enough for now.
def process(report)
+ Puppet.debug "Recieved report to process from #{report.host}"
return if Puppet[:reports] == "none"
reports.each do |name|
+ Puppet.debug "Processing report from #{report.host} with processor #{name}"
if mod = Puppet::Reports.report(name)
# We have to use a dup because we're including a module in the
# report.
diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb
index 6c288f3c0..eba99d6be 100644
--- a/lib/puppet/interface.rb
+++ b/lib/puppet/interface.rb
@@ -64,6 +64,10 @@ class Puppet::Interface
end
face
end
+
+ def find_action(name, action, version = :current)
+ Puppet::Interface::FaceCollection.get_action_for_face(name, action, version)
+ end
end
def set_default_format(format)
diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb
index fc1121eb6..bd47a36ea 100644
--- a/lib/puppet/interface/action.rb
+++ b/lib/puppet/interface/action.rb
@@ -38,6 +38,7 @@ class Puppet::Interface::Action
def to_s() "#{@face}##{@name}" end
attr_reader :name
+ attr_reader :face
attr_accessor :default
def default?
!!@default
@@ -195,15 +196,12 @@ class Puppet::Interface::Action
wrapper = <<WRAPPER
def #{@name}(#{decl.join(", ")})
#{optn}
- args = #{args}
- options = args.last
-
- action = get_action(#{name.inspect})
- action.add_default_args(args)
- action.validate_args(args)
- __invoke_decorations(:before, action, args, options)
+ args = #{args}
+ action = get_action(#{name.inspect})
+ args << action.validate_and_clean(args.pop)
+ __invoke_decorations(:before, action, args, args.last)
rval = self.__send__(#{internal_name.inspect}, *args)
- __invoke_decorations(:after, action, args, options)
+ __invoke_decorations(:after, action, args, args.last)
return rval
end
WRAPPER
@@ -253,35 +251,59 @@ WRAPPER
option
end
- def add_default_args(args)
- options.map {|x| get_option(x) }.each do |option|
- if option.has_default? and not option.aliases.any? {|x| args.last.has_key? x}
- args.last[option.name] = option.default
+ def validate_and_clean(original)
+ # The final set of arguments; effectively a hand-rolled shallow copy of
+ # the original, which protects the caller from the surprises they might
+ # get if they passed us a hash and we mutated it...
+ result = {}
+
+ # Check for multiple aliases for the same option, and canonicalize the
+ # name of the argument while we are about it.
+ overlap = Hash.new do |h, k| h[k] = [] end
+ unknown = []
+ original.keys.each do |name|
+ if option = get_option(name) then
+ canonical = option.name
+ if result.has_key? canonical
+ overlap[canonical] << name
+ else
+ result[canonical] = original[name]
+ end
+ else
+ unknown << name
end
end
- end
- def validate_args(args)
- # Check for multiple aliases for the same option...
- args.last.keys.each do |name|
- # #7290: If this isn't actually an option, ignore it for now. We should
- # probably fail, but that wasn't our API, and I don't want to perturb
- # behaviour this late in the RC cycle. --daniel 2011-04-29
- if option = get_option(name) then
- overlap = (option.aliases & args.last.keys)
- unless overlap.length == 1 then
- raise ArgumentError, "Multiple aliases for the same option passed: #{overlap.join(', ')}"
- end
+ unless overlap.empty?
+ msg = overlap.map {|k, v| "(#{k}, #{v.sort.join(', ')})" }.join(", ")
+ raise ArgumentError, "Multiple aliases for the same option passed: #{msg}"
+ end
+
+ unless unknown.empty?
+ msg = unknown.sort.join(", ")
+ raise ArgumentError, "Unknown options passed: #{msg}"
+ end
+
+ # Inject default arguments and check for missing mandating options.
+ missing = []
+ options.map {|x| get_option(x) }.each do |option|
+ name = option.name
+ next if result.has_key? name
+
+ if option.has_default?
+ result[name] = option.default
+ elsif option.required?
+ missing << name
end
end
- # Check for missing mandatory options.
- required = options.map do |name|
- get_option(name)
- end.select(&:required?).collect(&:name) - args.last.keys
+ unless missing.empty?
+ msg = missing.sort.join(', ')
+ raise ArgumentError, "The following options are required: #{msg}"
+ end
- return if required.empty?
- raise ArgumentError, "The following options are required: #{required.join(', ')}"
+ # All done.
+ return result
end
########################################################################
diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb
index 4522824fd..b1f6ba398 100644
--- a/lib/puppet/interface/face_collection.rb
+++ b/lib/puppet/interface/face_collection.rb
@@ -20,6 +20,24 @@ module Puppet::Interface::FaceCollection
get_face(name, version) or load_face(name, version)
end
+ def self.get_action_for_face(name, action_name, version)
+ name = underscorize(name)
+
+ # If the version they request specifically doesn't exist, don't search
+ # elsewhere. Usually this will start from :current and all...
+ return nil unless face = self[name, version]
+ unless action = face.get_action(action_name)
+ # ...we need to search for it bound to an o{lder,ther} version. Since
+ # we load all actions when the face is first references, this will be in
+ # memory in the known set of versions of the face.
+ (@faces[name].keys - [ :current ]).sort.reverse.each do |version|
+ break if action = @faces[name][version].get_action(action_name)
+ end
+ end
+
+ return action
+ end
+
# get face from memory, without loading.
def self.get_face(name, pattern)
return nil unless @faces.has_key? name
@@ -38,9 +56,7 @@ module Puppet::Interface::FaceCollection
#
# We use require to avoid executing the code multiple times, like any
# other Ruby library that we might want to use. --daniel 2011-04-06
- begin
- require "puppet/face/#{name}"
-
+ if safely_require name then
# If we wanted :current, we need to index to find that; direct version
# requests just work™ as they go. --daniel 2011-04-06
if version == :current then
@@ -72,18 +88,32 @@ module Puppet::Interface::FaceCollection
latest_ver = @faces[name].keys.sort.last
@faces[name][:current] = @faces[name][latest_ver]
end
- rescue LoadError => e
- raise unless e.message =~ %r{-- puppet/face/#{name}$}
- # ...guess we didn't find the file; return a much better problem.
- rescue SyntaxError => e
- raise unless e.message =~ %r{puppet/face/#{name}\.rb:\d+: }
- Puppet.err "Failed to load face #{name}:\n#{e}"
- # ...but we just carry on after complaining.
+ end
+
+ unless version == :current or get_face(name, version)
+ # Try an obsolete version of the face, if needed, to see if that helps?
+ safely_require name, version
end
return get_face(name, version)
end
+ def self.safely_require(name, version = nil)
+ path = File.join 'puppet' ,'face', version.to_s, name.to_s
+ require path
+ true
+
+ rescue LoadError => e
+ raise unless e.message =~ %r{-- #{path}$}
+ # ...guess we didn't find the file; return a much better problem.
+ nil
+ rescue SyntaxError => e
+ raise unless e.message =~ %r{#{path}\.rb:\d+: }
+ Puppet.err "Failed to load face #{name}:\n#{e}"
+ # ...but we just carry on after complaining.
+ nil
+ end
+
def self.register(face)
@faces[underscorize(face.name)][face.version] = face
end
diff --git a/lib/puppet/resource/catalog.rb b/lib/puppet/resource/catalog.rb
index bb19f3ebc..ca9f25a5a 100644
--- a/lib/puppet/resource/catalog.rb
+++ b/lib/puppet/resource/catalog.rb
@@ -92,7 +92,7 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
resource.ref =~ /^(.+)\[/
class_name = $1 || resource.class.name
- newref = [class_name, key]
+ newref = [class_name, key].flatten
if key.is_a? String
ref_string = "#{class_name}[#{key}]"
@@ -105,7 +105,10 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
# isn't sufficient.
if existing = @resource_table[newref]
return if existing == resource
- raise(ArgumentError, "Cannot alias #{resource.ref} to #{key.inspect}; resource #{newref.inspect} already exists")
+ resource_definition = " at #{resource.file}:#{resource.line}" if resource.file and resource.line
+ existing_definition = " at #{existing.file}:#{existing.line}" if existing.file and existing.line
+ msg = "Cannot alias #{resource.ref} to #{key.inspect}#{resource_definition}; resource #{newref.inspect} already defined#{existing_definition}"
+ raise ArgumentError, msg
end
@resource_table[newref] = resource
@aliases[resource.ref] ||= []
@@ -421,7 +424,7 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
res = Puppet::Resource.new(nil, type)
end
title_key = [res.type, res.title.to_s]
- uniqueness_key = [res.type, res.uniqueness_key]
+ uniqueness_key = [res.type, res.uniqueness_key].flatten
@resource_table[title_key] || @resource_table[uniqueness_key]
end
diff --git a/lib/puppet/type/file/source.rb b/lib/puppet/type/file/source.rb
index 222b85dbb..39f85e2ad 100755
--- a/lib/puppet/type/file/source.rb
+++ b/lib/puppet/type/file/source.rb
@@ -146,7 +146,6 @@ module Puppet
def metadata
return @metadata if @metadata
return nil unless value
- result = nil
value.each do |source|
begin
if data = Puppet::FileServing::Metadata.indirection.find(source)
@@ -158,7 +157,7 @@ module Puppet
fail detail, "Could not retrieve file metadata for #{source}: #{detail}"
end
end
- fail "Could not retrieve information from source(s) #{value.join(", ")}" unless @metadata
+ fail "Could not retrieve information from environment #{Puppet[:environment]} source(s) #{value.join(", ")}" unless @metadata
@metadata
end
diff --git a/lib/puppet/type/service.rb b/lib/puppet/type/service.rb
index 53ff72867..eaf2b8ee1 100644
--- a/lib/puppet/type/service.rb
+++ b/lib/puppet/type/service.rb
@@ -8,17 +8,15 @@ module Puppet
newtype(:service) do
@doc = "Manage running services. Service support unfortunately varies
- widely by platform --- some platforms have very little if any
- concept of a running service, and some have a very codified and
- powerful concept. Puppet's service support will generally be able
- to do the right thing regardless (e.g., if there is no
- 'status' command, then Puppet will look in the process table for a
- command matching the service name), but the more information you
- can provide, the better behaviour you will get. In particular, any
- virtual services that don't have a predictable entry in the process table
- (for example, `network` on Red Hat/CentOS systems) will manifest odd
- behavior on restarts if you don't specify `hasstatus` or a `status`
- command.
+ widely by platform --- some platforms have very little if any concept of a
+ running service, and some have a very codified and powerful concept.
+ Puppet's service support is usually capable of doing the right thing, but
+ the more information you can provide, the better behaviour you will get.
+
+ Puppet 2.7 and newer expect init scripts to have a working status command.
+ If this isn't the case for any of your services' init scripts, you will
+ need to set `hasstatus` to false and possibly specify a custom status
+ command in the `status` attribute.
Note that if a `service` receives an event from another resource,
the service will get restarted. The actual command to restart the
@@ -103,19 +101,17 @@ module Puppet
end
newparam(:hasstatus) do
- desc "Declare the the service's init script has a
- functional status command. Based on testing, it was found
- that a large number of init scripts on different platforms do
- not support any kind of status command; thus, you must specify
- manually whether the service you are running has such a
- command. Alternately, you can provide a specific command using the
- `status` attribute.
-
- If you specify neither of these, then Puppet will look for the
- service name in the process table. Be aware that 'virtual' init
- scripts such as networking will respond poorly to refresh events
- (via notify and subscribe relationships) if you don't override
- this default behavior."
+ desc "Declare whether the service's init script has a functional status
+ command; defaults to `true`. This attribute's default value changed in
+ Puppet 2.7.0.
+
+ If a service's init script does not support any kind of status command,
+ you should set `hasstatus` to false and either provide a specific
+ command using the `status` attribute or expect that Puppet will look for
+ the service name in the process table. Be aware that 'virtual' init
+ scripts (like 'network' under Red Hat systems) will respond poorly to
+ refresh events from other resources if you override the default behavior
+ without providing a status command."
newvalues(:true, :false)
diff --git a/spec/lib/puppet/face/1.0.0/huzzah.rb b/spec/lib/puppet/face/1.0.0/huzzah.rb
new file mode 100755
index 000000000..8a1311704
--- /dev/null
+++ b/spec/lib/puppet/face/1.0.0/huzzah.rb
@@ -0,0 +1,8 @@
+require 'puppet/face'
+Puppet::Face.define(:huzzah, '1.0.0') do
+ copyright "Puppet Labs", 2011
+ license "Apache 2 license; see COPYING"
+ summary "life is a thing for celebration"
+ script :obsolete_in_core do |_| "you are in obsolete core now!" end
+ script :call_newer do |_| method_on_newer end
+end
diff --git a/spec/lib/puppet/face/huzzah.rb b/spec/lib/puppet/face/huzzah.rb
index ab465d9e0..f3d18a797 100755
--- a/spec/lib/puppet/face/huzzah.rb
+++ b/spec/lib/puppet/face/huzzah.rb
@@ -4,4 +4,5 @@ Puppet::Face.define(:huzzah, '2.0.1') do
license "Apache 2 license; see COPYING"
summary "life is a thing for celebration"
script :bar do |options| "is where beer comes from" end
+ script :call_older do |_| method_on_older end
end
diff --git a/spec/lib/puppet/face/huzzah/obsolete.rb b/spec/lib/puppet/face/huzzah/obsolete.rb
new file mode 100644
index 000000000..1f717ea2f
--- /dev/null
+++ b/spec/lib/puppet/face/huzzah/obsolete.rb
@@ -0,0 +1,6 @@
+Puppet::Face.define(:huzzah, '1.0.0') do
+ action :obsolete do
+ summary "This is an action on version 1.0.0 of the face"
+ when_invoked do |options| options end
+ end
+end
diff --git a/spec/unit/application/face_base_spec.rb b/spec/unit/application/face_base_spec.rb
index 0a4a86be6..bebc26210 100755
--- a/spec/unit/application/face_base_spec.rb
+++ b/spec/unit/application/face_base_spec.rb
@@ -55,6 +55,7 @@ describe Puppet::Application::FaceBase do
it "should stop if the first thing found is not an action" do
app.command_line.stubs(:args).returns %w{banana count_args}
expect { app.run }.to exit_with 1
+ @logs.first.should_not be_nil
@logs.first.message.should =~ /has no 'banana' action/
end
diff --git a/spec/unit/application/inspect_spec.rb b/spec/unit/application/inspect_spec.rb
index 9f12c83ad..be5887f01 100755
--- a/spec/unit/application/inspect_spec.rb
+++ b/spec/unit/application/inspect_spec.rb
@@ -12,6 +12,11 @@ describe Puppet::Application::Inspect do
before :each do
@inspect = Puppet::Application[:inspect]
+ @inspect.preinit
+ end
+
+ it "should operate in agent run_mode" do
+ @inspect.class.run_mode.name.should == :agent
end
describe "during setup" do
diff --git a/spec/unit/face/certificate_spec.rb b/spec/unit/face/certificate_spec.rb
index 0cb905b75..9291d7523 100755
--- a/spec/unit/face/certificate_spec.rb
+++ b/spec/unit/face/certificate_spec.rb
@@ -10,14 +10,26 @@ describe Puppet::Face[:certificate, '0.0.1'] do
end
it "should set the ca location when invoked" do
- Puppet::SSL::Host.expects(:ca_location=).with(:foo)
+ Puppet::SSL::Host.expects(:ca_location=).with(:local)
Puppet::SSL::Host.indirection.expects(:save)
- subject.sign "hello, friend", :ca_location => :foo
+ subject.sign "hello, friend", :ca_location => :local
end
it "(#7059) should set the ca location when an inherited action is invoked" do
- Puppet::SSL::Host.expects(:ca_location=).with(:foo)
+ Puppet::SSL::Host.expects(:ca_location=).with(:local)
subject.indirection.expects(:find)
- subject.find "hello, friend", :ca_location => :foo
+ subject.find "hello, friend", :ca_location => :local
+ end
+
+ it "should validate the option as required" do
+ expect do
+ subject.find 'hello, friend'
+ end.to raise_exception ArgumentError, /required/i
+ end
+
+ it "should validate the option as a supported value" do
+ expect do
+ subject.find 'hello, friend', :ca_location => :foo
+ end.to raise_exception ArgumentError, /valid values/i
end
end
diff --git a/spec/unit/indirector/face_spec.rb b/spec/unit/indirector/face_spec.rb
index 943ff7991..8e324f019 100755
--- a/spec/unit/indirector/face_spec.rb
+++ b/spec/unit/indirector/face_spec.rb
@@ -12,6 +12,8 @@ describe Puppet::Indirector::Face do
instance
end
+ it { should be_option :extra }
+
it "should be able to return a list of indirections" do
Puppet::Indirector::Face.indirections.should be_include("catalog")
end
@@ -48,7 +50,7 @@ describe Puppet::Indirector::Face do
end
it "should forward passed options" do
subject.indirection.expects(method).with(:test, {'one'=>'1'})
- subject.send(method, :test, {'one'=>'1'})
+ subject.send(method, :test, :extra => {'one'=>'1'})
end
end
diff --git a/spec/unit/indirector/report/processor_spec.rb b/spec/unit/indirector/report/processor_spec.rb
index bafbe6ee7..fbc70a104 100755
--- a/spec/unit/indirector/report/processor_spec.rb
+++ b/spec/unit/indirector/report/processor_spec.rb
@@ -25,9 +25,11 @@ describe Puppet::Transaction::Report::Processor, " when saving a report" do
it "should not process the report if reports are set to 'none'" do
Puppet::Reports.expects(:report).never
- Puppet.settings.expects(:value).with(:reports).returns("none")
+ Puppet[:reports] = 'none'
- request = stub 'request', :instance => mock("report")
+ request = Puppet::Indirector::Request.new(:indirection_name, :head, "key")
+ report = Puppet::Transaction::Report.new('apply')
+ request.instance = report
@reporter.save(request)
end
@@ -40,14 +42,14 @@ end
describe Puppet::Transaction::Report::Processor, " when processing a report" do
before do
- Puppet.settings.stubs(:value).with(:reports).returns("one")
+ Puppet[:reports] = "one"
Puppet.settings.stubs(:use)
@reporter = Puppet::Transaction::Report::Processor.new
@report_type = mock 'one'
@dup_report = mock 'dupe report'
@dup_report.stubs(:process)
- @report = mock 'report'
+ @report = Puppet::Transaction::Report.new('apply')
@report.expects(:dup).returns(@dup_report)
@request = stub 'request', :instance => @report
@@ -74,7 +76,7 @@ describe Puppet::Transaction::Report::Processor, " when processing a report" do
end
it "should not raise exceptions" do
- Puppet.settings.stubs(:value).with(:trace).returns(false)
+ Puppet[:trace] = false
@dup_report.expects(:process).raises(ArgumentError)
proc { @reporter.save(@request) }.should_not raise_error
end
diff --git a/spec/unit/interface/action_spec.rb b/spec/unit/interface/action_spec.rb
index d71a7d000..c3f08e817 100755
--- a/spec/unit/interface/action_spec.rb
+++ b/spec/unit/interface/action_spec.rb
@@ -121,6 +121,7 @@ describe Puppet::Interface::Action do
let :face do
Puppet::Interface.new(:ruby_api, '1.0.0') do
action :bar do
+ option "--bar"
when_invoked do |*args|
args.last
end
@@ -138,8 +139,8 @@ describe Puppet::Interface::Action do
options.should == { :bar => "beer" }
end
- it "should call #validate_args on the action when invoked" do
- face.get_action(:bar).expects(:validate_args).with([1, :two, 'three', {}])
+ it "should call #validate_and_clean on the action when invoked" do
+ face.get_action(:bar).expects(:validate_and_clean).with({}).returns({})
face.bar 1, :two, 'three'
end
end
@@ -171,14 +172,28 @@ describe Puppet::Interface::Action do
face.get_action(:foo).options.should =~ [:bar]
end
- it "should only list options and not aliases" do
- face = Puppet::Interface.new(:action_level_options, '0.0.1') do
- action :foo do
- when_invoked do |options| true end
- option "--bar", "-b", "--foo-bar"
+ describe "option aliases" do
+ let :option do action.get_option :bar end
+ let :action do face.get_action :foo end
+ let :face do
+ Puppet::Interface.new(:action_level_options, '0.0.1') do
+ action :foo do
+ when_invoked do |options| options end
+ option "--bar", "--foo", "-b"
+ end
+ end
+ end
+
+ it "should only list options and not aliases" do
+ action.options.should =~ [:bar]
+ end
+
+ it "should use the canonical option name when passed aliases" do
+ name = option.name
+ option.aliases.each do |input|
+ face.foo(input => 1).should == { name => 1 }
end
end
- face.get_action(:foo).options.should =~ [:bar]
end
describe "with both face and action options" do
@@ -436,12 +451,12 @@ describe Puppet::Interface::Action do
end
it "should be invoked when calling a child action" do
- subject.on_child(:foo => true, :bar => true).should == :on_child
+ subject.on_child(:foo => true).should == :on_child
subject.reported.should == [ :child_before ]
end
it "should be invoked when calling a parent action" do
- subject.on_parent(:foo => true, :bar => true).should == :on_parent
+ subject.on_parent(:foo => true).should == :on_parent
subject.reported.should == [ :child_before ]
end
end
@@ -453,12 +468,12 @@ describe Puppet::Interface::Action do
end
it "should be invoked when calling a child action" do
- subject.on_child(:foo => true, :bar => true).should == :on_child
+ subject.on_child(:foo => true).should == :on_child
subject.reported.should == [ :parent_before ]
end
it "should be invoked when calling a parent action" do
- subject.on_parent(:foo => true, :bar => true).should == :on_parent
+ subject.on_parent(:foo => true).should == :on_parent
subject.reported.should == [ :parent_before ]
end
end
@@ -534,7 +549,7 @@ describe Puppet::Interface::Action do
it "should return the block if asked"
end
- context "#validate_args" do
+ context "#validate_and_clean" do
subject do
Puppet::Interface.new(:validate_args, '1.0.0') do
script :test do |options| true end
@@ -551,6 +566,16 @@ describe Puppet::Interface::Action do
expect { subject.test :foo => true, :f => true }.
to raise_error ArgumentError, /Multiple aliases for the same option/
end
+
+ it "should fail if an unknown option is passed" do
+ expect { subject.test :unknown => true }.
+ to raise_error ArgumentError, /Unknown options passed: unknown/
+ end
+
+ it "should report all the unknown options passed" do
+ expect { subject.test :unknown => true, :unseen => false }.
+ to raise_error ArgumentError, /Unknown options passed: unknown, unseen/
+ end
end
context "default option values" do
diff --git a/spec/unit/interface/face_collection_spec.rb b/spec/unit/interface/face_collection_spec.rb
index 98887a778..514a624b1 100755
--- a/spec/unit/interface/face_collection_spec.rb
+++ b/spec/unit/interface/face_collection_spec.rb
@@ -35,7 +35,8 @@ describe Puppet::Interface::FaceCollection do
end
it "should attempt to load the face if it isn't found" do
- subject.expects(:require).with('puppet/face/bar')
+ subject.expects(:require).once.with('puppet/face/bar')
+ subject.expects(:require).once.with('puppet/face/0.0.1/bar')
subject["bar", '0.0.1']
end
@@ -64,7 +65,8 @@ describe Puppet::Interface::FaceCollection do
it "should return false if the face file itself is missing" do
subject.stubs(:require).
- raises(LoadError, 'no such file to load -- puppet/face/bar')
+ raises(LoadError, 'no such file to load -- puppet/face/bar').then.
+ raises(LoadError, 'no such file to load -- puppet/face/0.0.1/bar')
subject["bar", '0.0.1'].should be_false
end
@@ -97,6 +99,42 @@ describe Puppet::Interface::FaceCollection do
end
end
+ describe "::get_action_for_face" do
+ it "should return an action on the current face" do
+ Puppet::Face::FaceCollection.get_action_for_face(:huzzah, :bar, :current).
+ should be_an_instance_of Puppet::Interface::Action
+ end
+
+ it "should return an action on an older version of a face" do
+ action = Puppet::Face::FaceCollection.
+ get_action_for_face(:huzzah, :obsolete, :current)
+
+ action.should be_an_instance_of Puppet::Interface::Action
+ action.face.version.should == SemVer.new('1.0.0')
+ end
+
+ it "should load the full older version of a face" do
+ action = Puppet::Face::FaceCollection.
+ get_action_for_face(:huzzah, :obsolete, :current)
+
+ action.face.version.should == SemVer.new('1.0.0')
+ action.face.should be_action :obsolete_in_core
+ end
+
+ it "should not add obsolete actions to the current version" do
+ action = Puppet::Face::FaceCollection.
+ get_action_for_face(:huzzah, :obsolete, :current)
+
+ action.face.version.should == SemVer.new('1.0.0')
+ action.face.should be_action :obsolete_in_core
+
+ current = Puppet::Face[:huzzah, :current]
+ current.version.should == SemVer.new('2.0.1')
+ current.should_not be_action :obsolete_in_core
+ current.should_not be_action :obsolete
+ end
+ end
+
describe "::register" do
it "should store the face by name" do
face = Puppet::Face.new(:my_face, '0.0.1')
diff --git a/spec/unit/interface_spec.rb b/spec/unit/interface_spec.rb
index 4cb1f8743..4ff71ac3d 100755
--- a/spec/unit/interface_spec.rb
+++ b/spec/unit/interface_spec.rb
@@ -126,14 +126,11 @@ describe Puppet::Interface do
end
it "should try to require faces that are not known" do
- pending "mocking require causes random stack overflow"
- subject::FaceCollection.expects(:require).with "puppet/face/foo"
- subject[:foo, '0.0.1']
+ subject::FaceCollection.expects(:load_face).with(:foo, :current)
+ subject::FaceCollection.expects(:load_face).with(:foo, '0.0.1')
+ expect { subject[:foo, '0.0.1'] }.to raise_error Puppet::Error
end
- it "should be able to load all actions in all search paths"
-
-
it_should_behave_like "things that declare options" do
def add_options_to(&block)
subject.new(:with_options, '0.0.1', &block)
diff --git a/spec/unit/resource/catalog_spec.rb b/spec/unit/resource/catalog_spec.rb
index c03f05dee..ce783e393 100755
--- a/spec/unit/resource/catalog_spec.rb
+++ b/spec/unit/resource/catalog_spec.rb
@@ -484,7 +484,7 @@ describe Puppet::Resource::Catalog, "when compiling" do
lambda { @catalog.alias(@one, "other") }.should_not raise_error
end
- it "should create aliases for resources isomorphic resources whose names do not match their titles" do
+ it "should create aliases for isomorphic resources whose names do not match their titles" do
resource = Puppet::Type::File.new(:title => "testing", :path => @basepath+"/something")
@catalog.add_resource(resource)
@@ -492,7 +492,7 @@ describe Puppet::Resource::Catalog, "when compiling" do
@catalog.resource(:file, @basepath+"/something").should equal(resource)
end
- it "should not create aliases for resources non-isomorphic resources whose names do not match their titles", :fails_on_windows => true do
+ it "should not create aliases for non-isomorphic resources whose names do not match their titles", :fails_on_windows => true do
resource = Puppet::Type.type(:exec).new(:title => "testing", :command => "echo", :path => %w{/bin /usr/bin /usr/local/bin})
@catalog.add_resource(resource)
@@ -508,11 +508,6 @@ describe Puppet::Resource::Catalog, "when compiling" do
@catalog.resource("notify", "other").should equal(@one)
end
- it "should ignore conflicting aliases that point to the aliased resource" do
- @catalog.alias(@one, "other")
- lambda { @catalog.alias(@one, "other") }.should_not raise_error
- end
-
it "should fail to add an alias if the aliased name already exists" do
@catalog.add_resource @one
proc { @catalog.alias @two, "one" }.should raise_error(ArgumentError)
@@ -566,6 +561,58 @@ describe Puppet::Resource::Catalog, "when compiling" do
@catalog.create_resource :file, args
@catalog.resource("File[/yay]").should equal(resource)
end
+
+ describe "when adding resources with multiple namevars" do
+ before :each do
+ Puppet::Type.newtype(:multiple) do
+ newparam(:color, :namevar => true)
+ newparam(:designation, :namevar => true)
+
+ def self.title_patterns
+ [ [
+ /^(\w+) (\w+)$/,
+ [
+ [:color, lambda{|x| x}],
+ [:designation, lambda{|x| x}]
+ ]
+ ] ]
+ end
+ end
+ end
+
+ it "should add an alias using the uniqueness key" do
+ @resource = Puppet::Type.type(:multiple).new(:title => "some resource", :color => "red", :designation => "5")
+
+ @catalog.add_resource(@resource)
+ @catalog.resource(:multiple, "some resource").must == @resource
+ @catalog.resource("Multiple[some resource]").must == @resource
+ @catalog.resource("Multiple[red 5]").must == @resource
+ end
+
+ it "should conflict with a resource with the same uniqueness key" do
+ @resource = Puppet::Type.type(:multiple).new(:title => "some resource", :color => "red", :designation => "5")
+ @other = Puppet::Type.type(:multiple).new(:title => "another resource", :color => "red", :designation => "5")
+
+ @catalog.add_resource(@resource)
+ expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias Multiple\[another resource\] to \["red", "5"\].*resource \["Multiple", "red", "5"\] already defined/)
+ end
+
+ it "should conflict when its uniqueness key matches another resource's title" do
+ @resource = Puppet::Type.type(:file).new(:title => "/tmp/foo")
+ @other = Puppet::Type.type(:file).new(:title => "another file", :path => "/tmp/foo")
+
+ @catalog.add_resource(@resource)
+ expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias File\[another file\] to \["\/tmp\/foo"\].*resource \["File", "\/tmp\/foo"\] already defined/)
+ end
+
+ it "should conflict when its uniqueness key matches the uniqueness key derived from another resource's title" do
+ @resource = Puppet::Type.type(:multiple).new(:title => "red leader")
+ @other = Puppet::Type.type(:multiple).new(:title => "another resource", :color => "red", :designation => "leader")
+
+ @catalog.add_resource(@resource)
+ expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias Multiple\[another resource\] to \["red", "leader"\].*resource \["Multiple", "red", "leader"\] already defined/)
+ end
+ end
end
describe "when applying" do