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.
- data/CHANGELOG +0 -0
- data/COPYING +340 -0
- data/LICENSE +17 -0
- data/README +24 -0
- data/Rakefile +294 -0
- data/TODO +4 -0
- data/bin/cf2puppet +186 -0
- data/bin/puppet +176 -0
- data/bin/puppetca +213 -0
- data/bin/puppetd +246 -0
- data/bin/puppetdoc +184 -0
- data/bin/puppetmasterd +258 -0
- data/examples/code/allatonce +13 -0
- data/examples/code/assignments +11 -0
- data/examples/code/classing +35 -0
- data/examples/code/components +73 -0
- data/examples/code/execs +16 -0
- data/examples/code/failers/badclassnoparam +10 -0
- data/examples/code/failers/badclassparam +10 -0
- data/examples/code/failers/badcompnoparam +9 -0
- data/examples/code/failers/badcompparam +9 -0
- data/examples/code/failers/badtypeparam +3 -0
- data/examples/code/file.bl +11 -0
- data/examples/code/filedefaults +10 -0
- data/examples/code/fileparsing +116 -0
- data/examples/code/filerecursion +15 -0
- data/examples/code/functions +3 -0
- data/examples/code/groups +7 -0
- data/examples/code/head +30 -0
- data/examples/code/importing +8 -0
- data/examples/code/nodes +20 -0
- data/examples/code/one +8 -0
- data/examples/code/relationships +34 -0
- data/examples/code/selectors +28 -0
- data/examples/code/simpletests +11 -0
- data/examples/code/snippets/argumentdefaults +14 -0
- data/examples/code/snippets/casestatement +39 -0
- data/examples/code/snippets/classheirarchy.pp +15 -0
- data/examples/code/snippets/classincludes.pp +17 -0
- data/examples/code/snippets/classpathtest +11 -0
- data/examples/code/snippets/dirchmod +19 -0
- data/examples/code/snippets/failmissingexecpath.pp +13 -0
- data/examples/code/snippets/falsevalues.pp +3 -0
- data/examples/code/snippets/filecreate +11 -0
- data/examples/code/snippets/implicititeration +15 -0
- data/examples/code/snippets/multipleinstances +7 -0
- data/examples/code/snippets/namevartest +9 -0
- data/examples/code/snippets/scopetest +13 -0
- data/examples/code/snippets/selectorvalues.pp +22 -0
- data/examples/code/snippets/simpledefaults +5 -0
- data/examples/code/snippets/simpleselector +38 -0
- data/examples/code/svncommit +13 -0
- data/examples/root/bin/sleeper +69 -0
- data/examples/root/etc/configfile +0 -0
- data/examples/root/etc/debian-passwd +29 -0
- data/examples/root/etc/debian-syslog.conf +71 -0
- data/examples/root/etc/init.d/sleeper +65 -0
- data/examples/root/etc/otherfile +0 -0
- data/examples/root/etc/puppet/fileserver.conf +3 -0
- data/examples/root/etc/puppet/puppetmasterd.conf +10 -0
- data/ext/module:puppet +195 -0
- data/install.rb +270 -0
- data/lib/puppet.rb +249 -0
- data/lib/puppet/base64.rb +19 -0
- data/lib/puppet/client.rb +519 -0
- data/lib/puppet/config.rb +49 -0
- data/lib/puppet/daemon.rb +208 -0
- data/lib/puppet/element.rb +71 -0
- data/lib/puppet/event.rb +259 -0
- data/lib/puppet/log.rb +321 -0
- data/lib/puppet/metric.rb +250 -0
- data/lib/puppet/parsedfile.rb +38 -0
- data/lib/puppet/parser/ast.rb +1560 -0
- data/lib/puppet/parser/interpreter.rb +150 -0
- data/lib/puppet/parser/lexer.rb +226 -0
- data/lib/puppet/parser/parser.rb +1354 -0
- data/lib/puppet/parser/scope.rb +755 -0
- data/lib/puppet/server.rb +170 -0
- data/lib/puppet/server/authstore.rb +227 -0
- data/lib/puppet/server/ca.rb +140 -0
- data/lib/puppet/server/filebucket.rb +147 -0
- data/lib/puppet/server/fileserver.rb +477 -0
- data/lib/puppet/server/logger.rb +43 -0
- data/lib/puppet/server/master.rb +103 -0
- data/lib/puppet/server/servlet.rb +247 -0
- data/lib/puppet/sslcertificates.rb +737 -0
- data/lib/puppet/statechange.rb +150 -0
- data/lib/puppet/storage.rb +95 -0
- data/lib/puppet/transaction.rb +179 -0
- data/lib/puppet/transportable.rb +151 -0
- data/lib/puppet/type.rb +1354 -0
- data/lib/puppet/type/component.rb +141 -0
- data/lib/puppet/type/cron.rb +543 -0
- data/lib/puppet/type/exec.rb +316 -0
- data/lib/puppet/type/group.rb +152 -0
- data/lib/puppet/type/nameservice.rb +3 -0
- data/lib/puppet/type/nameservice/netinfo.rb +173 -0
- data/lib/puppet/type/nameservice/objectadd.rb +146 -0
- data/lib/puppet/type/nameservice/posix.rb +200 -0
- data/lib/puppet/type/package.rb +420 -0
- data/lib/puppet/type/package/apt.rb +70 -0
- data/lib/puppet/type/package/dpkg.rb +108 -0
- data/lib/puppet/type/package/rpm.rb +81 -0
- data/lib/puppet/type/package/sun.rb +117 -0
- data/lib/puppet/type/package/yum.rb +58 -0
- data/lib/puppet/type/pfile.rb +569 -0
- data/lib/puppet/type/pfile/checksum.rb +219 -0
- data/lib/puppet/type/pfile/create.rb +108 -0
- data/lib/puppet/type/pfile/group.rb +129 -0
- data/lib/puppet/type/pfile/mode.rb +131 -0
- data/lib/puppet/type/pfile/source.rb +264 -0
- data/lib/puppet/type/pfile/type.rb +31 -0
- data/lib/puppet/type/pfile/uid.rb +166 -0
- data/lib/puppet/type/pfilebucket.rb +80 -0
- data/lib/puppet/type/pprocess.rb +97 -0
- data/lib/puppet/type/service.rb +347 -0
- data/lib/puppet/type/service/base.rb +17 -0
- data/lib/puppet/type/service/debian.rb +50 -0
- data/lib/puppet/type/service/init.rb +145 -0
- data/lib/puppet/type/service/smf.rb +29 -0
- data/lib/puppet/type/state.rb +182 -0
- data/lib/puppet/type/symlink.rb +183 -0
- data/lib/puppet/type/tidy.rb +183 -0
- data/lib/puppet/type/typegen.rb +149 -0
- data/lib/puppet/type/typegen/filerecord.rb +243 -0
- data/lib/puppet/type/typegen/filetype.rb +316 -0
- data/lib/puppet/type/user.rb +290 -0
- data/lib/puppet/util.rb +138 -0
- data/test/certmgr/certmgr.rb +265 -0
- data/test/client/client.rb +203 -0
- data/test/executables/puppetbin.rb +53 -0
- data/test/executables/puppetca.rb +79 -0
- data/test/executables/puppetd.rb +71 -0
- data/test/executables/puppetmasterd.rb +153 -0
- data/test/executables/puppetmodule.rb +60 -0
- data/test/language/ast.rb +412 -0
- data/test/language/interpreter.rb +71 -0
- data/test/language/scope.rb +412 -0
- data/test/language/snippets.rb +445 -0
- data/test/other/events.rb +111 -0
- data/test/other/log.rb +195 -0
- data/test/other/metrics.rb +92 -0
- data/test/other/overrides.rb +115 -0
- data/test/other/parsedfile.rb +31 -0
- data/test/other/relationships.rb +113 -0
- data/test/other/state.rb +106 -0
- data/test/other/storage.rb +39 -0
- data/test/other/transactions.rb +235 -0
- data/test/parser/lexer.rb +120 -0
- data/test/parser/parser.rb +180 -0
- data/test/puppet/conffiles.rb +104 -0
- data/test/puppet/defaults.rb +100 -0
- data/test/puppet/error.rb +23 -0
- data/test/puppet/utiltest.rb +120 -0
- data/test/puppettest.rb +774 -0
- data/test/server/authstore.rb +209 -0
- data/test/server/bucket.rb +227 -0
- data/test/server/ca.rb +201 -0
- data/test/server/fileserver.rb +710 -0
- data/test/server/logger.rb +175 -0
- data/test/server/master.rb +150 -0
- data/test/server/server.rb +130 -0
- data/test/tagging/tagging.rb +80 -0
- data/test/test +51 -0
- data/test/types/basic.rb +119 -0
- data/test/types/component.rb +272 -0
- data/test/types/cron.rb +261 -0
- data/test/types/exec.rb +273 -0
- data/test/types/file.rb +616 -0
- data/test/types/filebucket.rb +167 -0
- data/test/types/fileignoresource.rb +287 -0
- data/test/types/filesources.rb +587 -0
- data/test/types/filetype.rb +162 -0
- data/test/types/group.rb +271 -0
- data/test/types/package.rb +205 -0
- data/test/types/query.rb +101 -0
- data/test/types/service.rb +100 -0
- data/test/types/symlink.rb +93 -0
- data/test/types/tidy.rb +124 -0
- data/test/types/type.rb +135 -0
- data/test/types/user.rb +371 -0
- metadata +243 -0
data/lib/puppet.rb
ADDED
@@ -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 $
|