Renaming 'configuration' to 'catalog', fixing #954.
[vinpup.git] / lib / puppet / network / handler / resource.rb
blobf2a33975140928b0a5175b2f5171bc2dba939177
1 require 'puppet'
2 require 'puppet/network/handler'
4 # Serve Puppet elements.  Useful for querying, copying, and, um, other stuff.
5 class Puppet::Network::Handler
6     class Resource < Handler
7         desc "An interface for interacting with client-based resources that can
8         be used for querying or managing remote machines without using Puppet's
9         central server tools.
10         
11         The ``describe`` and ``list`` methods return TransBuckets containing
12         TransObject instances (``describe`` returns a single TransBucket),
13         and the ``apply`` method accepts a TransBucket of TransObjects and
14         applies them locally.
15         "
17         attr_accessor :local
19         @interface = XMLRPC::Service::Interface.new("resource") { |iface|
20             iface.add_method("string apply(string, string)")
21             iface.add_method("string describe(string, string, array, array)")
22             iface.add_method("string list(string, array, string)")
23         }
25         side :client
27         # Apply a TransBucket as a transaction.
28         def apply(bucket, format = "yaml", client = nil, clientip = nil)
29             unless local?
30                 begin
31                     case format
32                     when "yaml":
33                         bucket = YAML::load(Base64.decode64(bucket))
34                     else
35                         raise Puppet::Error, "Unsupported format '%s'" % format
36                     end
37                 rescue => detail
38                     raise Puppet::Error, "Could not load YAML TransBucket: %s" % detail
39                 end
40             end
42             catalog = bucket.to_catalog
44             # And then apply the catalog.  This way we're reusing all
45             # the code in there.  It should probably just be separated out, though.
46             transaction = catalog.apply
47             
48             # And then clean up
49             catalog.clear(true)
51             # It'd be nice to return some kind of report, but... at this point
52             # we have no such facility.
53             return "success"
54         end
56         # Describe a given object.  This returns the 'is' values for every property
57         # available on the object type.
58         def describe(type, name, retrieve = nil, ignore = [], format = "yaml", client = nil, clientip = nil)
59             Puppet.info "Describing %s[%s]" % [type.to_s.capitalize, name]
60             @local = true unless client
61             typeklass = nil
62             unless typeklass = Puppet.type(type)
63                 raise Puppet::Error, "Puppet type %s is unsupported" % type
64             end
66             obj = nil
68             retrieve ||= :all
69             ignore ||= []
71             if obj = typeklass[name]
72                 obj[:check] = retrieve
73             else
74                 begin
75                     obj = typeklass.create(:name => name, :check => retrieve)
76                 rescue Puppet::Error => detail
77                     raise Puppet::Error, "%s[%s] could not be created: %s" %
78                         [type, name, detail]
79                 end
80             end
82             unless obj
83                 raise XMLRPC::FaultException.new(
84                     1, "Could not create %s[%s]" % [type, name]
85                 )
86             end
88             trans = obj.to_trans
90             # Now get rid of any attributes they specifically don't want
91             ignore.each do |st|
92                 if trans.include? st
93                     trans.delete(st)
94                 end
95             end
97             # And get rid of any attributes that are nil
98             trans.each do |attr, value|
99                 if value.nil?
100                     trans.delete(attr)
101                 end
102             end
104             unless @local
105                 case format
106                 when "yaml":
107                     trans = Base64.encode64(YAML::dump(trans))
108                 else
109                     raise XMLRPC::FaultException.new(
110                         1, "Unavailable config format %s" % format
111                     )
112                 end
113             end
115             return trans
116         end
118         # Create a new fileserving module.
119         def initialize(hash = {})
120             if hash[:Local]
121                 @local = hash[:Local]
122             else
123                 @local = false
124             end
125         end
127         # List all of the elements of a given type.
128         def list(type, ignore = [], base = nil, format = "yaml", client = nil, clientip = nil)
129             @local = true unless client
130             typeklass = nil
131             unless typeklass = Puppet.type(type)
132                 raise Puppet::Error, "Puppet type %s is unsupported" % type
133             end
135             # They can pass in false
136             ignore ||= []
137             ignore = [ignore] unless ignore.is_a? Array
138             bucket = Puppet::TransBucket.new
139             bucket.type = typeklass.name
141             typeklass.instances.each do |obj|
142                 next if ignore.include? obj.name
144                 #object = Puppet::TransObject.new(obj.name, typeklass.name)
145                 bucket << obj.to_trans
146             end
148             unless @local
149                 case format
150                 when "yaml":
151                     begin
152                     bucket = Base64.encode64(YAML::dump(bucket))
153                     rescue => detail
154                         Puppet.err detail
155                         raise XMLRPC::FaultException.new(
156                             1, detail.to_s
157                         )
158                     end
159                 else
160                     raise XMLRPC::FaultException.new(
161                         1, "Unavailable config format %s" % format
162                     )
163                 end
164             end
166             return bucket
167         end
169         private
171         def authcheck(file, mount, client, clientip)
172             unless mount.allowed?(client, clientip)
173                 mount.warning "%s cannot access %s" %
174                     [client, file]
175                 raise Puppet::AuthorizationError, "Cannot access %s" % mount
176             end
177         end
179         # Deal with ignore parameters.
180         def handleignore(children, path, ignore)            
181             ignore.each { |ignore|                
182                 Dir.glob(File.join(path,ignore), File::FNM_DOTMATCH) { |match|
183                     children.delete(File.basename(match))
184                 }                
185             }
186             return children
187         end  
189         def to_s
190             "resource"
191         end
192     end