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/interface/action.rb | 1 + lib/puppet/interface/face_collection.rb | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'lib/puppet/interface') 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/interface') 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/interface') 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