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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
require 'puppet'
require 'puppet/util/classgen'
# Methods dealing with Type management. This module gets included into the
# Puppet::Type class, it's just split out here for clarity.
module Puppet::MetaType
module Manager
include Puppet::Util::ClassGen
# remove all type instances; this is mostly only useful for testing
def allclear
@types.each { |name, type|
type.clear
}
end
# iterate across all of the subclasses of Type
def eachtype
@types.each do |name, type|
# Only consider types that have names
#if ! type.parameters.empty? or ! type.validproperties.empty?
yield type
#end
end
end
# Load all types. Only currently used for documentation.
def loadall
typeloader.loadall
end
# Define a new type.
def newtype(name, options = {}, &block)
# Handle backward compatibility
unless options.is_a?(Hash)
Puppet.warning "Puppet::Type.newtype(#{name}) now expects a hash as the second argument, not #{options.inspect}"
options = {:parent => options}
end
# First make sure we don't have a method sitting around
name = symbolize(name)
newmethod = "new#{name.to_s}"
# Used for method manipulation.
selfobj = singleton_class()
@types ||= {}
if @types.include?(name)
if self.respond_to?(newmethod)
# Remove the old newmethod
selfobj.send(:remove_method,newmethod)
end
end
options = symbolize_options(options)
if parent = options[:parent]
options.delete(:parent)
end
# Then create the class.
klass = genclass(
name,
:parent => (parent || Puppet::Type),
:overwrite => true,
:hash => @types,
:attributes => options,
&block
)
# Now define a "new<type>" method for convenience.
if self.respond_to? newmethod
# Refuse to overwrite existing methods like 'newparam' or 'newtype'.
Puppet.warning "'new#{name.to_s}' method already exists; skipping"
else
selfobj.send(:define_method, newmethod) do |*args|
klass.new(*args)
end
end
# If they've got all the necessary methods defined and they haven't
# already added the property, then do so now.
klass.ensurable if klass.ensurable? and ! klass.validproperty?(:ensure)
# Now set up autoload any providers that might exist for this type.
klass.providerloader = Puppet::Util::Autoload.new(
klass,
"puppet/provider/#{klass.name.to_s}"
)
# We have to load everything so that we can figure out the default type.
klass.providerloader.loadall()
klass
end
# Remove an existing defined type. Largely used for testing.
def rmtype(name)
# Then create the class.
klass = rmclass(
name,
:hash => @types
)
singleton_class.send(:remove_method, "new#{name}") if respond_to?("new#{name}")
end
# Return a Type instance by name.
def type(name)
@types ||= {}
name = name.to_s.downcase.to_sym
if t = @types[name]
return t
else
if typeloader.load(name)
Puppet.warning "Loaded puppet/type/#{name} but no class was created" unless @types.include? name
end
return @types[name]
end
end
# Create a loader for Puppet types.
def typeloader
unless defined?(@typeloader)
@typeloader = Puppet::Util::Autoload.new(
self,
"puppet/type", :wrap => false
)
end
@typeloader
end
end
end
|