From 111a4b546dd1bcaab182d5c8ad694404c2c2f91c Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Fri, 1 Apr 2011 15:23:14 +1100 Subject: (#6857) Password disclosure when changing a user's password Make the should_to_s and is_to_s functions to return a form of 'redacted'. Rather than send the password hash to system logs in cases of failure or running in --noop mode, just state whether it's the new or old hash. We're already doing this with password changes that work, so this just brings it inline with those, albeit via a slightly different pair of methods. --- lib/puppet/type/user.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb index f74e4266f..8d04fdc30 100755 --- a/lib/puppet/type/user.rb +++ b/lib/puppet/type/user.rb @@ -165,6 +165,14 @@ module Puppet return "changed password" end end + + def is_to_s( currentvalue ) + return '[old password hash redacted]' + end + def should_to_s( newvalue ) + return '[new password hash redacted]' + end + end newproperty(:password_min_age, :required_features => :manages_password_age) do -- cgit From f6882d6d5779883e931a6f558c06f631098011c5 Mon Sep 17 00:00:00 2001 From: nfagerlund Date: Wed, 29 Jun 2011 16:50:46 -0700 Subject: (#8147) Change default reporturl to match newer Dashboard versions Puppet's default reporturl setting was http://localhost:3000/reports, which has been deprecated in Puppet Dashboard in favor of http://localhost:3000/reports/upload. As Dashboard is the first-class destination for the http report processor, this commit changes Puppet's default to match what current versions of Dashboard expect. Reviewed-By: Jacob Helwig --- lib/puppet/defaults.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 07442d0e9..2247634b3 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -466,7 +466,7 @@ module Puppet :desc => "The directory in which to store reports received from the client. Each client gets a separate subdirectory."}, - :reporturl => ["http://localhost:3000/reports", + :reporturl => ["http://localhost:3000/reports/upload", "The URL used by the http reports processor to send reports"], :fileserverconfig => ["$confdir/fileserver.conf", "Where the fileserver configuration is stored."], :strict_hostname_checking => [false, "Whether to only search for the complete -- cgit From 5826f7399325c784a5e8e33c7fabc46e202334a8 Mon Sep 17 00:00:00 2001 From: Jeff McCune Date: Tue, 21 Jun 2011 18:54:35 -0700 Subject: (#8032) Add containment to create_resources Without this change native resource types declared using the create_resources() function are not contained within the class scope of the function call. As a result, resources were "floating off" in the graph, disconnected from the rest of the relationship edges. With this change, the scope is preserved and native resources are contained by the class the function call is executed from. Reviewed-by: Dan Bode --- lib/puppet/parser/functions/create_resources.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/parser/functions/create_resources.rb b/lib/puppet/parser/functions/create_resources.rb index 430f110b4..3b8bb3543 100644 --- a/lib/puppet/parser/functions/create_resources.rb +++ b/lib/puppet/parser/functions/create_resources.rb @@ -27,15 +27,16 @@ Takes two parameters: args[1].each do |title, params| raise ArgumentError, 'params should not contain title' if(params['title']) case type_of_resource - when :type - res = resource.hash2resource(params.merge(:title => title)) - catalog.add_resource(res) - when :define + # JJM The only difference between a type and a define is the call to instantiate_resource + # for a defined type. + when :type, :define p_resource = Puppet::Parser::Resource.new(type_name, title, :scope => self, :source => resource) params.merge(:name => title).each do |k,v| p_resource.set_parameter(k,v) end - resource.instantiate_resource(self, p_resource) + if type_of_resource == :define then + resource.instantiate_resource(self, p_resource) + end compiler.add_resource(self, p_resource) when :class klass = find_hostclass(title) -- cgit From ae3ef423c03b7ef27f975dadfb67bf77ca481503 Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Wed, 6 Jul 2011 21:59:05 -0700 Subject: (#7699) - Help should only show options once puppet help was reprinting every option once for every alias that is had. This fix involves only storing the option.name in the @options instance var for both face and actions options. The @options_hash still maintains the list of options and aliases as its keys. Reviewed-by: Daniel Pittman (puppet-dev list) --- lib/puppet/interface/action.rb | 3 ++- lib/puppet/interface/option_manager.rb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index 185302b07..fe77a9658 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -227,8 +227,9 @@ WRAPPER end end + @options << option.name + option.aliases.each do |name| - @options << name @options_hash[name] = option end diff --git a/lib/puppet/interface/option_manager.rb b/lib/puppet/interface/option_manager.rb index 326a91d92..a1f300e8e 100644 --- a/lib/puppet/interface/option_manager.rb +++ b/lib/puppet/interface/option_manager.rb @@ -26,8 +26,9 @@ module Puppet::Interface::OptionManager end end + @options << option.name + option.aliases.each do |name| - @options << name @options_hash[name] = option end -- cgit From 1feccc3f2db29d112308a55032e7f93ca44b45aa Mon Sep 17 00:00:00 2001 From: Jeff McCune Date: Sun, 10 Jul 2011 13:51:31 -0700 Subject: Revert "Merge branch 'ticket/2.7.x/7699_fix_help_listing_options_twice' into 2.7.x" This reverts commit b7ee0258ab40478329c20177eda9b250f27ede18, reversing changes made to 8fe2e555ac3d57f5b6503ffe1a5466db8d6e190a. --- lib/puppet/interface/action.rb | 3 +-- lib/puppet/interface/option_manager.rb | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index fe77a9658..185302b07 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -227,9 +227,8 @@ WRAPPER end end - @options << option.name - option.aliases.each do |name| + @options << name @options_hash[name] = option end diff --git a/lib/puppet/interface/option_manager.rb b/lib/puppet/interface/option_manager.rb index a1f300e8e..326a91d92 100644 --- a/lib/puppet/interface/option_manager.rb +++ b/lib/puppet/interface/option_manager.rb @@ -26,9 +26,8 @@ module Puppet::Interface::OptionManager end end - @options << option.name - option.aliases.each do |name| + @options << name @options_hash[name] = option end -- cgit From 45b3908e03734388b6c699ffbc4223f43b44a1d5 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 12 Jul 2011 15:47:21 -0700 Subject: (#4142) Fix module check not to fail when empty metadata.json Even though the puppet module tool was fixed to generate the required metadata attributes when it packages modules, it still creates an empty metadata.json file that gets checked into everybody's module repos. This causes the module to be unusable straight from a git clone since puppet was requiring all the required metadata attributes just with the presence of that file, and resulting in the error: No source module metadata provided for mcollective at This change makes it so that if you have an empty metadata.json (like the moduletool generates), puppet doesn't consider it to have metadata. If you have ANY metadata attributes in that file, it will still check to make sure all the required attributes are present. The work around up to this point has just been to delete the metadata.json file in git cloned modules. This also fixed the tests around this to actually run, since previously the tests depended on the a json feature, which we didn't have. We do, however, have a pson feature. Reviewed-by: Nick Lewis --- lib/puppet/module.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb index 059591ed8..00468df96 100644 --- a/lib/puppet/module.rb +++ b/lib/puppet/module.rb @@ -42,7 +42,10 @@ class Puppet::Module def has_metadata? return false unless metadata_file - FileTest.exist?(metadata_file) + return false unless FileTest.exist?(metadata_file) + + metadata = PSON.parse File.read(metadata_file) + return metadata.is_a?(Hash) && !metadata.keys.empty? end def initialize(name, environment = nil) -- cgit From b82f29c61aa84a12fc208487e4b049cb24702261 Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Wed, 13 Jul 2011 15:38:32 -0700 Subject: (#7699) Help command should only list options once The problem was caused by the fact that the options method returns a list of options that treated the aliases as seperate options. The fix is to only maintain a list of options and not add all aliases to the options list. --- lib/puppet/interface/action.rb | 3 ++- lib/puppet/interface/option_manager.rb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index 185302b07..fe77a9658 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -227,8 +227,9 @@ WRAPPER end end + @options << option.name + option.aliases.each do |name| - @options << name @options_hash[name] = option end diff --git a/lib/puppet/interface/option_manager.rb b/lib/puppet/interface/option_manager.rb index 326a91d92..a1f300e8e 100644 --- a/lib/puppet/interface/option_manager.rb +++ b/lib/puppet/interface/option_manager.rb @@ -26,8 +26,9 @@ module Puppet::Interface::OptionManager end end + @options << option.name + option.aliases.each do |name| - @options << name @options_hash[name] = option end -- cgit From b268fb3d4cca79bdce0adc7da8b4d47f20769521 Mon Sep 17 00:00:00 2001 From: Max Martin Date: Wed, 6 Jul 2011 15:04:27 -0700 Subject: (#7144) Update Settings#writesub to convert mode to Fixnum Settings#writesub was not checking the type of the mode value passed in from the defaults, causing it to pass a string for mode to File.open, leading to failures. This commit resolves that issue. Paired-with: Matt Robinson --- lib/puppet/util.rb | 1 - lib/puppet/util/settings.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index d06f44808..34c6ec1ed 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -29,7 +29,6 @@ module Util end end - def self.synchronize_on(x,type) sync_object,users = 0,1 begin diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb index f243b8691..4559e9af3 100644 --- a/lib/puppet/util/settings.rb +++ b/lib/puppet/util/settings.rb @@ -721,7 +721,7 @@ if @config.include?(:run_mode) end Puppet::Util::SUIDManager.asuser(*chown) do - mode = obj.mode || 0640 + mode = obj.mode ? obj.mode.to_i : 0640 args << "w" if args.empty? args << mode -- cgit From c4848d25f51372b9c8fc0e5259b7d58fd23ebb44 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Thu, 14 Jul 2011 14:13:31 -0700 Subject: maint: Fix documentation link for fileserver configuration The link to the filesever configuration page linked to the wiki, which links back to the docs site. Short circuiting that do just link to where you want to go. Reviewed-by: Nick Lewis --- lib/puppet/type/file/source.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/type/file/source.rb b/lib/puppet/type/file/source.rb index 76c646baf..49e885865 100755 --- a/lib/puppet/type/file/source.rb +++ b/lib/puppet/type/file/source.rb @@ -42,7 +42,7 @@ module Puppet on the local host, whereas `agent` will connect to the puppet server that it received the manifest from. - See the [fileserver configuration documentation](http://projects.puppetlabs.com/projects/puppet/wiki/File_Serving_Configuration) for information on how to configure + See the [fileserver configuration documentation](http://docs.puppetlabs.com/guides/file_serving.html) for information on how to configure and use file services within Puppet. If you specify multiple file sources for a file, then the first -- cgit From d02000bf0060045eb27649ce2b433dcac34a7827 Mon Sep 17 00:00:00 2001 From: nfagerlund Date: Fri, 15 Jul 2011 10:52:37 -0700 Subject: (#8401) Document that --detailed-exitcodes is a bitmask The agent/apply/device man pages mentioned the 2 and 4 exit codes, but didn't mention that they can combine to make 6 if there are both changes and failures. This commit adds the missing information to all three man pages. Reviewed-by: Matt Robinson --- lib/puppet/application/agent.rb | 8 ++++---- lib/puppet/application/apply.rb | 7 ++++--- lib/puppet/application/device.rb | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/agent.rb b/lib/puppet/application/agent.rb index f0442648b..ea7cbdfb5 100644 --- a/lib/puppet/application/agent.rb +++ b/lib/puppet/application/agent.rb @@ -187,10 +187,10 @@ configuration options can also be generated by running puppet agent with should always at least contain MD5, MD2, SHA1 and SHA256. * --detailed-exitcodes: - Provide transaction information via exit codes. If this is enabled, an - exit code of '2' means there were changes, and an exit code of '4' - means that there were failures during the transaction. This option - only makes sense in conjunction with --onetime. + Provide transaction information via exit codes. If this is enabled, an exit + code of '2' means there were changes, an exit code of '4' means there were + failures during the transaction, and an exit code of '6' means there were both + changes and failures. * --disable: Disable working on the local system. This puts a lock file in place, diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb index 5562a9b09..200309b7d 100644 --- a/lib/puppet/application/apply.rb +++ b/lib/puppet/application/apply.rb @@ -82,9 +82,10 @@ configuration options can also be generated by running puppet with Enable full debugging. * --detailed-exitcodes: - Provide transaction information via exit codes. If this is enabled, an - exit code of '2' means there were changes, and an exit code of '4' - means that there were failures during the transaction. + Provide transaction information via exit codes. If this is enabled, an exit + code of '2' means there were changes, an exit code of '4' means there were + failures during the transaction, and an exit code of '6' means there were both + changes and failures. * --help: Print this help message diff --git a/lib/puppet/application/device.rb b/lib/puppet/application/device.rb index 3e2dec98c..977c5c023 100644 --- a/lib/puppet/application/device.rb +++ b/lib/puppet/application/device.rb @@ -113,10 +113,10 @@ parameter, so you can specify '--server ' as an argument. Enable full debugging. * --detailed-exitcodes: - Provide transaction information via exit codes. If this is enabled, an - exit code of '2' means there were changes, and an exit code of '4' means - that there were failures during the transaction. This option only makes - sense in conjunction with --onetime. + Provide transaction information via exit codes. If this is enabled, an exit + code of '2' means there were changes, an exit code of '4' means there were + failures during the transaction, and an exit code of '6' means there were both + changes and failures. * --help: Print this help message -- cgit From 72abe6ce7192bba0b295a8a83483668d21050624 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Tue, 19 Jul 2011 10:55:26 -0700 Subject: (#7204) Consolidate Semantic Versioning code. This introduces a class representing a semantic version, and implementing a few of the most common uses of them: validation, comparison, and finding the greatest available version matching a range. This refactoring also allows us to easily expand our matching of version ranges in the future, which is a big plus. Reviewed-By: Daniel Pittman --- lib/puppet/interface.rb | 5 ++-- lib/puppet/interface/face_collection.rb | 49 ++++----------------------------- 2 files changed, 8 insertions(+), 46 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 6be8b6930..6c288f3c0 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -2,6 +2,7 @@ require 'puppet' require 'puppet/util/autoload' require 'puppet/interface/documentation' require 'prettyprint' +require 'semver' class Puppet::Interface include FullDocs @@ -84,12 +85,12 @@ class Puppet::Interface attr_reader :name, :version def initialize(name, version, &block) - unless Puppet::Interface::FaceCollection.validate_version(version) + unless SemVer.valid?(version) raise ArgumentError, "Cannot create face #{name.inspect} with invalid version number '#{version}'!" end @name = Puppet::Interface::FaceCollection.underscorize(name) - @version = version + @version = SemVer.new(version) # The few bits of documentation we actually demand. The default license # is a favour to our end users; if you happen to get that in a core face diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb index 12d3c56b1..4522824fd 100644 --- a/lib/puppet/interface/face_collection.rb +++ b/lib/puppet/interface/face_collection.rb @@ -1,8 +1,6 @@ require 'puppet/interface' module Puppet::Interface::FaceCollection - SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ - @faces = Hash.new { |hash, key| hash[key] = {} } def self.faces @@ -17,55 +15,18 @@ module Puppet::Interface::FaceCollection @faces.keys.select {|name| @faces[name].length > 0 } end - def self.validate_version(version) - !!(SEMVER_VERSION =~ version.to_s) - end - - def self.semver_to_array(v) - parts = SEMVER_VERSION.match(v).to_a[1..4] - parts[0..2] = parts[0..2].map { |e| e.to_i } - parts - end - - def self.cmp_semver(a, b) - a, b = [a, b].map do |x| semver_to_array(x) end - - cmp = a[0..2] <=> b[0..2] - if cmp == 0 - cmp = a[3] <=> b[3] - cmp = +1 if a[3].empty? && !b[3].empty? - cmp = -1 if b[3].empty? && !a[3].empty? - end - cmp - end - - def self.prefix_match?(desired, target) - # Can't meaningfully do a prefix match with current on either side. - return false if desired == :current - return false if target == :current - - # REVISIT: Should probably fail if the matcher is not valid. - prefix = desired.split('.').map {|x| x =~ /^\d+$/ and x.to_i } - have = semver_to_array(target) - - while want = prefix.shift do - return false unless want == have.shift - end - return true - end - def self.[](name, version) name = underscorize(name) get_face(name, version) or load_face(name, version) end # get face from memory, without loading. - def self.get_face(name, desired_version) + def self.get_face(name, pattern) return nil unless @faces.has_key? name + return @faces[name][:current] if pattern == :current - return @faces[name][:current] if desired_version == :current - - found = @faces[name].keys.select {|v| prefix_match?(desired_version, v) }.sort.last + versions = @faces[name].keys - [ :current ] + found = SemVer.find_matching(pattern, versions) return @faces[name][found] end @@ -108,7 +69,7 @@ module Puppet::Interface::FaceCollection # versions here and return the last item in that set. # # --daniel 2011-04-06 - latest_ver = @faces[name].keys.sort {|a, b| cmp_semver(a, b) }.last + latest_ver = @faces[name].keys.sort.last @faces[name][:current] = @faces[name][latest_ver] end rescue LoadError => e -- cgit From cc311ad3dcb70547d7249e7aec9f545672c3e8e2 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 19 Jul 2011 16:45:26 -0700 Subject: maint: SSL::Inventory.serial should report missing names. Our SSL inventory was able to find the serial number of a certificate by name, but was incapable of living up to the contract it offered, that it would actually report when a certificate was missing. Now it returns `nil`, which is the same case as "no inventory", if the certificate was not found, rather than accidentally returning the entire inventory data as raw strings. Reviewed-By: Pieter van de Bruggen --- lib/puppet/ssl/inventory.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/ssl/inventory.rb b/lib/puppet/ssl/inventory.rb index e094da100..c210fdc35 100644 --- a/lib/puppet/ssl/inventory.rb +++ b/lib/puppet/ssl/inventory.rb @@ -48,5 +48,7 @@ class Puppet::SSL::Inventory return Integer($1) end + + return nil end end -- cgit From c830ab01f31b3c6999953783a0ec1939bdbc25a9 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 18 Jul 2011 11:40:05 -0700 Subject: (#6789) Port SSL::CertificateAuthority::Interface to a Face The Puppet::SSL::CertificateAuthority::Interface class was an early prototype heading toward building out a system like Faces. Now that we have done that, this changeset ports the early code to a new face. Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/ca.rb | 5 + lib/puppet/face/ca.rb | 233 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 lib/puppet/application/ca.rb create mode 100644 lib/puppet/face/ca.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/ca.rb b/lib/puppet/application/ca.rb new file mode 100644 index 000000000..d1ec2502e --- /dev/null +++ b/lib/puppet/application/ca.rb @@ -0,0 +1,5 @@ +require 'puppet/application/face_base' + +class Puppet::Application::Ca < Puppet::Application::FaceBase + run_mode :master +end diff --git a/lib/puppet/face/ca.rb b/lib/puppet/face/ca.rb new file mode 100644 index 000000000..e643530f0 --- /dev/null +++ b/lib/puppet/face/ca.rb @@ -0,0 +1,233 @@ +require 'puppet/face' + +Puppet::Face.define(:ca, '0.1.0') do + copyright "Puppet Labs", 2011 + license "Apache 2 license; see COPYING" + + summary "Local Puppet Certificate Authority management." + + description < e + "- #{name} (#{host.certificate.fingerprint}) (#{e.to_s})" + end + end + end.join("\n") + end + end + + action :destroy do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + ca.destroy host + end + end + + action :revoke do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.revoke host + rescue ArgumentError => e + # This is a bit naff, but it makes the behaviour consistent with the + # destroy action. The underlying tools could be nicer for that sort + # of thing; they have fairly inconsistent reporting of failures. + raise unless e.to_s =~ /Could not find a serial number for / + "Nothing was revoked" + end + end + end + + action :generate do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.generate host + rescue RuntimeError => e + if e.to_s =~ /already has a requested certificate/ + "#{host} already has a certificate request; use sign instead" + else + raise + end + rescue ArgumentError => e + if e.to_s =~ /A Certificate already exists for / + "#{host} already has a certificate" + else + raise + end + end + end + end + + action :sign do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.sign host + rescue ArgumentError => e + if e.to_s =~ /Could not find certificate request/ + e.to_s + else + raise + end + end + end + end + + action :print do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + ca.print host + end + end + + action :fingerprint do + option "--digest ALGORITHM" do + summary "The hash algorithm to use when displaying the fingerprint" + end + + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + # I want the default from the CA, not to duplicate it, but passing + # 'nil' explicitly means that we don't get that. This works... + if options.has_key? :digest + ca.fingerprint host, options[:digest] + else + ca.fingerprint host + end + rescue ArgumentError => e + raise unless e.to_s =~ /Could not find a certificate or csr for/ + nil + end + end + end + + action :verify do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.verify host + { :host => host, :valid => true } + rescue ArgumentError => e + raise unless e.to_s =~ /Could not find a certificate for/ + { :host => host, :valid => false, :error => e.to_s } + rescue Puppet::SSL::CertificateAuthority::CertificateVerificationError => e + { :host => host, :valid => false, :error => e.to_s } + end + end + + when_rendering :console do |value| + if value[:valid] + nil + else + "Could not verify #{value[:host]}: #{value[:error]}" + end + end + end +end -- cgit From b75b1c19ecf6c278b065d203ac8486fa598caa8b Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Wed, 20 Jul 2011 11:58:55 -0700 Subject: (#6787) Add `default_to` for options. This implement support for options with default values, allowing faces to set those values when not invoked. This can eliminate substantial duplicate code from actions, especially when there are face-level options in use. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/action.rb | 9 +++++++++ lib/puppet/interface/option.rb | 19 +++++++++++++++++++ lib/puppet/interface/option_builder.rb | 13 +++++++++++++ 3 files changed, 41 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index fe77a9658..fc1121eb6 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -199,6 +199,7 @@ def #{@name}(#{decl.join(", ")}) options = args.last action = get_action(#{name.inspect}) + action.add_default_args(args) action.validate_args(args) __invoke_decorations(:before, action, args, options) rval = self.__send__(#{internal_name.inspect}, *args) @@ -252,6 +253,14 @@ 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 + end + end + end + def validate_args(args) # Check for multiple aliases for the same option... args.last.keys.each do |name| diff --git a/lib/puppet/interface/option.rb b/lib/puppet/interface/option.rb index 3cd930acf..01f6f2307 100644 --- a/lib/puppet/interface/option.rb +++ b/lib/puppet/interface/option.rb @@ -6,6 +6,7 @@ class Puppet::Interface::Option def initialize(parent, *declaration, &block) @parent = parent @optparse = [] + @default = nil # Collect and sort the arguments in the declaration. dups = {} @@ -81,8 +82,26 @@ class Puppet::Interface::Option !!@required end + def has_default? + !!@default + end + + def default=(proc) + required and raise ArgumentError, "#{self} can't be optional and have a default value" + proc.is_a? Proc or raise ArgumentError, "default value for #{self} is a #{proc.class.name.inspect}, not a proc" + @default = proc + end + + def default + @default and @default.call + end + attr_reader :parent, :name, :aliases, :optparse attr_accessor :required + def required=(value) + has_default? and raise ArgumentError, "#{self} can't be optional and have a default value" + @required = value + end attr_accessor :before_action def before_action=(proc) diff --git a/lib/puppet/interface/option_builder.rb b/lib/puppet/interface/option_builder.rb index 5676ec977..c87adc2c0 100644 --- a/lib/puppet/interface/option_builder.rb +++ b/lib/puppet/interface/option_builder.rb @@ -51,4 +51,17 @@ class Puppet::Interface::OptionBuilder def required(value = true) @option.required = value end + + def default_to(&block) + block or raise ArgumentError, "#{@option} default_to requires a block" + if @option.has_default? + raise ArgumentError, "#{@option} already has a default value" + end + # Ruby 1.8 treats a block without arguments as accepting any number; 1.9 + # gets this right, so we work around it for now... --daniel 2011-07-20 + unless block.arity == 0 or (RUBY_VERSION =~ /^1\.8/ and block.arity == -1) + raise ArgumentError, "#{@option} default_to block should not take any arguments" + end + @option.default = block + end end -- cgit From fd6a653cb32cb03e339655862c526fd5dccbfcf0 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Wed, 20 Jul 2011 12:35:22 -0700 Subject: (#7123) Support runtime setting of 'default' on actions. Given the inheritance model for actions, we are sometimes going to need to set them to 'default' at runtime, rather than during their static declaration. Add tests to verify that this works correctly, and update the code to ensure that happens. This gives up caching of the default action, but this should be an extremely rare operation - pretty much only CLI invocation, really. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/action_manager.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb index fbf588d7d..5c9af4f96 100644 --- a/lib/puppet/interface/action_manager.rb +++ b/lib/puppet/interface/action_manager.rb @@ -7,13 +7,14 @@ module Puppet::Interface::ActionManager require 'puppet/interface/action_builder' @actions ||= {} - @default_action ||= nil raise "Action #{name} already defined for #{self}" if action?(name) + action = Puppet::Interface::ActionBuilder.build(self, name, &block) - if action.default - raise "Actions #{@default_action.name} and #{name} cannot both be default" if @default_action - @default_action = action + + if action.default and current = get_default_action + raise "Actions #{current.name} and #{name} cannot both be default" end + @actions[action.name] = action end @@ -61,7 +62,11 @@ module Puppet::Interface::ActionManager end def get_default_action - @default_action + default = actions.map {|x| get_action(x) }.select {|x| x.default } + if default.length > 1 + raise "The actions #{default.map(&:name).join(", ")} cannot all be default" + end + default.first end def action?(name) -- cgit From 395c1742981590c694ee6f0154ba7ad63c6bcb36 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Wed, 20 Jul 2011 12:37:53 -0700 Subject: (#7123) Make `find` the default action... Part of the progress toward getting the `puppet status` invocation working nicely is that it should default to invoking the `find` operation. This implements that, using the new runtime default action facility. Reviewed-By: Pieter van de Bruggen --- lib/puppet/face/status.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/puppet') diff --git a/lib/puppet/face/status.rb b/lib/puppet/face/status.rb index bdb0c4d26..e8c87e98d 100644 --- a/lib/puppet/face/status.rb +++ b/lib/puppet/face/status.rb @@ -12,6 +12,7 @@ Puppet::Indirector::Face.define(:status, '0.0.1') do get_action(:search).summary "Invalid for this subcommand." find = get_action(:find) + find.default = true find.summary "Check status of puppet master server." find.arguments "" find.returns <<-'EOT' -- cgit From 1e0655e6bdbc872014abdffa5deacb334616e826 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 21 Jul 2011 15:34:52 -0700 Subject: (#7184) Centralize "find action for face" into Puppet::Face As part of moving to load actions first, and their associated face, when invoked from the command line, it makes sense to push the logic for finding the action and face down into the Puppet::Face implementation. This means that we can change the logic there without needing to update the public part of the CLI implementation, and that any further facades can use the same, correct, logic to locate the action for the face. Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/face_base.rb | 3 ++- lib/puppet/interface.rb | 4 ++++ lib/puppet/interface/action.rb | 1 + lib/puppet/interface/face_collection.rb | 11 +++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) (limited to 'lib/puppet') 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/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..ce9c60b49 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 diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb index 4522824fd..ddc66f583 100644 --- a/lib/puppet/interface/face_collection.rb +++ b/lib/puppet/interface/face_collection.rb @@ -20,6 +20,17 @@ module Puppet::Interface::FaceCollection get_face(name, version) or load_face(name, version) end + def self.get_action_for_face(face_name, action_name, version) + # 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[face_name, version] + unless action = face.get_action(action_name) + # ...we need to search for it bound to an o{lder,ther} version. + end + + return action + end + # get face from memory, without loading. def self.get_face(name, pattern) return nil unless @faces.has_key? name -- cgit From 2cd3bc47993fbd32a77ca9dfdd51353f2dfbcb58 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 21 Jul 2011 16:34:20 -0700 Subject: (#7184) Find actions bound to other versions of Faces. When we first touch a Face, we load all the available Actions from disk. Given they define themselves against a specific version of a Face, they are automatically available tied to the correct version; this makes it trivially possible to locate those on demand and return them. Now, we have the ability to find and, consequently, invoke Actions on older versions of Faces. We don't load enough context, though: the older face will only have external Actions defined, not anything core. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/face_collection.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb index ddc66f583..868997b67 100644 --- a/lib/puppet/interface/face_collection.rb +++ b/lib/puppet/interface/face_collection.rb @@ -20,12 +20,19 @@ module Puppet::Interface::FaceCollection get_face(name, version) or load_face(name, version) end - def self.get_action_for_face(face_name, action_name, version) + 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[face_name, version] + 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. + # ...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 -- cgit From 532c4f37e4f8289cf4a9871ebc0cb5086c2ba26a Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 21 Jul 2011 16:43:16 -0700 Subject: (#7184) Load the core of obsolete versions of Faces. When we define an action on an older version of a Face, we must be sure to directly load the core of that version, not just define it with the external Action(s) that it had. Otherwise we break our contract, which is that any core Actions for a specific version will be available to your external Action for as long as we support that core version. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/face_collection.rb | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb index 868997b67..b1f6ba398 100644 --- a/lib/puppet/interface/face_collection.rb +++ b/lib/puppet/interface/face_collection.rb @@ -56,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 @@ -90,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 -- cgit From 77441be2299bbb96ab9f048855b0fd4c16eb7b5a Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 22 Jul 2011 14:32:00 -0700 Subject: (#8561) Unify validation and modification of action arguments. Rather than having multiple, separate operations that modify and validate the arguments to an action, a single pass makes sense. This also means less walks across the set of data, and a few less expensive method calls in Ruby. Additionally, we work on a duplicate of the arguments hash rather than directly modifying the original. Because everything we do is at the top level key/value mapping, this is sufficient to isolate the original. While mostly theoretical, we now don't mutilate the hash passed in, so the user won't get nastily surprised by the fact that we could have done so. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/action.rb | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index ce9c60b49..2a2f48e03 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -200,8 +200,7 @@ def #{@name}(#{decl.join(", ")}) options = args.last action = get_action(#{name.inspect}) - action.add_default_args(args) - action.validate_args(args) + args = action.validate_and_clean(args) __invoke_decorations(:before, action, args, options) rval = self.__send__(#{internal_name.inspect}, *args) __invoke_decorations(:after, action, args, options) @@ -254,15 +253,19 @@ WRAPPER option end - def add_default_args(args) + def validate_and_clean(original_args) + # Make a shallow copy, so as not to surprise callers. We only modify the + # top level keys and all, so this should be sufficient without being too + # costly overall. + args = original_args.dup + + # Inject default arguments. 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 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 @@ -281,8 +284,12 @@ WRAPPER get_option(name) end.select(&:required?).collect(&:name) - args.last.keys - return if required.empty? - raise ArgumentError, "The following options are required: #{required.join(', ')}" + unless required.empty? + raise ArgumentError, "The following options are required: #{required.join(', ')}" + end + + # All done. + return args end ######################################################################## -- cgit From 82e5fa9561e2d4cb1d699a41c14f50953d8f2d97 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 22 Jul 2011 15:15:38 -0700 Subject: (#8561, #7290) Implement the option contract fully. Rewrite the process of validating and updating the options to fully reflect the contract - we fail if there are unknown options passed, report nicely errors of duplicate names, pass only the canonical names to the action code, and generally enforce nicely. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/action.rb | 84 ++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 35 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index 2a2f48e03..bd47a36ea 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -196,14 +196,12 @@ class Puppet::Interface::Action wrapper = < Date: Fri, 22 Jul 2011 15:24:16 -0700 Subject: maint: don't print inside action implementations. Rather than printing directly, we should return the data from the Action and allow the facade to route that to the user directly. Reviewed-By: Pieter van de Bruggen --- lib/puppet/indirector/face.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/indirector/face.rb b/lib/puppet/indirector/face.rb index ead3f4b46..b4cac5c51 100644 --- a/lib/puppet/indirector/face.rb +++ b/lib/puppet/indirector/face.rb @@ -86,11 +86,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 -- cgit From ae360034c07f9b16467f5ae245ac6d037789ee13 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 22 Jul 2011 16:26:10 -0700 Subject: (#7290) Update indirected Faces to avoid unknown options. Now that we enforce that options must be declared, the model we exposed in the Ruby API (but not the CLI facade) was that you could pass additional arguments to the indirection method by passing them as unknown options doesn't work. Instead, explicitly declare an option, `extra`, that accepts the final argument to be passed direct to the indirection. This makes things work smoothly, as well as making it possible (once you can input a hash on the command line) to invoke extra arguments from the facade too... Reviewed-By: Pieter van de Bruggen --- lib/puppet/indirector/face.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/indirector/face.rb b/lib/puppet/indirector/face.rb index b4cac5c51..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 "" - 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 "" - 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 "" - 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 -- cgit From 10e05ad302d1b2d93f5da070d612817729473009 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Mon, 25 Jul 2011 12:05:31 -0700 Subject: (#7266) Move Certificate option validation into face. The validation for the ca_location option on the certificate application continued to hang around on the application long after the face realized its potential to take responsibility for itself. This change moves (and adds) validation code as appropriate into the Face. Reviewed-By: Matt Robinson --- lib/puppet/application/certificate.rb | 5 ----- lib/puppet/face/certificate.rb | 22 +++++++++++++--------- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'lib/puppet') 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/face/certificate.rb b/lib/puppet/face/certificate.rb index 9a306da37..5e176e27e 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 "" 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 "" - 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,7 +97,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do find = get_action(:find) find.summary "Retrieve a certificate." find.arguments "" - find.returns <<-'EOT' + find.returns <<-EOT An x509 SSL certificate. You will usually want to render this as a string (--render-as s). @@ -105,7 +109,7 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do destroy.summary "Delete a certificate." destroy.arguments "" destroy.returns "Nothing." - destroy.description <<-'EOT' + destroy.description <<-EOT Deletes a certificate. This action currently only works on the local CA. EOT -- cgit From f484851b7528c0fcf1254d25a022e9cb7ef9b3bd Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 19 Jul 2011 14:11:37 -0700 Subject: maint: Add debug logging when the master receives a report It's always bothered me that when running puppet inspect (or any application that produces a report really) the master gives no indication that anything happened when it processes the report. Reviewed-by: Max Martin --- lib/puppet/indirector/report/processor.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/puppet') 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. -- cgit From 3165364e20fc008b3997effafb290fe47c13bf42 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 19 Jul 2011 14:18:43 -0700 Subject: maint: Adding logging to include environment when source fails Reviewed-by: Max Martin --- lib/puppet/type/file/source.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/type/file/source.rb b/lib/puppet/type/file/source.rb index 6ebec51fe..2fb65bbad 100755 --- a/lib/puppet/type/file/source.rb +++ b/lib/puppet/type/file/source.rb @@ -154,7 +154,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 result + fail "Could not retrieve information from environment #{Puppet[:environment]} source(s) #{value.join(", ")}" unless result result end -- cgit From 89c021cac52a4bdecbe490772cb73cef9ef049c5 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 19 Jul 2011 14:19:26 -0700 Subject: (#8418) Fix inspect app to have the correct run_mode Requiring puppet before the run_mode has been set by the application causes the default run_mode of 'user' to be set instead of what the application wants. This leads to the incorrect default settings to be used, which lead to inspect not being able to properly retrieve file metadata from a fileserver. Reviewed-by: Max Martin --- lib/puppet/application/inspect.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/inspect.rb b/lib/puppet/application/inspect.rb index ce32c661c..2260feed7 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 @@ -97,6 +95,11 @@ Licensed under the GNU General Public License version 2 Puppet::Resource::Catalog.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 -- cgit From cc2c3edbb6907e8be03792a83f2b81fb839f5189 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Mon, 25 Jul 2011 15:13:28 -0700 Subject: (Maint.) Unquoting HEREDOCs. The additional quotation marks frustrate certain syntax highlighters, and are completely unnecessary for their use. Reviewed-By: Daniel Pittman --- lib/puppet/face/certificate_request.rb | 10 +++++----- lib/puppet/face/certificate_revocation_list.rb | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/face/certificate_request.rb b/lib/puppet/face/certificate_request.rb index 774821f12..1fb4e81cc 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,14 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do find = get_action(:find) find.summary "Retrieve a single CSR." find.arguments "" - find.returns <<-'EOT' + 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 +31,10 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do search = get_action(:search) search.summary "Retrieve all outstanding CSRs." search.arguments "" - 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.returns <<-EOT EOT search.short_description <<-EOT Retrieves all outstanding certificate signing requests. Due to a known bug, @@ -44,7 +44,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..1623d4342 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,7 +13,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do find = get_action(:find) find.summary "Retrieve the certificate revocation list." find.arguments "" - find.returns <<-'EOT' + find.returns <<-EOT The certificate revocation list. When used from the Ruby API: returns an OpenSSL::X509::CRL object. @@ -28,7 +28,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 +38,7 @@ Puppet::Indirector::Face.define(:certificate_revocation_list, '0.0.1') do destroy.summary "Delete the certificate revocation list." destroy.arguments "" 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. -- cgit From 0366b1856489f01f1c46519dfebbda3a8676f933 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Mon, 25 Jul 2011 15:15:51 -0700 Subject: (#7293) Set default format for SSL-related faces. By default, the SSL-related faces should all render a strings, not with `Object#inspect`. Reviewed-By: Daniel Pittman --- lib/puppet/face/certificate.rb | 4 ++-- lib/puppet/face/certificate_request.rb | 10 ++++------ lib/puppet/face/certificate_revocation_list.rb | 4 +--- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/face/certificate.rb b/lib/puppet/face/certificate.rb index 5e176e27e..8019b6bea 100644 --- a/lib/puppet/face/certificate.rb +++ b/lib/puppet/face/certificate.rb @@ -97,9 +97,9 @@ Puppet::Indirector::Face.define(:certificate, '0.0.1') do find = get_action(:find) find.summary "Retrieve a certificate." find.arguments "" + find.render_as = :s find.returns <<-EOT - An x509 SSL certificate. You will usually want to render this as a - string (--render-as s). + An x509 SSL certificate. Note that this action has a side effect of caching a copy of the certificate in Puppet's `ssldir`. diff --git a/lib/puppet/face/certificate_request.rb b/lib/puppet/face/certificate_request.rb index 1fb4e81cc..cf342d51a 100644 --- a/lib/puppet/face/certificate_request.rb +++ b/lib/puppet/face/certificate_request.rb @@ -15,12 +15,10 @@ Puppet::Indirector::Face.define(:certificate_request, '0.0.1') do find = get_action(:find) find.summary "Retrieve a single CSR." find.arguments "" + 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 Retrieve a single CSR from the puppet master's CA: @@ -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 "" - 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, diff --git a/lib/puppet/face/certificate_revocation_list.rb b/lib/puppet/face/certificate_revocation_list.rb index 1623d4342..022323b29 100644 --- a/lib/puppet/face/certificate_revocation_list.rb +++ b/lib/puppet/face/certificate_revocation_list.rb @@ -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 "" + 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 -- cgit From 778127d0c3cf01701d227ec88a8e5e6550638c35 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Mon, 25 Jul 2011 16:18:54 -0700 Subject: maint: Fix cert app to print help and exit if no subcommand In 2.6.x this was the behavior, but the changes to the way options parsing worked in 2.7.x to support faces changed the behavior of how help was called. This resulted in the follow unhelpful error message when you just called `puppet cert`: /Users/matthewrobinson/work/puppet/lib/puppet/ssl/certificate_authority/interface.rb:85:in `method=' Invalid method to apply Reviewed-by: Pieter van de Bruggen --- lib/puppet/application/cert.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/cert.rb b/lib/puppet/application/cert.rb index 162672b6a..330fba8bd 100644 --- a/lib/puppet/application/cert.rb +++ b/lib/puppet/application/cert.rb @@ -218,7 +218,8 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License if sub = self.command_line.args.shift then self.subcommand = sub else - help + puts help + exit end end result -- cgit From fb2ffd6879f4c885fe29f70e3cf9bcde89cdc8e9 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Mon, 25 Jul 2011 15:34:56 -0700 Subject: (#8596) Detect resource alias conflicts when titles do not match The introduction of composite namevars caused the resource title used in resource aliases to be set as an array, even when the resource only had one namevar. This would fail to conflict with non-alias entries in the resource table, which used a string for the title, even though the single element array contained the same string. Now, we flatten the key used in the resource table, so that single element arrays are represented as strings, and will properly conflict with resource titles. Paired-With: Jacob Helwig --- lib/puppet/resource/catalog.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/resource/catalog.rb b/lib/puppet/resource/catalog.rb index 0a63ff172..2fdd19b0c 100644 --- a/lib/puppet/resource/catalog.rb +++ b/lib/puppet/resource/catalog.rb @@ -98,7 +98,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}]" @@ -111,7 +111,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] ||= [] @@ -377,7 +380,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 -- cgit From 1d4acb5afda61b1f2c05223afff19c68248a3996 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 19 Jul 2011 11:27:03 -0700 Subject: maint: Suggest where to start troubleshooting SSL error message Much like the infamous "hostname was not match" error message, there's another SSL error that people run into that isn't clear how to troubleshoot. err: Could not send report: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed. As far as I can tell this only ever happens when the clock is off on the master or client. People seem to think it will happen other times, but I haven't been able to reproduce it other ways - missing private key, revoked cert, offline CA all have their own errors. I googled around and the only thing I've seen for this error in relation to puppet is the time sync problem. So the error message text just has some additional info to suggest you check your clocks. Reviewed-by: Nick Lewis --- lib/puppet/indirector/rest.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/indirector/rest.rb b/lib/puppet/indirector/rest.rb index 8018fe8e3..19daff51d 100644 --- a/lib/puppet/indirector/rest.rb +++ b/lib/puppet/indirector/rest.rb @@ -93,7 +93,9 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus http_connection.send(method, *args) rescue OpenSSL::SSL::SSLError => error - if error.message.include? "hostname was not match" + if error.message.include? "certificate verify failed" + raise Puppet::Error, "#{error.message}. This is often because the time is out of sync on the server or client" + elsif error.message.include? "hostname was not match" raise unless cert = peer_certs.find { |c| c.name !~ /^puppet ca/i } valid_certnames = [cert.name, *cert.alternate_names].uniq -- cgit From 0c385f1fb436ab6f667693d347f711470305a019 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Mon, 30 May 2011 20:17:11 +0200 Subject: Fix #5010 - Allow leading whitespace in auth.conf The regex used to detect ACE is too lax and would allow trailing spaces to sneak in, which in turn would confuse the ACE parser. Signed-off-by: Brice Figureau --- lib/puppet/network/authconfig.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/network/authconfig.rb b/lib/puppet/network/authconfig.rb index 4ba89fa71..61fb24ded 100644 --- a/lib/puppet/network/authconfig.rb +++ b/lib/puppet/network/authconfig.rb @@ -130,6 +130,7 @@ module Puppet end def parse_right_directive(right, var, value, count) + value.strip! case var when "allow" modify_right(right, :allow, value, "allowing %s access", count) @@ -159,6 +160,7 @@ module Puppet def modify_right(right, method, value, msg, count) value.split(/\s*,\s*/).each do |val| begin + val.strip! right.info msg % val right.send(method, val) rescue AuthStoreError => detail -- cgit From 6401dfe5602fd39cc59ec1f1b3822110e4ad864a Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Mon, 30 May 2011 20:31:14 +0200 Subject: Fix #6026 - security file should support inline comments Auth.conf, namespaceauth.conf and fileserver.conf were not supporting trailing inlined comments. Also this commit fixes some indentation and error management. Signed-off-by: Brice Figureau --- lib/puppet/file_serving/configuration/parser.rb | 19 ++++++------------- lib/puppet/network/authconfig.rb | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/file_serving/configuration/parser.rb b/lib/puppet/file_serving/configuration/parser.rb index 334201d37..83b75e28f 100644 --- a/lib/puppet/file_serving/configuration/parser.rb +++ b/lib/puppet/file_serving/configuration/parser.rb @@ -24,9 +24,10 @@ class Puppet::FileServing::Configuration::Parser < Puppet::Util::LoadedFile when /^\s*$/; next # skip blank lines when /\[([-\w]+)\]/ mount = newmount($1) - when /^\s*(\w+)\s+(.+)$/ + when /^\s*(\w+)\s+(.+?)(\s*#.*)?$/ var = $1 value = $2 + value.strip! raise(ArgumentError, "Fileserver configuration file does not use '=' as a separator") if value =~ /^=/ case var when "path" @@ -58,12 +59,8 @@ class Puppet::FileServing::Configuration::Parser < Puppet::Util::LoadedFile begin mount.info "allowing #{val} access" mount.allow(val) - rescue AuthStoreError => detail - - raise ArgumentError.new( - detail.to_s, - - @count, file) + rescue Puppet::AuthStoreError => detail + raise ArgumentError.new(detail.to_s, @count, file) end } end @@ -75,12 +72,8 @@ class Puppet::FileServing::Configuration::Parser < Puppet::Util::LoadedFile begin mount.info "denying #{val} access" mount.deny(val) - rescue AuthStoreError => detail - - raise ArgumentError.new( - detail.to_s, - - @count, file) + rescue Puppet::AuthStoreError => detail + raise ArgumentError.new(detail.to_s, @count, file) end } end diff --git a/lib/puppet/network/authconfig.rb b/lib/puppet/network/authconfig.rb index 61fb24ded..1e486a2f9 100644 --- a/lib/puppet/network/authconfig.rb +++ b/lib/puppet/network/authconfig.rb @@ -102,7 +102,7 @@ module Puppet name = $3 if $2 == "path" name.chomp! right = newrights.newright(name, count, @file) - when /^\s*(allow|deny|method|environment|auth(?:enticated)?)\s+(.+)$/ + when /^\s*(allow|deny|method|environment|auth(?:enticated)?)\s+(.+?)(\s*#.*)?$/ parse_right_directive(right, $1, $2, count) else raise ConfigurationError, "Invalid line #{count}: #{line}" -- cgit From 7e6fc0d80ccd29f206c3b56960ee1eef3afc33a3 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Tue, 31 May 2011 20:01:36 +0200 Subject: Deprecate RestAuthConfig#allowed? in favor of #check_authorization #allowed? was a poorly named method since it isn't actually a predicate method. Instead of returning a boolean, this methods throws an exception when the access is denied (in order to keep the full context of what ACE triggered the deny). Given that #allowed? was overriding the behavior from AuthConfig, we leave a version of #allowed? in place that will issue a deprecation warning before delegating to #check_authorization. Once support for XML-RPC agents is removed from the master, we will be able to remove this delegation, since there should no longer be a reason for a distinction between AuthConfig and RestAuthConfig. Signed-off-by: Brice Figureau Signed-off-by: Jacob Helwig --- lib/puppet/network/rest_authconfig.rb | 7 ++++++- lib/puppet/network/rest_authorization.rb | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/network/rest_authconfig.rb b/lib/puppet/network/rest_authconfig.rb index dfe8f85c4..7dcc81ef4 100644 --- a/lib/puppet/network/rest_authconfig.rb +++ b/lib/puppet/network/rest_authconfig.rb @@ -29,10 +29,15 @@ module Puppet @main end + def allowed?(request) + Puppet.deprecation_warning "allowed? should not be called for REST authorization - use check_authorization instead" + check_authorization(request) + end + # check wether this request is allowed in our ACL # raise an Puppet::Network::AuthorizedError if the request # is denied. - def allowed?(indirection, method, key, params) + def check_authorization(indirection, method, key, params) read # we're splitting the request in part because diff --git a/lib/puppet/network/rest_authorization.rb b/lib/puppet/network/rest_authorization.rb index 50f094e3e..d636d486a 100644 --- a/lib/puppet/network/rest_authorization.rb +++ b/lib/puppet/network/rest_authorization.rb @@ -16,7 +16,7 @@ module Puppet::Network # Verify that our client has access. def check_authorization(indirection, method, key, params) - authconfig.allowed?(indirection, method, key, params) + authconfig.check_authorization(indirection, method, key, params) end end end -- cgit From c315da0efeace1878a877dc4b2f4aebc1ec13f0d Mon Sep 17 00:00:00 2001 From: Peter Meier Date: Fri, 29 Apr 2011 15:56:15 +0200 Subject: Fix #1886 - Add node cleanup capability Here is a changeset that adds a new action to the puppet node face. This application removes all traces of a node on the puppetmaster (including certs, cached facts and nodes, reports, and storedconfig entries). Furthermore it is capable of unexporting exported resources of a host so that consumers of these resources can remove the exported resources and we will safely remove the node from our infrastructure. Usage: puppet node clean [--unexport] [ ...] To achieve this we add different destroy methods to the different parts of the indirector. So for example for yaml indirections we already offer read access for the yaml, this changeset adds the destroy handler which only removes the yaml file for a request. This can be used to remove cached entries. This work is based on the initial work of Brice Figureau --- lib/puppet/face/node/clean.rb | 154 ++++++++++++++++++++++++++++++ lib/puppet/indirector/report/processor.rb | 45 +++++---- lib/puppet/indirector/yaml.rb | 5 + lib/puppet/reports/store.rb | 15 +++ 4 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 lib/puppet/face/node/clean.rb (limited to 'lib/puppet') diff --git a/lib/puppet/face/node/clean.rb b/lib/puppet/face/node/clean.rb new file mode 100644 index 000000000..10d6239ba --- /dev/null +++ b/lib/puppet/face/node/clean.rb @@ -0,0 +1,154 @@ +Puppet::Indirector::Face.define(:node, '0.0.1') do + action(:clean) do + option "--[no-]unexport" do + summary "Unexport exported resources" + end + + summary "Clean up everything a puppetmaster knows about a node" + + arguments " [ ...]" + + description <<-EOT +This includes + + * Signed certificates ($vardir/ssl/ca/signed/node.domain.pem) + * Cached facts ($vardir/yaml/facts/node.domain.yaml) + * Cached node stuff ($vardir/yaml/node/node.domain.yaml) + * Reports ($vardir/reports/node.domain) + * Stored configs: it can either remove all data from an host in your storedconfig + database, or with --unexport turn every exported resource supporting ensure to absent + so that any other host checking out their config can remove those exported configurations. + +This will unexport exported resources of a +host, so that consumers of these resources can remove the exported +resources and we will safely remove the node from our +infrastructure. +EOT + when_invoked do |*args| + nodes = args[0..-2] + options = args.last + raise "At least one node should be passed" if nodes.empty? || nodes == options + + # TODO: this is a hack and should be removed if faces provide the proper + # infrastructure to set the run mode. + require 'puppet/util/run_mode' + $puppet_application_mode = Puppet::Util::RunMode[:master] + + if Puppet::SSL::CertificateAuthority.ca? + Puppet::SSL::Host.ca_location = :local + else + Puppet::SSL::Host.ca_location = :none + end + + Puppet::Node::Facts.indirection.terminus_class = :yaml + Puppet::Node::Facts.indirection.cache_class = :yaml + Puppet::Node.indirection.terminus_class = :yaml + Puppet::Node.indirection.cache_class = :yaml + + begin + nodes.each do |node| + node = node.downcase + clean_cert(node) + clean_cached_facts(node) + clean_cached_node(node) + clean_reports(node) + clean_storeconfigs(node,options[:unexport]) + end + rescue => detail + puts detail.backtrace if Puppet[:trace] + puts detail.to_s + end + end + end + + # clean signed cert for +host+ + def clean_cert(node) + if Puppet::SSL::Host.ca_location == :local + ca.apply(:revoke, :to => [node]) + ca.apply(:destroy, :to => [node]) + Puppet.info "%s certificates removed from ca" % node + else + Puppet.info "Not managing %s certs as this host is not a CA" % node + end + end + + # clean facts for +host+ + def clean_cached_facts(node) + Puppet::Node::Facts.indirection.destroy(node) + Puppet.info "%s's facts removed" % node + end + + # clean cached node +host+ + def clean_cached_node(node) + Puppet::Node.indirection.destroy(node) + Puppet.info "%s's cached node removed" % node + end + + # clean node reports for +host+ + def clean_reports(node) + Puppet::Transaction::Report.indirection.destroy(node) + Puppet.info "%s's reports removed" % node + end + + # clean storeconfig for +node+ + def clean_storeconfigs(node,do_unexport=false) + return unless Puppet[:storeconfigs] && Puppet.features.rails? + require 'puppet/rails' + Puppet::Rails.connect + unless rails_node = Puppet::Rails::Host.find_by_name(node) + Puppet.notice "No entries found for %s in storedconfigs." % node + return + end + + if do_unexport + unexport(rails_node) + Puppet.notice "Force %s's exported resources to absent" % node + Puppet.warning "Please wait until all other hosts have checked out their configuration before finishing the cleanup with:" + Puppet.warning "$ puppet node clean #{node}" + else + rails_node.destroy + Puppet.notice "%s storeconfigs removed" % node + end + end + + def unexport(node) + # fetch all exported resource + query = {:include => {:param_values => :param_name}} + query[:conditions] = ["exported=? AND host_id=?", true, node.id] + Puppet::Rails::Resource.find(:all, query).each do |resource| + if type_is_ensurable(resource) + line = 0 + param_name = Puppet::Rails::ParamName.find_or_create_by_name("ensure") + + if ensure_param = resource.param_values.find( + :first, + :conditions => [ 'param_name_id = ?', param_name.id] + ) + line = ensure_param.line.to_i + Puppet::Rails::ParamValue.delete(ensure_param.id); + end + + # force ensure parameter to "absent" + resource.param_values.create( + :value => "absent", + :line => line, + :param_name => param_name + ) + Puppet.info("%s has been marked as \"absent\"" % resource.name) + end + end + end + + def ca + @ca ||= Puppet::SSL::CertificateAuthority.instance + end + + def environment + @environemnt ||= Puppet::Node::Environment.new + end + + def type_is_ensurable(resource) + (type=Puppet::Type.type(resource.restype)) && type.validattr?(:ensure) || \ + (type = environment.known_resource_types.find_definition('',resource.restype)) && type.arguments.keys.include?('ensure') + end +end \ No newline at end of file diff --git a/lib/puppet/indirector/report/processor.rb b/lib/puppet/indirector/report/processor.rb index 81b379eb8..7bdadcb36 100644 --- a/lib/puppet/indirector/report/processor.rb +++ b/lib/puppet/indirector/report/processor.rb @@ -14,6 +14,12 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code process(request.instance) end + def destroy(request) + processors do |mod| + mod.destroy(request.key) if mod.respond_to?(:destroy) + end + end + private # Process the report with each of the configured report types. @@ -21,23 +27,17 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code # 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. - newrep = report.dup - begin - newrep.extend(mod) - newrep.process - rescue => detail - puts detail.backtrace if Puppet[:trace] - Puppet.err "Report #{name} failed: #{detail}" - end - else - Puppet.warning "No report named '#{name}'" + processors do |mod| + Puppet.debug "Processing report from #{report.host} with processor #{mod}" + # We have to use a dup because we're including a module in the + # report. + newrep = report.dup + begin + newrep.extend(mod) + newrep.process + rescue => detail + puts detail.backtrace if Puppet[:trace] + Puppet.err "Report #{name} failed: #{detail}" end end end @@ -47,4 +47,15 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] x = Puppet[:reports].gsub(/(^\s+)|(\s+$)/, '').split(/\s*,\s*/) end + + def processors(&blk) + return if Puppet[:reports] == "none" + reports.each do |name| + if mod = Puppet::Reports.report(name) + yield(mod) + else + Puppet.warning "No report named '#{name}'" + end + end + end end diff --git a/lib/puppet/indirector/yaml.rb b/lib/puppet/indirector/yaml.rb index 23997e97a..7b12d25e2 100644 --- a/lib/puppet/indirector/yaml.rb +++ b/lib/puppet/indirector/yaml.rb @@ -47,6 +47,11 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus File.join(base, self.class.indirection_name.to_s, name.to_s + ext) end + def destroy(request) + file_path = path(request.key) + File.unlink(file_path) if File.exists?(file_path) + end + def search(request) Dir.glob(path(request.key,'')).collect do |file| YAML.load_file(file) diff --git a/lib/puppet/reports/store.rb b/lib/puppet/reports/store.rb index 625a263b3..997206ec4 100644 --- a/lib/puppet/reports/store.rb +++ b/lib/puppet/reports/store.rb @@ -41,5 +41,20 @@ Puppet::Reports.register_report(:store) do # Only testing cares about the return value file end + + # removes all reports for a given host + def self.destroy(host) + client = host.gsub("..",".") + dir = File.join(Puppet[:reportdir], client) + + if File.exists?(dir) + Dir.entries(dir).each do |file| + next if ['.','..'].include?(file) + file = File.join(dir, file) + File.unlink(file) if File.file?(file) + end + Dir.rmdir(dir) + end + end end -- cgit From ccd622a96dfe5871689f5b2f059c11aef3caf3b4 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Wed, 27 Jul 2011 14:10:02 -0700 Subject: (#1886) Clean up `node clean` for merge. This includes various style changes, and assorted fixes to testing. Paired-With: Matt Robinson --- lib/puppet/face/ca.rb | 30 ++++++------ lib/puppet/face/node/clean.rb | 111 ++++++++++++++++++++---------------------- 2 files changed, 69 insertions(+), 72 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/face/ca.rb b/lib/puppet/face/ca.rb index e643530f0..00591d637 100644 --- a/lib/puppet/face/ca.rb +++ b/lib/puppet/face/ca.rb @@ -6,21 +6,21 @@ Puppet::Face.define(:ca, '0.1.0') do summary "Local Puppet Certificate Authority management." - description < [ ...]" - description <<-EOT -This includes - - * Signed certificates ($vardir/ssl/ca/signed/node.domain.pem) - * Cached facts ($vardir/yaml/facts/node.domain.yaml) - * Cached node stuff ($vardir/yaml/node/node.domain.yaml) - * Reports ($vardir/reports/node.domain) - * Stored configs: it can either remove all data from an host in your storedconfig - database, or with --unexport turn every exported resource supporting ensure to absent - so that any other host checking out their config can remove those exported configurations. - -This will unexport exported resources of a -host, so that consumers of these resources can remove the exported -resources and we will safely remove the node from our -infrastructure. -EOT + This includes + + * Signed certificates ($vardir/ssl/ca/signed/node.domain.pem) + * Cached facts ($vardir/yaml/facts/node.domain.yaml) + * Cached node stuff ($vardir/yaml/node/node.domain.yaml) + * Reports ($vardir/reports/node.domain) + * Stored configs: it can either remove all data from an host in your + storedconfig database, or with --unexport turn every exported resource + supporting ensure to absent so that any other host checking out their + config can remove those exported configurations. + + This will unexport exported resources of a + host, so that consumers of these resources can remove the exported + resources and we will safely remove the node from our + infrastructure. + EOT + when_invoked do |*args| nodes = args[0..-2] options = args.last @@ -39,82 +39,78 @@ EOT else Puppet::SSL::Host.ca_location = :none end - + Puppet::Node::Facts.indirection.terminus_class = :yaml Puppet::Node::Facts.indirection.cache_class = :yaml Puppet::Node.indirection.terminus_class = :yaml Puppet::Node.indirection.cache_class = :yaml - begin - nodes.each do |node| - node = node.downcase - clean_cert(node) - clean_cached_facts(node) - clean_cached_node(node) - clean_reports(node) - clean_storeconfigs(node,options[:unexport]) - end - rescue => detail - puts detail.backtrace if Puppet[:trace] - puts detail.to_s - end + nodes.each { |node| cleanup(node.downcase, options[:unexport]) } end end - + + def cleanup(node, unexport) + clean_cert(node) + clean_cached_facts(node) + clean_cached_node(node) + clean_reports(node) + clean_storeconfigs(node, unexport) + end + # clean signed cert for +host+ def clean_cert(node) - if Puppet::SSL::Host.ca_location == :local - ca.apply(:revoke, :to => [node]) - ca.apply(:destroy, :to => [node]) - Puppet.info "%s certificates removed from ca" % node + if Puppet::SSL::CertificateAuthority.ca? + Puppet::Face[:ca, :current].revoke(node) + Puppet::Face[:ca, :current].destroy(node) + Puppet.info "#{node} certificates removed from ca" else - Puppet.info "Not managing %s certs as this host is not a CA" % node + Puppet.info "Not managing #{node} certs as this host is not a CA" end end # clean facts for +host+ def clean_cached_facts(node) Puppet::Node::Facts.indirection.destroy(node) - Puppet.info "%s's facts removed" % node + Puppet.info "#{node}'s facts removed" end # clean cached node +host+ def clean_cached_node(node) Puppet::Node.indirection.destroy(node) - Puppet.info "%s's cached node removed" % node + Puppet.info "#{node}'s cached node removed" end # clean node reports for +host+ def clean_reports(node) Puppet::Transaction::Report.indirection.destroy(node) - Puppet.info "%s's reports removed" % node + Puppet.info "#{node}'s reports removed" end # clean storeconfig for +node+ - def clean_storeconfigs(node,do_unexport=false) + def clean_storeconfigs(node, do_unexport=false) return unless Puppet[:storeconfigs] && Puppet.features.rails? require 'puppet/rails' Puppet::Rails.connect unless rails_node = Puppet::Rails::Host.find_by_name(node) - Puppet.notice "No entries found for %s in storedconfigs." % node + Puppet.notice "No entries found for #{node} in storedconfigs." return end if do_unexport unexport(rails_node) - Puppet.notice "Force %s's exported resources to absent" % node + Puppet.notice "Force #{node}'s exported resources to absent" Puppet.warning "Please wait until all other hosts have checked out their configuration before finishing the cleanup with:" Puppet.warning "$ puppet node clean #{node}" else rails_node.destroy - Puppet.notice "%s storeconfigs removed" % node + Puppet.notice "#{node} storeconfigs removed" end end def unexport(node) # fetch all exported resource query = {:include => {:param_values => :param_name}} - query[:conditions] = ["exported=? AND host_id=?", true, node.id] + query[:conditions] = [ "exported=? AND host_id=?", true, node.id ] Puppet::Rails::Resource.find(:all, query).each do |resource| if type_is_ensurable(resource) line = 0 @@ -122,7 +118,7 @@ EOT if ensure_param = resource.param_values.find( :first, - :conditions => [ 'param_name_id = ?', param_name.id] + :conditions => [ 'param_name_id = ?', param_name.id ] ) line = ensure_param.line.to_i Puppet::Rails::ParamValue.delete(ensure_param.id); @@ -134,21 +130,22 @@ EOT :line => line, :param_name => param_name ) - Puppet.info("%s has been marked as \"absent\"" % resource.name) + Puppet.info("#{resource.name} has been marked as \"absent\"") end end end - def ca - @ca ||= Puppet::SSL::CertificateAuthority.instance - end - def environment - @environemnt ||= Puppet::Node::Environment.new + @environment ||= Puppet::Node::Environment.new end def type_is_ensurable(resource) - (type=Puppet::Type.type(resource.restype)) && type.validattr?(:ensure) || \ - (type = environment.known_resource_types.find_definition('',resource.restype)) && type.arguments.keys.include?('ensure') + if (type = Puppet::Type.type(resource.restype)) && type.validattr?(:ensure) + return true + else + type = environment.known_resource_types.find_definition('', resource.restype) + return true if type && type.arguments.keys.include?('ensure') + end + return false end -end \ No newline at end of file +end -- cgit From 023d9597b9895f57fda05dc79adad41684179eb2 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 28 Jul 2011 15:08:00 -0700 Subject: (#8690) Accept 'global' options in Puppet Faces When we introduced verification of options, we forgot to handle the case that global options from the Puppet settings system could be passed to the face. This, in turn, means that the system would fail if you used any of those. This remediates that, and now these work as expected. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/action.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index bd47a36ea..60ddb2ca3 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -269,6 +269,8 @@ WRAPPER else result[canonical] = original[name] end + elsif Puppet.settings.include? name + result[name] = original[name] else unknown << name end -- cgit From 38801ddbd3036b45d35e48e444d1e7d566b5db47 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Thu, 28 Jul 2011 15:34:47 -0700 Subject: (Maint.) Disable cleaning of storeconfigs. This feature (and the corresponding tests) were causing intermittent failures which we were unable to trace. We will reintroduce this behavior when we can do so without test fragility. Reviewed-By: Matt Robinson --- lib/puppet/face/node/clean.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/face/node/clean.rb b/lib/puppet/face/node/clean.rb index a4df1bfaf..d2852de04 100644 --- a/lib/puppet/face/node/clean.rb +++ b/lib/puppet/face/node/clean.rb @@ -54,7 +54,10 @@ Puppet::Face.define(:node, '0.0.1') do clean_cached_facts(node) clean_cached_node(node) clean_reports(node) - clean_storeconfigs(node, unexport) + + # This is roughly functional, but seems to introduce order-dependent test + # failures; this can be re-added when those issues are resolved. + # clean_storeconfigs(node, unexport) end # clean signed cert for +host+ -- cgit From 94f0b93b6065d1818f0f3b99d12d651655247c30 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Fri, 29 Jul 2011 12:29:51 -0700 Subject: (#8704) Give better errors for invalid fileserver.conf If you tried to just put an allow or deny line in the fileserver.conf without a mount point, you got a really confusing error message: lib/puppet/network/handler/fileserver.rb:285:in `readconfig': undefined method `info' for nil:NilClass (NoMethodError) Now instead we give an error saying no mount point was specified. Reviewed-by: Josh Cooper --- lib/puppet/network/handler/fileserver.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb index 5b4b17a32..5da4cedef 100755 --- a/lib/puppet/network/handler/fileserver.rb +++ b/lib/puppet/network/handler/fileserver.rb @@ -269,6 +269,7 @@ class Puppet::Network::Handler value = $2 case var when "path" + raise FileServerError.new("No mount specified for argument #{var} #{value}") unless mount if mount.name == MODULES Puppet.warning "The '#{mount.name}' module can not have a path. Ignoring attempt to set it" else @@ -280,6 +281,7 @@ class Puppet::Network::Handler end end when "allow" + raise FileServerError.new("No mount specified for argument #{var} #{value}") unless mount value.split(/\s*,\s*/).each { |val| begin mount.info "allowing #{val} access" @@ -294,6 +296,7 @@ class Puppet::Network::Handler end } when "deny" + raise FileServerError.new("No mount specified for argument #{var} #{value}") unless mount value.split(/\s*,\s*/).each { |val| begin mount.info "denying #{val} access" -- cgit From ea0f2bf3fe596c6356db1150b28ddf6842f22ae9 Mon Sep 17 00:00:00 2001 From: Jacob Helwig Date: Tue, 2 Aug 2011 14:12:16 -0700 Subject: Revert "Merge branch 'vcsrepo'" vcsrepo is available in a module of its own, is missing tests, and goes against the long-term goal of moving "extra" types out of core puppet into modules (an example of this is the nagios types). This reverts commit 25b967559dfa39eb094008c7a3952c4ee885530b, reversing changes made to b87a1dea704ed981f2f0af728afac2c63e87b5a8. Reviewed-by: Michael Stahnke --- lib/puppet/provider/vcsrepo.rb | 34 ----- lib/puppet/provider/vcsrepo/bzr.rb | 64 --------- lib/puppet/provider/vcsrepo/cvs.rb | 80 ----------- lib/puppet/provider/vcsrepo/git.rb | 264 ------------------------------------- lib/puppet/provider/vcsrepo/hg.rb | 101 -------------- lib/puppet/provider/vcsrepo/svn.rb | 82 ------------ lib/puppet/type/vcsrepo.rb | 138 ------------------- 7 files changed, 763 deletions(-) delete mode 100644 lib/puppet/provider/vcsrepo.rb delete mode 100644 lib/puppet/provider/vcsrepo/bzr.rb delete mode 100644 lib/puppet/provider/vcsrepo/cvs.rb delete mode 100644 lib/puppet/provider/vcsrepo/git.rb delete mode 100644 lib/puppet/provider/vcsrepo/hg.rb delete mode 100644 lib/puppet/provider/vcsrepo/svn.rb delete mode 100644 lib/puppet/type/vcsrepo.rb (limited to 'lib/puppet') diff --git a/lib/puppet/provider/vcsrepo.rb b/lib/puppet/provider/vcsrepo.rb deleted file mode 100644 index 2c026ba86..000000000 --- a/lib/puppet/provider/vcsrepo.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'tmpdir' -require 'digest/md5' -require 'fileutils' - -# Abstract -class Puppet::Provider::Vcsrepo < Puppet::Provider - - private - - def set_ownership - owner = @resource.value(:owner) || nil - group = @resource.value(:group) || nil - FileUtils.chown_R(owner, group, @resource.value(:path)) - end - - def path_exists? - File.directory?(@resource.value(:path)) - end - - # Note: We don't rely on Dir.chdir's behavior of automatically returning the - # value of the last statement -- for easier stubbing. - def at_path(&block) #:nodoc: - value = nil - Dir.chdir(@resource.value(:path)) do - value = yield - end - value - end - - def tempdir - @tempdir ||= File.join(Dir.tmpdir, 'vcsrepo-' + Digest::MD5.hexdigest(@resource.value(:path))) - end - -end diff --git a/lib/puppet/provider/vcsrepo/bzr.rb b/lib/puppet/provider/vcsrepo/bzr.rb deleted file mode 100644 index a0605624b..000000000 --- a/lib/puppet/provider/vcsrepo/bzr.rb +++ /dev/null @@ -1,64 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:bzr, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Bazaar repositories" - - commands :bzr => 'bzr' - defaultfor :bzr => :exists - has_features :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - clone_repository(@resource.value(:revision)) - end - end - - def exists? - File.directory?(File.join(@resource.value(:path), '.bzr')) - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def revision - at_path do - current_revid = bzr('version-info')[/^revision-id:\s+(\S+)/, 1] - desired = @resource.value(:revision) - begin - desired_revid = bzr('revision-info', desired).strip.split(/\s+/).last - rescue Puppet::ExecutionFailure - # Possible revid available during update (but definitely not current) - desired_revid = nil - end - if current_revid == desired_revid - desired - else - current_revid - end - end - end - - def revision=(desired) - bzr('update', '-r', desired, @resource.value(:path)) - end - - private - - def create_repository(path) - bzr('init', path) - end - - def clone_repository(revision) - args = ['branch'] - if revision - args.push('-r', revision) - end - args.push(@resource.value(:source), - @resource.value(:path)) - bzr(*args) - end - -end diff --git a/lib/puppet/provider/vcsrepo/cvs.rb b/lib/puppet/provider/vcsrepo/cvs.rb deleted file mode 100644 index e82c23afe..000000000 --- a/lib/puppet/provider/vcsrepo/cvs.rb +++ /dev/null @@ -1,80 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:cvs, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports CVS repositories/workspaces" - - commands :cvs => 'cvs' - defaultfor :cvs => :exists - has_features :gzip_compression, :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - checkout_repository - end - end - - def exists? - if @resource.value(:source) - directory = File.join(@resource.value(:path), 'CVS') - else - directory = File.join(@resource.value(:path), 'CVSROOT') - end - File.directory?(directory) - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def revision - if File.exist?(tag_file) - contents = File.read(tag_file) - # Note: Doesn't differentiate between N and T entries - contents[1..-1] - else - 'MAIN' - end - end - - def revision=(desired) - at_path do - cvs('update', '-r', desired, '.') - end - end - - private - - def tag_file - File.join(@resource.value(:path), 'CVS', 'Tag') - end - - def checkout_repository - dirname, basename = File.split(@resource.value(:path)) - Dir.chdir(dirname) do - args = ['-d', @resource.value(:source)] - if @resource.value(:compression) - args.push('-z', @resource.value(:compression)) - end - args.push('checkout', '-d', basename, module_name) - cvs(*args) - end - if @resource.value(:revision) - self.revision = @resource.value(:revision) - end - end - - # When the source: - # * Starts with ':' (eg, :pserver:...) - def module_name - if (source = @resource.value(:source)) - source[0, 1] == ':' ? File.basename(source) : '.' - end - end - - def create_repository(path) - cvs('-d', path, 'init') - end - -end diff --git a/lib/puppet/provider/vcsrepo/git.rb b/lib/puppet/provider/vcsrepo/git.rb deleted file mode 100644 index fa7e492cf..000000000 --- a/lib/puppet/provider/vcsrepo/git.rb +++ /dev/null @@ -1,264 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Git repositories" - - ##TODO modify the commands below so that the su - is included - commands :git => 'git' - defaultfor :git => :exists - has_features :bare_repositories, :reference_tracking - - def create - if !@resource.value(:source) - init_repository(@resource.value(:path)) - else - clone_repository(@resource.value(:source), @resource.value(:path)) - if @resource.value(:revision) - if @resource.value(:ensure) == :bare - notice "Ignoring revision for bare repository" - else - checkout_or_reset - end - end - if @resource.value(:ensure) != :bare - update_submodules - end - end - update_owner_and_excludes - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def latest? - at_path do - return self.revision == self.latest - end - end - - def latest - branch = on_branch? - if branch == 'master' - return get_revision('origin/HEAD') - else - return get_revision('origin/%s' % branch) - end - end - - def revision - update_references - current = at_path { git('rev-parse', 'HEAD') } - canonical = at_path { git('rev-parse', @resource.value(:revision)) } - if current == canonical - @resource.value(:revision) - else - current - end - end - - def revision=(desired) - checkout_or_reset(desired) - if local_branch_revision?(desired) - # reset instead of pull to avoid merge conflicts. assuming remote is - # authoritative. - # might be worthwhile to have an allow_local_changes param to decide - # whether to reset or pull when we're ensuring latest. - at_path { git('reset', '--hard', "origin/#{desired}") } - end - if @resource.value(:ensure) != :bare - update_submodules - end - update_owner_and_excludes - end - - def bare_exists? - bare_git_config_exists? && !working_copy_exists? - end - - def working_copy_exists? - File.directory?(File.join(@resource.value(:path), '.git')) - end - - def exists? - working_copy_exists? || bare_exists? - end - - def update_references - at_path do - git('fetch', '--tags', 'origin') - end - end - - private - - def bare_git_config_exists? - File.exist?(File.join(@resource.value(:path), 'config')) - end - - def clone_repository(source, path) - check_force - args = ['clone'] - if @resource.value(:ensure) == :bare - args << '--bare' - end - if !File.exist?(File.join(@resource.value(:path), '.git')) - args.push(source, path) - git(*args) - else - notice "Repo has already been cloned" - end - end - - def check_force - if path_exists? - if @resource.value(:force) - notice "Removing %s to replace with vcsrepo." % @resource.value(:path) - destroy - else - raise Puppet::Error, "Could not create repository (non-repository at path)" - end - end - end - - def init_repository(path) - check_force - if @resource.value(:ensure) == :bare && working_copy_exists? - convert_working_copy_to_bare - elsif @resource.value(:ensure) == :present && bare_exists? - convert_bare_to_working_copy - else - # normal init - FileUtils.mkdir(@resource.value(:path)) - args = ['init'] - if @resource.value(:ensure) == :bare - args << '--bare' - end - at_path do - git(*args) - end - end - end - - # Convert working copy to bare - # - # Moves: - # /.git - # to: - # / - def convert_working_copy_to_bare - notice "Converting working copy repository to bare repository" - FileUtils.mv(File.join(@resource.value(:path), '.git'), tempdir) - FileUtils.rm_rf(@resource.value(:path)) - FileUtils.mv(tempdir, @resource.value(:path)) - end - - # Convert bare to working copy - # - # Moves: - # / - # to: - # /.git - def convert_bare_to_working_copy - notice "Converting bare repository to working copy repository" - FileUtils.mv(@resource.value(:path), tempdir) - FileUtils.mkdir(@resource.value(:path)) - FileUtils.mv(tempdir, File.join(@resource.value(:path), '.git')) - if commits_in?(File.join(@resource.value(:path), '.git')) - reset('HEAD') - git('checkout', '-f') - update_owner_and_excludes - end - end - - def commits_in?(dot_git) - Dir.glob(File.join(dot_git, 'objects/info/*'), File::FNM_DOTMATCH) do |e| - return true unless %w(. ..).include?(File::basename(e)) - end - false - end - - def checkout_or_reset(revision = @resource.value(:revision)) - if local_branch_revision? - reset(revision) - elsif tag_revision? - at_path { git('checkout', '-b', revision) } - elsif remote_branch_revision? - at_path { git('checkout', '-b', revision, '--track', "origin/#{revision}") } - end - end - - def reset(desired) - at_path do - git('reset', '--hard', desired) - end - end - - def update_submodules - at_path do - git('submodule', 'init') - git('submodule', 'update') - git('submodule', 'foreach', 'git', 'submodule', 'init') - git('submodule', 'foreach', 'git', 'submodule', 'update') - end - end - - def remote_branch_revision?(revision = @resource.value(:revision)) - # git < 1.6 returns 'origin/#{revision}' - # git 1.6+ returns 'remotes/origin/#{revision}' - at_path { branches.grep /(remotes\/)?origin\/#{revision}/ } - end - - def local_branch_revision?(revision = @resource.value(:revision)) - at_path { branches.include?(revision) } - end - - def tag_revision?(revision = @resource.value(:revision)) - at_path { tags.include?(revision) } - end - - def branches - at_path { git('branch', '-a') }.gsub('*', ' ').split(/\n/).map { |line| line.strip } - end - - def on_branch? - at_path { git('branch', '-a') }.split(/\n/).grep(/\*/).to_s.gsub('*', '').strip - end - - def tags - at_path { git('tag', '-l') }.split(/\n/).map { |line| line.strip } - end - - def set_excludes - at_path { open('.git/info/exclude', 'w') { |f| @resource.value(:excludes).each { |ex| f.write(ex + "\n") }}} - end - - def get_revision(rev) - if !working_copy_exists? - create - end - at_path do - git('fetch', 'origin') - git('fetch', '--tags', 'origin') - end - current = at_path { git('rev-parse', rev).strip } - if @resource.value(:revision) - if local_branch_revision? - canonical = at_path { git('rev-parse', @resource.value(:revision)).strip } - elsif remote_branch_revision? - canonical = at_path { git('rev-parse', 'origin/' + @resource.value(:revision)).strip } - end - current = @resource.value(:revision) if current == canonical - end - return current - end - - def update_owner_and_excludes - if @resource.value(:owner) or @resource.value(:group) - set_ownership - end - if @resource.value(:excludes) - set_excludes - end - end -end diff --git a/lib/puppet/provider/vcsrepo/hg.rb b/lib/puppet/provider/vcsrepo/hg.rb deleted file mode 100644 index f96758612..000000000 --- a/lib/puppet/provider/vcsrepo/hg.rb +++ /dev/null @@ -1,101 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:hg, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Mercurial repositories" - - commands :hg => 'hg' - defaultfor :hg => :exists - has_features :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - clone_repository(@resource.value(:revision)) - end - update_owner - end - - def working_copy_exists? - File.directory?(File.join(@resource.value(:path), '.hg')) - end - - def exists? - working_copy_exists? - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def latest? - at_path do - return self.revision == self.latest - end - end - - def latest - at_path do - begin - hg('incoming', '--branch', '.', '--newest-first', '--limit', '1')[/^changeset:\s+(?:-?\d+):(\S+)/m, 1] - rescue Puppet::ExecutionFailure - # If there are no new changesets, return the current nodeid - self.revision - end - end - end - - def revision - at_path do - current = hg('parents')[/^changeset:\s+(?:-?\d+):(\S+)/m, 1] - desired = @resource.value(:revision) - if desired - # Return the tag name if it maps to the current nodeid - mapped = hg('tags')[/^#{Regexp.quote(desired)}\s+\d+:(\S+)/m, 1] - if current == mapped - desired - else - current - end - else - current - end - end - end - - def revision=(desired) - at_path do - hg('pull') - begin - hg('merge') - rescue Puppet::ExecutionFailure - # If there's nothing to merge, just skip - end - hg('update', '--clean', '-r', desired) - end - update_owner - end - - private - - def create_repository(path) - hg('init', path) - end - - def clone_repository(revision) - args = ['clone'] - if revision - args.push('-u', revision) - end - args.push(@resource.value(:source), - @resource.value(:path)) - hg(*args) - end - - def update_owner - if @resource.value(:owner) or @resource.value(:group) - set_ownership - end - end - -end diff --git a/lib/puppet/provider/vcsrepo/svn.rb b/lib/puppet/provider/vcsrepo/svn.rb deleted file mode 100644 index 680188c1e..000000000 --- a/lib/puppet/provider/vcsrepo/svn.rb +++ /dev/null @@ -1,82 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', 'vcsrepo') - -Puppet::Type.type(:vcsrepo).provide(:svn, :parent => Puppet::Provider::Vcsrepo) do - desc "Supports Subversion repositories" - - commands :svn => 'svn', - :svnadmin => 'svnadmin' - - defaultfor :svn => :exists - has_features :filesystem_types, :reference_tracking - - def create - if !@resource.value(:source) - create_repository(@resource.value(:path)) - else - checkout_repository(@resource.value(:source), - @resource.value(:path), - @resource.value(:revision)) - end - end - - def working_copy_exists? - File.directory?(File.join(@resource.value(:path), '.svn')) - end - - def exists? - working_copy_exists? - end - - def destroy - FileUtils.rm_rf(@resource.value(:path)) - end - - def latest? - at_path do - if self.revision < self.latest then - return false - else - return true - end - end - end - - def latest - at_path do - svn('info', '-r', 'HEAD')[/^Revision:\s+(\d+)/m, 1] - end - end - - def revision - at_path do - svn('info')[/^Revision:\s+(\d+)/m, 1] - end - end - - def revision=(desired) - at_path do - svn('update', '-r', desired) - end - end - - private - - def checkout_repository(source, path, revision = nil) - args = ['checkout'] - if revision - args.push('-r', revision) - end - args.push(source, path) - svn(*args) - end - - def create_repository(path) - args = ['create'] - if @resource.value(:fstype) - args.push('--fs-type', @resource.value(:fstype)) - end - args << path - svnadmin(*args) - end - -end diff --git a/lib/puppet/type/vcsrepo.rb b/lib/puppet/type/vcsrepo.rb deleted file mode 100644 index f0d2613ca..000000000 --- a/lib/puppet/type/vcsrepo.rb +++ /dev/null @@ -1,138 +0,0 @@ -require 'pathname' - -Puppet::Type.newtype(:vcsrepo) do - desc "A local version control repository" - - feature :gzip_compression, - "The provider supports explicit GZip compression levels" - - feature :bare_repositories, - "The provider differentiates between bare repositories - and those with working copies", - :methods => [:bare_exists?, :working_copy_exists?] - - feature :filesystem_types, - "The provider supports different filesystem types" - - feature :reference_tracking, - "The provider supports tracking revision references that can change - over time (eg, some VCS tags and branch names)" - - ensurable do - attr_accessor :latest - - def insync?(is) - @should ||= [] - - case should - when :present - return true unless [:absent, :purged, :held].include?(is) - when :latest - if is == :latest - return true - else - self.debug "%s repo revision is %s, latest is %s" % - [@resource.name, provider.revision, provider.latest] - return false - end - end - end - - newvalue :present do - provider.create - end - - newvalue :bare, :required_features => [:bare_repositories] do - provider.create - end - - newvalue :absent do - provider.destroy - end - - newvalue :latest, :required_features => [:reference_tracking] do - if provider.exists? - if provider.respond_to?(:update_references) - provider.update_references - end - if provider.respond_to?(:latest?) - reference = provider.latest || provider.revision - else - reference = resource.value(:revision) || provider.revision - end - notice "Updating to latest '#{reference}' revision" - provider.revision = reference - else - provider.create - end - end - - def retrieve - prov = @resource.provider - if prov - if prov.working_copy_exists? - prov.latest? ? :latest : :present - elsif prov.class.feature?(:bare_repositories) and prov.bare_exists? - :bare - else - :absent - end - else - raise Puppet::Error, "Could not find provider" - end - end - - end - - newparam(:path) do - desc "Absolute path to repository" - isnamevar - validate do |value| - path = Pathname.new(value) - unless path.absolute? - raise ArgumentError, "Path must be absolute: #{path}" - end - end - end - - newparam(:source) do - desc "The source URI for the repository" - end - - newparam(:fstype, :required_features => [:filesystem_types]) do - desc "Filesystem type" - end - - newproperty(:revision) do - desc "The revision of the repository" - newvalue(/^\S+$/) - end - - newparam(:owner) do - desc "The user/uid that owns the repository files" - end - - newparam(:group) do - desc "The group/gid that owns the repository files" - end - - newparam(:excludes) do - desc "Files to be excluded from the repository" - end - - newparam(:force) do - desc "Force repository creation, destroying any files on the path in the process." - newvalues(:true, :false) - defaultto false - end - - newparam :compression, :required_features => [:gzip_compression] do - desc "Compression level" - validate do |amount| - unless Integer(amount).between?(0, 6) - raise ArgumentError, "Unsupported compression level: #{amount} (expected 0-6)" - end - end - end - -end -- cgit From 711344836aa1e469876fc511be14e8159e61b0b8 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 4 Aug 2011 10:49:59 -0700 Subject: (#4762) Ensure that clients on the moon can successfully connect. Previously, we only allowed Puppet Clients at a maximum distance of somewhere between 7,494 and 14,988 kilometers from the master, depending on the variance in local conditions. While this gave us good data security against hostile clients connecting from the dark side of the moon, real world testing shows the moon folks are likely to just take over a local staging host and attack that way. So, instead, allow clients sufficient time they should be comfortable able to connect to a master from the moon. We still refuse clients further out, like Mars, since it seems unlikely that Puppet management over that distance should work. We advise the manned Mars expedition to deploy a local Puppet Master to manage infrastructure in their base, and to watch out for the martians. --- lib/puppet/network/http/webrick.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/network/http/webrick.rb b/lib/puppet/network/http/webrick.rb index 54bcf30c2..52aec1bf1 100644 --- a/lib/puppet/network/http/webrick.rb +++ b/lib/puppet/network/http/webrick.rb @@ -40,7 +40,7 @@ class Puppet::Network::HTTP::WEBrick @listening = true @thread = Thread.new { @server.start { |sock| - raise "Client disconnected before connection could be established" unless IO.select([sock],nil,nil,0.1) + raise "Client disconnected before connection could be established" unless IO.select([sock],nil,nil,6.2) sock.accept @server.run(sock) } -- cgit