1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
require 'puppet'
require 'puppet/util/autoload'
class Puppet::Interface
require 'puppet/interface/action_manager'
include Puppet::Interface::ActionManager
extend Puppet::Interface::ActionManager
# This is just so we can search for actions. We only use its
# list of directories to search.
def self.autoloader
@autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface")
end
def self.interfaces
unless @loaded
@loaded = true
$LOAD_PATH.each do |dir|
next unless FileTest.directory?(dir)
Dir.chdir(dir) do
Dir.glob("puppet/interface/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file|
iname = file.sub(/\.rb/, '')
begin
require iname
rescue Exception => detail
puts detail.backtrace if Puppet[:trace]
raise "Could not load #{iname} from #{dir}/#{file}: #{detail}"
end
end
end
end
end
@interfaces.keys
end
# Return an interface by name, loading from disk if necessary.
def self.interface(name)
@interfaces ||= {}
unless @interfaces[unify_name(name)]
require "puppet/interface/#{unify_name(name)}"
end
@interfaces[unify_name(name)]
rescue Exception => detail
puts detail.backtrace if Puppet[:trace]
$stderr.puts "Unable to find interface '#{name.to_s}': #{detail}."
end
def self.register_interface(name, instance)
@interfaces ||= {}
@interfaces[unify_name(name)] = instance
const_set(name2const(name), instance)
end
def self.unload_interface(name)
@interfaces ||= {}
@interfaces.delete(unify_name(name))
const = name2const(name)
const_get(const)
remove_const(const)
rescue
# nothing - if the constant-getting fails, just return
end
def self.unify_name(name)
name.to_s.downcase.to_sym
end
def self.name2const(name)
name.to_s.capitalize
end
attr_accessor :default_format
def set_default_format(format)
self.default_format = format.to_sym
end
# Return the interface name.
def name
@name || self.to_s.sub(/.+::/, '').downcase
end
attr_accessor :type, :verb, :name, :arguments, :options
def initialize(name, options = {}, &block)
@name = name
@default_format = :pson
options.each { |opt, val| send(opt.to_s + "=", val) }
# We have to register before loading actions,
# since the actions require the registration
# Use the full class name, so this works with
# subclasses.
Puppet::Interface.register_interface(name, self)
load_actions
if block_given?
instance_eval(&block)
end
end
# Try to find actions defined in other files.
def load_actions
path = "puppet/interface/#{name}"
loaded = []
self.class.autoloader.search_directories.each do |dir|
fdir = ::File.join(dir, path)
next unless FileTest.directory?(fdir)
Dir.chdir(fdir) do
Dir.glob("*.rb").each do |file|
aname = file.sub(/\.rb/, '')
if loaded.include?(aname)
Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'"
next
end
loaded << aname
Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'"
require "#{path}/#{aname}"
end
end
end
end
def to_s
name.to_s
end
end
|