puppet 0.9.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (182) hide show
  1. data/CHANGELOG +0 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +17 -0
  4. data/README +24 -0
  5. data/Rakefile +294 -0
  6. data/TODO +4 -0
  7. data/bin/cf2puppet +186 -0
  8. data/bin/puppet +176 -0
  9. data/bin/puppetca +213 -0
  10. data/bin/puppetd +246 -0
  11. data/bin/puppetdoc +184 -0
  12. data/bin/puppetmasterd +258 -0
  13. data/examples/code/allatonce +13 -0
  14. data/examples/code/assignments +11 -0
  15. data/examples/code/classing +35 -0
  16. data/examples/code/components +73 -0
  17. data/examples/code/execs +16 -0
  18. data/examples/code/failers/badclassnoparam +10 -0
  19. data/examples/code/failers/badclassparam +10 -0
  20. data/examples/code/failers/badcompnoparam +9 -0
  21. data/examples/code/failers/badcompparam +9 -0
  22. data/examples/code/failers/badtypeparam +3 -0
  23. data/examples/code/file.bl +11 -0
  24. data/examples/code/filedefaults +10 -0
  25. data/examples/code/fileparsing +116 -0
  26. data/examples/code/filerecursion +15 -0
  27. data/examples/code/functions +3 -0
  28. data/examples/code/groups +7 -0
  29. data/examples/code/head +30 -0
  30. data/examples/code/importing +8 -0
  31. data/examples/code/nodes +20 -0
  32. data/examples/code/one +8 -0
  33. data/examples/code/relationships +34 -0
  34. data/examples/code/selectors +28 -0
  35. data/examples/code/simpletests +11 -0
  36. data/examples/code/snippets/argumentdefaults +14 -0
  37. data/examples/code/snippets/casestatement +39 -0
  38. data/examples/code/snippets/classheirarchy.pp +15 -0
  39. data/examples/code/snippets/classincludes.pp +17 -0
  40. data/examples/code/snippets/classpathtest +11 -0
  41. data/examples/code/snippets/dirchmod +19 -0
  42. data/examples/code/snippets/failmissingexecpath.pp +13 -0
  43. data/examples/code/snippets/falsevalues.pp +3 -0
  44. data/examples/code/snippets/filecreate +11 -0
  45. data/examples/code/snippets/implicititeration +15 -0
  46. data/examples/code/snippets/multipleinstances +7 -0
  47. data/examples/code/snippets/namevartest +9 -0
  48. data/examples/code/snippets/scopetest +13 -0
  49. data/examples/code/snippets/selectorvalues.pp +22 -0
  50. data/examples/code/snippets/simpledefaults +5 -0
  51. data/examples/code/snippets/simpleselector +38 -0
  52. data/examples/code/svncommit +13 -0
  53. data/examples/root/bin/sleeper +69 -0
  54. data/examples/root/etc/configfile +0 -0
  55. data/examples/root/etc/debian-passwd +29 -0
  56. data/examples/root/etc/debian-syslog.conf +71 -0
  57. data/examples/root/etc/init.d/sleeper +65 -0
  58. data/examples/root/etc/otherfile +0 -0
  59. data/examples/root/etc/puppet/fileserver.conf +3 -0
  60. data/examples/root/etc/puppet/puppetmasterd.conf +10 -0
  61. data/ext/module:puppet +195 -0
  62. data/install.rb +270 -0
  63. data/lib/puppet.rb +249 -0
  64. data/lib/puppet/base64.rb +19 -0
  65. data/lib/puppet/client.rb +519 -0
  66. data/lib/puppet/config.rb +49 -0
  67. data/lib/puppet/daemon.rb +208 -0
  68. data/lib/puppet/element.rb +71 -0
  69. data/lib/puppet/event.rb +259 -0
  70. data/lib/puppet/log.rb +321 -0
  71. data/lib/puppet/metric.rb +250 -0
  72. data/lib/puppet/parsedfile.rb +38 -0
  73. data/lib/puppet/parser/ast.rb +1560 -0
  74. data/lib/puppet/parser/interpreter.rb +150 -0
  75. data/lib/puppet/parser/lexer.rb +226 -0
  76. data/lib/puppet/parser/parser.rb +1354 -0
  77. data/lib/puppet/parser/scope.rb +755 -0
  78. data/lib/puppet/server.rb +170 -0
  79. data/lib/puppet/server/authstore.rb +227 -0
  80. data/lib/puppet/server/ca.rb +140 -0
  81. data/lib/puppet/server/filebucket.rb +147 -0
  82. data/lib/puppet/server/fileserver.rb +477 -0
  83. data/lib/puppet/server/logger.rb +43 -0
  84. data/lib/puppet/server/master.rb +103 -0
  85. data/lib/puppet/server/servlet.rb +247 -0
  86. data/lib/puppet/sslcertificates.rb +737 -0
  87. data/lib/puppet/statechange.rb +150 -0
  88. data/lib/puppet/storage.rb +95 -0
  89. data/lib/puppet/transaction.rb +179 -0
  90. data/lib/puppet/transportable.rb +151 -0
  91. data/lib/puppet/type.rb +1354 -0
  92. data/lib/puppet/type/component.rb +141 -0
  93. data/lib/puppet/type/cron.rb +543 -0
  94. data/lib/puppet/type/exec.rb +316 -0
  95. data/lib/puppet/type/group.rb +152 -0
  96. data/lib/puppet/type/nameservice.rb +3 -0
  97. data/lib/puppet/type/nameservice/netinfo.rb +173 -0
  98. data/lib/puppet/type/nameservice/objectadd.rb +146 -0
  99. data/lib/puppet/type/nameservice/posix.rb +200 -0
  100. data/lib/puppet/type/package.rb +420 -0
  101. data/lib/puppet/type/package/apt.rb +70 -0
  102. data/lib/puppet/type/package/dpkg.rb +108 -0
  103. data/lib/puppet/type/package/rpm.rb +81 -0
  104. data/lib/puppet/type/package/sun.rb +117 -0
  105. data/lib/puppet/type/package/yum.rb +58 -0
  106. data/lib/puppet/type/pfile.rb +569 -0
  107. data/lib/puppet/type/pfile/checksum.rb +219 -0
  108. data/lib/puppet/type/pfile/create.rb +108 -0
  109. data/lib/puppet/type/pfile/group.rb +129 -0
  110. data/lib/puppet/type/pfile/mode.rb +131 -0
  111. data/lib/puppet/type/pfile/source.rb +264 -0
  112. data/lib/puppet/type/pfile/type.rb +31 -0
  113. data/lib/puppet/type/pfile/uid.rb +166 -0
  114. data/lib/puppet/type/pfilebucket.rb +80 -0
  115. data/lib/puppet/type/pprocess.rb +97 -0
  116. data/lib/puppet/type/service.rb +347 -0
  117. data/lib/puppet/type/service/base.rb +17 -0
  118. data/lib/puppet/type/service/debian.rb +50 -0
  119. data/lib/puppet/type/service/init.rb +145 -0
  120. data/lib/puppet/type/service/smf.rb +29 -0
  121. data/lib/puppet/type/state.rb +182 -0
  122. data/lib/puppet/type/symlink.rb +183 -0
  123. data/lib/puppet/type/tidy.rb +183 -0
  124. data/lib/puppet/type/typegen.rb +149 -0
  125. data/lib/puppet/type/typegen/filerecord.rb +243 -0
  126. data/lib/puppet/type/typegen/filetype.rb +316 -0
  127. data/lib/puppet/type/user.rb +290 -0
  128. data/lib/puppet/util.rb +138 -0
  129. data/test/certmgr/certmgr.rb +265 -0
  130. data/test/client/client.rb +203 -0
  131. data/test/executables/puppetbin.rb +53 -0
  132. data/test/executables/puppetca.rb +79 -0
  133. data/test/executables/puppetd.rb +71 -0
  134. data/test/executables/puppetmasterd.rb +153 -0
  135. data/test/executables/puppetmodule.rb +60 -0
  136. data/test/language/ast.rb +412 -0
  137. data/test/language/interpreter.rb +71 -0
  138. data/test/language/scope.rb +412 -0
  139. data/test/language/snippets.rb +445 -0
  140. data/test/other/events.rb +111 -0
  141. data/test/other/log.rb +195 -0
  142. data/test/other/metrics.rb +92 -0
  143. data/test/other/overrides.rb +115 -0
  144. data/test/other/parsedfile.rb +31 -0
  145. data/test/other/relationships.rb +113 -0
  146. data/test/other/state.rb +106 -0
  147. data/test/other/storage.rb +39 -0
  148. data/test/other/transactions.rb +235 -0
  149. data/test/parser/lexer.rb +120 -0
  150. data/test/parser/parser.rb +180 -0
  151. data/test/puppet/conffiles.rb +104 -0
  152. data/test/puppet/defaults.rb +100 -0
  153. data/test/puppet/error.rb +23 -0
  154. data/test/puppet/utiltest.rb +120 -0
  155. data/test/puppettest.rb +774 -0
  156. data/test/server/authstore.rb +209 -0
  157. data/test/server/bucket.rb +227 -0
  158. data/test/server/ca.rb +201 -0
  159. data/test/server/fileserver.rb +710 -0
  160. data/test/server/logger.rb +175 -0
  161. data/test/server/master.rb +150 -0
  162. data/test/server/server.rb +130 -0
  163. data/test/tagging/tagging.rb +80 -0
  164. data/test/test +51 -0
  165. data/test/types/basic.rb +119 -0
  166. data/test/types/component.rb +272 -0
  167. data/test/types/cron.rb +261 -0
  168. data/test/types/exec.rb +273 -0
  169. data/test/types/file.rb +616 -0
  170. data/test/types/filebucket.rb +167 -0
  171. data/test/types/fileignoresource.rb +287 -0
  172. data/test/types/filesources.rb +587 -0
  173. data/test/types/filetype.rb +162 -0
  174. data/test/types/group.rb +271 -0
  175. data/test/types/package.rb +205 -0
  176. data/test/types/query.rb +101 -0
  177. data/test/types/service.rb +100 -0
  178. data/test/types/symlink.rb +93 -0
  179. data/test/types/tidy.rb +124 -0
  180. data/test/types/type.rb +135 -0
  181. data/test/types/user.rb +371 -0
  182. metadata +243 -0
@@ -0,0 +1,249 @@
1
+ require 'singleton'
2
+ require 'puppet/log'
3
+
4
+ # see the bottom of the file for further inclusions
5
+
6
+ #------------------------------------------------------------
7
+ # the top-level module
8
+ #
9
+ # all this really does is dictate how the whole system behaves, through
10
+ # preferences for things like debugging
11
+ #
12
+ # it's also a place to find top-level commands like 'debug'
13
+ module Puppet
14
+ PUPPETVERSION="0.9.1"
15
+
16
+ def Puppet.version
17
+ return PUPPETVERSION
18
+ end
19
+
20
+ class Error < RuntimeError
21
+ attr_accessor :stack, :line, :file
22
+ def initialize(message)
23
+ @message = message
24
+
25
+ @stack = caller
26
+ end
27
+
28
+ def to_s
29
+ str = nil
30
+ if defined? @file and defined? @line and @file and @line
31
+ str = "%s in file %s at line %s" %
32
+ [@message.to_s, @file, @line]
33
+ elsif defined? @line and @line
34
+ str = "%s at line %s" %
35
+ [@message.to_s, @line]
36
+ else
37
+ str = @message.to_s
38
+ end
39
+
40
+ #if Puppet[:debug] and @stack
41
+ # str += @stack.to_s
42
+ #end
43
+
44
+ return str
45
+ end
46
+ end
47
+
48
+ class DevError < Error; end
49
+
50
+ # the hash that determines how our system behaves
51
+ @@config = Hash.new(false)
52
+
53
+ # define helper messages for each of the message levels
54
+ Puppet::Log.eachlevel { |level|
55
+ define_method(level,proc { |args|
56
+ if args.is_a?(Array)
57
+ args = args.join(" ")
58
+ end
59
+ Puppet::Log.create(
60
+ :level => level,
61
+ :message => args
62
+ )
63
+ })
64
+ module_function level
65
+ }
66
+
67
+ # I keep wanting to use Puppet.error
68
+ # XXX this isn't actually working right now
69
+ alias :error :err
70
+
71
+ @defaults = {
72
+ :rrddir => [:puppetvar, "rrd"],
73
+ :logdir => [:puppetvar, "log"],
74
+ :bucketdir => [:puppetvar, "bucket"],
75
+ :statedir => [:puppetvar, "state"],
76
+
77
+ # then the files},
78
+ :manifestdir => [:puppetconf, "manifests"],
79
+ :manifest => [:manifestdir, "site.pp"],
80
+ :localconfig => [:puppetconf, "localconfig.ma"],
81
+ :logfile => [:logdir, "puppet.log"],
82
+ :httplogfile => [:logdir, "http.log"],
83
+ :masterlog => [:logdir, "puppetmaster.log"],
84
+ :masterhttplog => [:logdir, "masterhttp.log"],
85
+ :checksumfile => [:statedir, "checksums"],
86
+ :ssldir => [:puppetconf, "ssl"],
87
+
88
+ # and finally the simple answers,
89
+ :server => "puppet",
90
+ :rrdgraph => false,
91
+ :noop => false,
92
+ :parseonly => false,
93
+ :puppetport => 8139,
94
+ :masterport => 8140,
95
+ }
96
+ if Process.uid == 0
97
+ @defaults[:puppetconf] = "/etc/puppet"
98
+ @defaults[:puppetvar] = "/var/puppet"
99
+ else
100
+ @defaults[:puppetconf] = File.expand_path("~/.puppet")
101
+ @defaults[:puppetvar] = File.expand_path("~/.puppet/var")
102
+ end
103
+
104
+ def self.clear
105
+ @@config = Hash.new(false)
106
+ end
107
+
108
+ # configuration parameter access and stuff
109
+ def self.[](param)
110
+ if param.is_a?(String)
111
+ param = param.intern
112
+ elsif ! param.is_a?(Symbol)
113
+ raise ArgumentError, "Invalid parameter type %s" % param.class
114
+ end
115
+ case param
116
+ when :debug:
117
+ if Puppet::Log.level == :debug
118
+ return true
119
+ else
120
+ return false
121
+ end
122
+ when :loglevel:
123
+ return Puppet::Log.level
124
+ else
125
+ # allow manual override
126
+ if @@config.include?(param)
127
+ return @@config[param]
128
+ else
129
+ if @defaults.include?(param)
130
+ default = @defaults[param]
131
+ if default.is_a?(Proc)
132
+ return default.call()
133
+ elsif default.is_a?(Array)
134
+ return File.join(self[default[0]], default[1])
135
+ else
136
+ return default
137
+ end
138
+ else
139
+ raise ArgumentError, "Invalid parameter %s" % param
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ # configuration parameter access and stuff
146
+ def self.[]=(param,value)
147
+ case param
148
+ when :debug:
149
+ if value
150
+ Puppet::Log.level=(:debug)
151
+ else
152
+ Puppet::Log.level=(:notice)
153
+ end
154
+ when :loglevel:
155
+ Puppet::Log.level=(value)
156
+ when :logdest:
157
+ Puppet::Log.newdestination(value)
158
+ else
159
+ @@config[param] = value
160
+ end
161
+ end
162
+
163
+ def self.asuser(user)
164
+ # FIXME this should use our user object, since it already knows how
165
+ # to find users and such
166
+ require 'etc'
167
+
168
+ begin
169
+ obj = Etc.getpwnam(user)
170
+ rescue ArgumentError
171
+ raise Puppet::Error, "User %s not found"
172
+ end
173
+
174
+ uid = obj.uid
175
+
176
+ olduid = nil
177
+ if Process.uid != uid
178
+ olduid = Process.uid
179
+ Process.euid = uid
180
+ end
181
+
182
+ retval = yield
183
+
184
+
185
+ if olduid
186
+ Process.euid = olduid
187
+ end
188
+
189
+ return retval
190
+ end
191
+
192
+ def self.setdefault(param,value)
193
+ if value.is_a?(Array)
194
+ if value[0].is_a?(Symbol)
195
+ unless @defaults.include?(value[0])
196
+ raise ArgumentError, "Unknown basedir %s for param %s" %
197
+ [value[0], param]
198
+ end
199
+ else
200
+ raise ArgumentError, "Invalid default %s for param %s" %
201
+ [value.inspect, param]
202
+ end
203
+
204
+ unless value[1].is_a?(String)
205
+ raise ArgumentError, "Invalid default %s for param %s" %
206
+ [value.inspect, param]
207
+ end
208
+
209
+ unless value.length == 2
210
+ raise ArgumentError, "Invalid default %s for param %s" %
211
+ [value.inspect, param]
212
+ end
213
+
214
+ @defaults[param] = value
215
+ else
216
+ @defaults[param] = value
217
+ end
218
+ end
219
+
220
+ # XXX this should all be done using puppet objects, not using
221
+ # normal mkdir
222
+ def self.recmkdir(dir,mode = 0755)
223
+ if FileTest.exist?(dir)
224
+ return false
225
+ else
226
+ tmp = dir.sub(/^\//,'')
227
+ path = [File::SEPARATOR]
228
+ tmp.split(File::SEPARATOR).each { |dir|
229
+ path.push dir
230
+ if ! FileTest.exist?(File.join(path))
231
+ Dir.mkdir(File.join(path), mode)
232
+ elsif FileTest.directory?(File.join(path))
233
+ next
234
+ else FileTest.exist?(File.join(path))
235
+ raise "Cannot create %s: basedir %s is a file" %
236
+ [dir, File.join(path)]
237
+ end
238
+ }
239
+ return true
240
+ end
241
+ end
242
+ end
243
+
244
+ require 'puppet/util'
245
+ require 'puppet/server'
246
+ require 'puppet/type'
247
+ require 'puppet/storage'
248
+
249
+ # $Id$
@@ -0,0 +1,19 @@
1
+ # a stupid hack class to get rid of all of the warnings but
2
+ # still make the encode/decode methods available
3
+
4
+ # 1.8.2 has a Base64 class, but 1.8.1 just imports the methods directly
5
+ # into Object
6
+
7
+ require 'base64'
8
+
9
+ unless defined? Base64
10
+ class Base64
11
+ def Base64.encode64(*args)
12
+ Object.method(:encode64).call(*args)
13
+ end
14
+
15
+ def Base64.decode64(*args)
16
+ Object.method(:decode64).call(*args)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,519 @@
1
+ # the available clients
2
+
3
+ require 'puppet'
4
+ require 'puppet/sslcertificates'
5
+ require 'puppet/type'
6
+ require 'facter'
7
+ require 'openssl'
8
+ require 'puppet/transaction'
9
+ require 'puppet/transportable'
10
+ require 'puppet/metric'
11
+ require 'puppet/daemon'
12
+ require 'puppet/server'
13
+ require 'puppet/base64'
14
+
15
+ $noclientnetworking = false
16
+ begin
17
+ require 'webrick'
18
+ require 'cgi'
19
+ require 'xmlrpc/client'
20
+ require 'xmlrpc/server'
21
+ rescue LoadError => detail
22
+ $noclientnetworking = detail
23
+ end
24
+
25
+ module Puppet
26
+ class NetworkClientError < RuntimeError; end
27
+ class ClientError < RuntimeError; end
28
+ #---------------------------------------------------------------
29
+ if $noclientnetworking
30
+ Puppet.err "Could not load client network libs: %s" % $noclientnetworking
31
+ else
32
+ class NetworkClient < XMLRPC::Client
33
+ #include Puppet::Daemon
34
+
35
+ # add the methods associated with each namespace
36
+ Puppet::Server::Handler.each { |handler|
37
+ interface = handler.interface
38
+ namespace = interface.prefix
39
+
40
+ interface.methods.each { |ary|
41
+ method = ary[0]
42
+ Puppet.info "Defining %s.%s" % [namespace, method]
43
+ self.send(:define_method,method) { |*args|
44
+ #Puppet.info "Calling %s" % method
45
+ #Puppet.info "peer cert is %s" % @http.peer_cert
46
+ #Puppet.info "cert is %s" % @http.cert
47
+ begin
48
+ call("%s.%s" % [namespace, method.to_s],*args)
49
+ rescue OpenSSL::SSL::SSLError => detail
50
+ #Puppet.err "Could not call %s.%s: Untrusted certificates" %
51
+ # [namespace, method]
52
+ raise NetworkClientError,
53
+ "Certificates were not trusted"
54
+ rescue XMLRPC::FaultException => detail
55
+ #Puppet.err "Could not call %s.%s: %s" %
56
+ # [namespace, method, detail.faultString]
57
+ #raise NetworkClientError,
58
+ # "XMLRPC Error: %s" % detail.faultString
59
+ raise NetworkClientError, detail.faultString
60
+ rescue Errno::ECONNREFUSED => detail
61
+ msg = "Could not connect to %s on port %s" % [@host, @port]
62
+ #Puppet.err msg
63
+ raise NetworkClientError, msg
64
+ rescue SocketError => detail
65
+ Puppet.err "Could not find server %s" % @puppetserver
66
+ exit(12)
67
+ rescue => detail
68
+ Puppet.err "Could not call %s.%s: %s" %
69
+ [namespace, method, detail.inspect]
70
+ #raise NetworkClientError.new(detail.to_s)
71
+ raise
72
+ end
73
+ }
74
+ }
75
+ }
76
+
77
+ def ca_file=(cafile)
78
+ @http.ca_file = cafile
79
+ store = OpenSSL::X509::Store.new
80
+ cacert = OpenSSL::X509::Certificate.new(
81
+ File.read(cafile)
82
+ )
83
+ store.add_cert(cacert)
84
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
85
+ @http.cert_store = store
86
+ end
87
+
88
+ def cert=(cert)
89
+ #Puppet.debug "Adding certificate"
90
+ @http.cert = cert
91
+ @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
92
+ end
93
+
94
+ def key=(key)
95
+ @http.key = key
96
+ end
97
+
98
+ def initialize(hash)
99
+ hash[:Path] ||= "/RPC2"
100
+ hash[:Server] ||= "localhost"
101
+ hash[:Port] ||= Puppet[:masterport]
102
+ Puppet.debug "Creating client for %s" % hash[:Server]
103
+
104
+ @puppetserver = hash[:Server]
105
+
106
+ super(
107
+ hash[:Server],
108
+ hash[:Path],
109
+ hash[:Port],
110
+ nil, # proxy_host
111
+ nil, # proxy_port
112
+ nil, # user
113
+ nil, # password
114
+ true # use_ssl
115
+ )
116
+
117
+ if hash[:Certificate]
118
+ self.cert = hash[:Certificate]
119
+ else
120
+ Puppet.err "No certificate; running with reduced functionality."
121
+ end
122
+
123
+ if hash[:Key]
124
+ self.key = hash[:Key]
125
+ end
126
+
127
+ if hash[:CAFile]
128
+ self.ca_file = hash[:CAFile]
129
+ end
130
+
131
+ # from here, i need to add the key, cert, and ca cert
132
+ # and reorgize how i start the client
133
+ end
134
+
135
+ def local
136
+ false
137
+ end
138
+ end
139
+ end
140
+
141
+ # FIXME this still isn't a good design, because none of the handlers overlap
142
+ # so i could just as easily include them all in the main module
143
+ # but at least it's better organized for now
144
+ class Client
145
+ include Puppet
146
+
147
+ # FIXME the cert stuff should only come up with networking, so it
148
+ # should be in the network client, not the normal client
149
+ # but if i do that, it's hard to tell whether the certs have been initialized
150
+ include Puppet::Daemon
151
+ attr_reader :local, :secureinit
152
+
153
+ class << self
154
+ attr_reader :drivername
155
+ end
156
+
157
+ def initcerts
158
+ unless self.readcert
159
+ unless self.requestcert
160
+ return nil
161
+ end
162
+ end
163
+
164
+ # unless we have a driver, we're a local client and we can't add
165
+ # certs anyway, so it doesn't matter
166
+ unless @driver
167
+ return true
168
+ end
169
+
170
+ self.setcerts
171
+ end
172
+
173
+ def initialize(hash)
174
+ # to whom do we connect?
175
+ @server = nil
176
+ @nil = nil
177
+ @secureinit = hash[:NoSecureInit] || true
178
+
179
+ if hash.include?(:FQDN)
180
+ @fqdn = hash[:FQDN]
181
+ else
182
+ self.fqdn
183
+ end
184
+
185
+ if hash.include?(:Cache)
186
+ @cache = hash[:Cache]
187
+ else
188
+ @cache = true
189
+ end
190
+
191
+ driverparam = self.class.drivername
192
+ if hash.include?(:Server)
193
+ if $noclientnetworking
194
+ raise NetworkClientError.new("Networking not available: %s" %
195
+ $nonetworking)
196
+ end
197
+
198
+ args = {:Server => hash[:Server]}
199
+ args[:Port] = hash[:Port] || Puppet[:masterport]
200
+
201
+ if self.readcert
202
+ args[:Certificate] = @cert
203
+ args[:Key] = @key
204
+ args[:CAFile] = @cacertfile
205
+ end
206
+
207
+ @driver = Puppet::NetworkClient.new(args)
208
+ @local = false
209
+ elsif hash.include?(driverparam)
210
+ @driver = hash[driverparam]
211
+ @local = true
212
+ else
213
+ raise ClientError, "%s must be passed a Server or %s" %
214
+ [self.class, driverparam]
215
+ end
216
+ end
217
+
218
+ def setcerts
219
+ @driver.cert = @cert
220
+ @driver.key = @key
221
+ @driver.ca_file = @cacertfile
222
+ end
223
+
224
+ class MasterClient < Puppet::Client
225
+ @drivername = :Master
226
+
227
+ def self.facts
228
+ facts = {}
229
+ Facter.each { |name,fact|
230
+ facts[name] = fact.downcase
231
+ }
232
+
233
+ facts
234
+ end
235
+
236
+ # this method is how the client receives the tree of Transportable
237
+ # objects
238
+ # for now, just descend into the tree and perform and necessary
239
+ # manipulations
240
+ def apply
241
+ unless defined? @objects
242
+ raise Puppet::Error, "Cannot apply; objects not defined"
243
+ end
244
+
245
+ begin
246
+ Puppet::Storage.init
247
+ Puppet::Storage.load
248
+ rescue => detail
249
+ Puppet.err "Corrupt state file %s" % Puppet[:checksumfile]
250
+ begin
251
+ File.unlink(Puppet[:checksumfile])
252
+ retry
253
+ rescue => detail
254
+ raise Puppet::Error.new("Cannot remove %s: %s" %
255
+ [Puppet[statefile], detail])
256
+ end
257
+ end
258
+
259
+ # FIXME this should be in getconfig, not apply
260
+ container = @objects.to_type
261
+ #if @local
262
+ # container = @objects.to_type
263
+ #else
264
+ # container = Marshal::load(@objects).to_type
265
+ #end
266
+
267
+ # this is a gross hack... but i don't see a good way around it
268
+ # set all of the variables to empty
269
+ Puppet::Transaction.init
270
+
271
+ # for now we just evaluate the top-level container, but eventually
272
+ # there will be schedules and such associated with each object,
273
+ # and probably with the container itself
274
+ transaction = container.evaluate
275
+ #transaction = Puppet::Transaction.new(objects)
276
+ transaction.toplevel = true
277
+ begin
278
+ transaction.evaluate
279
+ rescue Puppet::Error => detail
280
+ Puppet.err "Could not apply complete configuration: %s" %
281
+ detail
282
+ rescue => detail
283
+ Puppet.err "Found a bug: %s" % detail
284
+ end
285
+ Puppet::Metric.gather
286
+ Puppet::Metric.tally
287
+ if Puppet[:rrdgraph] == true
288
+ Metric.store
289
+ Metric.graph
290
+ end
291
+ Puppet::Storage.store
292
+
293
+ return transaction
294
+ end
295
+
296
+ def getconfig
297
+ #client.loadproperty('files/sslclient.properties')
298
+ Puppet.debug("getting config")
299
+
300
+ facts = self.class.facts
301
+
302
+ unless facts.length > 0
303
+ raise Puppet::ClientError.new(
304
+ "Could not retrieve any facts"
305
+ )
306
+ end
307
+
308
+ objects = nil
309
+ if @local
310
+ objects = @driver.getconfig(facts)
311
+
312
+ if objects == ""
313
+ raise Puppet::Error, "Could not retrieve configuration"
314
+ end
315
+ else
316
+ textfacts = CGI.escape(Marshal::dump(facts))
317
+
318
+ # error handling for this is done in the network client
319
+ textobjects = @driver.getconfig(textfacts)
320
+
321
+ unless textobjects == ""
322
+ begin
323
+ textobjects = CGI.unescape(textobjects)
324
+ rescue => detail
325
+ raise Puppet::Error, "Could not CGI.unescape configuration"
326
+ end
327
+ end
328
+
329
+ if @cache
330
+ if textobjects == ""
331
+ if FileTest.exists?(Puppet[:localconfig])
332
+ textobjects = File.read(Puppet[:localconfig])
333
+ else
334
+ raise Puppet::Error.new(
335
+ "Cannot connect to server and there is no cached configuration"
336
+ )
337
+ end
338
+ else
339
+ # we store the config so that if we can't connect next time, we
340
+ # can just run against the most recently acquired copy
341
+ confdir = File.dirname(Puppet[:localconfig])
342
+ unless FileTest.exists?(confdir)
343
+ Puppet.recmkdir(confdir, 0770)
344
+ end
345
+ File.open(Puppet[:localconfig], "w", 0660) { |f|
346
+ f.print textobjects
347
+ }
348
+ end
349
+ elsif textobjects == ""
350
+ raise Puppet::Error, "Could not retrieve configuration"
351
+ end
352
+
353
+ begin
354
+ objects = Marshal::load(textobjects)
355
+ rescue => detail
356
+ raise Puppet::Error.new("Could not understand configuration")
357
+ end
358
+ end
359
+ if objects.is_a?(Puppet::TransBucket)
360
+ @objects = objects
361
+ else
362
+ raise NetworkClientError,
363
+ "Invalid returned objects of type %s" % objects.class
364
+ end
365
+ end
366
+ end
367
+
368
+ class Dipper < Puppet::Client
369
+ @drivername = :Bucket
370
+
371
+ def initialize(hash = {})
372
+ if hash.include?(:Path)
373
+ bucket = Puppet::Server::FileBucket.new(
374
+ :Bucket => hash[:Path]
375
+ )
376
+ hash.delete(:Path)
377
+ hash[:Bucket] = bucket
378
+ end
379
+
380
+ super(hash)
381
+ end
382
+
383
+ def backup(file)
384
+ unless FileTest.exists?(file)
385
+ raise(BucketError, "File %s does not exist" % file, caller)
386
+ end
387
+ contents = File.open(file) { |of| of.read }
388
+
389
+ string = Base64.encode64(contents)
390
+ #puts "string is created"
391
+
392
+ sum = @driver.addfile(string,file)
393
+ #puts "file %s is added" % file
394
+ return sum
395
+ end
396
+
397
+ def restore(file,sum)
398
+ restore = true
399
+ if FileTest.exists?(file)
400
+ contents = File.open(file) { |of| of.read }
401
+
402
+ cursum = Digest::MD5.hexdigest(contents)
403
+
404
+ # if the checksum has changed...
405
+ # this might be extra effort
406
+ if cursum == sum
407
+ restore = false
408
+ end
409
+ end
410
+
411
+ if restore
412
+ #puts "Restoring %s" % file
413
+ if tmp = @driver.getfile(sum)
414
+ newcontents = Base64.decode64(tmp)
415
+ newsum = Digest::MD5.hexdigest(newcontents)
416
+ File.open(file,File::WRONLY|File::TRUNC) { |of|
417
+ of.print(newcontents)
418
+ }
419
+ else
420
+ Puppet.err "Could not find file with checksum %s" % sum
421
+ return nil
422
+ end
423
+ #puts "Done"
424
+ return newsum
425
+ else
426
+ return nil
427
+ end
428
+
429
+ end
430
+ end
431
+
432
+ # unlike the other client classes (again, this design sucks) this class
433
+ # is basically just a proxy class -- it calls its methods on the driver
434
+ # and that's about it
435
+ class ProxyClient < Puppet::Client
436
+ def self.mkmethods
437
+ interface = @handler.interface
438
+ namespace = interface.prefix
439
+
440
+ interface.methods.each { |ary|
441
+ method = ary[0]
442
+ Puppet.debug "%s: defining %s.%s" % [self, namespace, method]
443
+ self.send(:define_method,method) { |*args|
444
+ begin
445
+ @driver.send(method, *args)
446
+ rescue XMLRPC::FaultException => detail
447
+ #Puppet.err "Could not call %s.%s: %s" %
448
+ # [namespace, method, detail.faultString]
449
+ #raise NetworkClientError,
450
+ # "XMLRPC Error: %s" % detail.faultString
451
+ raise NetworkClientError, detail.faultString
452
+ end
453
+ }
454
+ }
455
+ end
456
+ end
457
+
458
+ class FileClient < Puppet::Client::ProxyClient
459
+ @drivername = :FileServer
460
+
461
+ # set up the appropriate interface methods
462
+ @handler = Puppet::Server::FileServer
463
+
464
+ self.mkmethods
465
+
466
+ def initialize(hash = {})
467
+ if hash.include?(:FileServer)
468
+ unless hash[:FileServer].is_a?(Puppet::Server::FileServer)
469
+ raise Puppet::DevError, "Must pass an actual FS object"
470
+ end
471
+ end
472
+
473
+ super(hash)
474
+ end
475
+ end
476
+
477
+ class CAClient < Puppet::Client::ProxyClient
478
+ @drivername = :CA
479
+
480
+ # set up the appropriate interface methods
481
+ @handler = Puppet::Server::CA
482
+ self.mkmethods
483
+
484
+ def initialize(hash = {})
485
+ if hash.include?(:CA)
486
+ hash[:CA] = Puppet::Server::CA.new()
487
+ end
488
+
489
+ super(hash)
490
+ end
491
+ end
492
+
493
+ class LogClient < Puppet::Client::ProxyClient
494
+ @drivername = :Logger
495
+
496
+ # set up the appropriate interface methods
497
+ @handler = Puppet::Server::Logger
498
+ self.mkmethods
499
+
500
+ def initialize(hash = {})
501
+ if hash.include?(:Logger)
502
+ hash[:Logger] = Puppet::Server::Logger.new()
503
+ end
504
+
505
+ super(hash)
506
+ end
507
+ end
508
+
509
+ class StatusClient < Puppet::Client::ProxyClient
510
+ # set up the appropriate interface methods
511
+ @handler = Puppet::Server::ServerStatus
512
+ self.mkmethods
513
+ end
514
+
515
+ end
516
+ #---------------------------------------------------------------
517
+ end
518
+
519
+ # $Id: client.rb 740 2005-11-01 20:22:19Z luke $