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
|
#!/usr/local/bin/ruby -w
# $Id$
# the available clients
require 'puppet'
require 'puppet/function'
require 'puppet/type'
require 'puppet/fact'
require 'puppet/transaction'
require 'puppet/transportable'
require 'puppet/metric'
require 'http-access2'
require 'soap/rpc/driver'
require 'soap/rpc/httpserver'
#require 'webrick/https'
require 'logger'
module Puppet
class ClientError < RuntimeError; end
#---------------------------------------------------------------
class Client < SOAP::RPC::HTTPServer
def initialize(hash)
# to whom do we connect?
@server = nil
@nil = nil
@url = hash[:Server]
if hash.include?(:Listen) and hash[:Listen] == false
Puppet.debug "We're a local client"
@localonly = true
@driver = @url
else
Puppet.debug "We're a networked client"
@localonly = false
@driver = SOAP::RPC::Driver.new(@url, 'urn:puppet-server')
@driver.add_method("getconfig", "name")
end
unless @localonly
hash.delete(:Server)
Puppet.debug "Server is %s" % @url
hash[:BindAddress] ||= "0.0.0.0"
hash[:Port] ||= 17444
#hash[:Debug] ||= true
hash[:AccessLog] ||= []
super(hash)
end
end
def getconfig
Puppet.debug "server is %s" % @url
#client.loadproperty('files/sslclient.properties')
Puppet.debug("getting config")
objects = nil
if @localonly
objects = @driver.getconfig(self)
else
objects = @driver.getconfig(Puppet::Fact["hostname"])
end
self.config(objects)
end
# this method is how the client receives the tree of Transportable
# objects
# for now, just descend into the tree and perform and necessary
# manipulations
def config(tree)
Puppet.debug("Calling config")
container = Marshal::load(tree).to_type
# this is a gross hack... but i don't see a good way around it
# set all of the variables to empty
Puppet::Transaction.init
# for now we just evaluate the top-level container, but eventually
# there will be schedules and such associated with each object,
# and probably with the container itself
transaction = container.evaluate
#transaction = Puppet::Transaction.new(objects)
transaction.toplevel = true
transaction.evaluate
Puppet::Metric.gather
Puppet::Metric.tally
if Puppet[:rrdgraph] == true
Metric.store
Metric.graph
end
self.shutdown
end
def callfunc(name,args)
Puppet.debug("Calling callfunc on %s" % name)
if function = Puppet::Function[name]
#Puppet.debug("calling function %s" % function)
value = function.call(args)
#Puppet.debug("from %s got %s" % [name,value])
return value
else
raise "Function '%s' not found" % name
end
end
private
def on_init
@default_namespace = 'urn:puppet-client'
add_method(self, 'config', 'config')
add_method(self, 'callfunc', 'name', 'arguments')
end
def cert(filename)
OpenSSL::X509::Certificate.new(File.open(File.join(@dir, filename)) { |f|
f.read
})
end
def key(filename)
OpenSSL::PKey::RSA.new(File.open(File.join(@dir, filename)) { |f|
f.read
})
end
end
#---------------------------------------------------------------
end
|