puppet 0.9.2 → 0.13.0
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 +58 -0
- data/README +21 -18
- data/Rakefile +176 -36
- data/bin/puppet +34 -48
- data/bin/puppetca +41 -28
- data/bin/puppetd +87 -65
- data/bin/puppetdoc +99 -23
- data/bin/puppetmasterd +72 -91
- data/conf/redhat/client.init +80 -0
- data/conf/redhat/client.sysconfig +11 -0
- data/conf/redhat/fileserver.conf +12 -0
- data/conf/redhat/puppet.spec +130 -0
- data/conf/redhat/server.init +89 -0
- data/conf/redhat/server.sysconfig +9 -0
- data/examples/code/allatonce +2 -2
- data/examples/code/assignments +1 -1
- data/examples/code/classing +2 -2
- data/examples/code/components +2 -2
- data/examples/code/file.bl +5 -5
- data/examples/code/filedefaults +2 -2
- data/examples/code/fileparsing +1 -1
- data/examples/code/filerecursion +1 -1
- data/examples/code/functions +1 -1
- data/examples/code/groups +1 -1
- data/examples/code/importing +1 -1
- data/examples/code/nodes +1 -1
- data/examples/code/one +1 -1
- data/examples/code/relationships +2 -2
- data/examples/code/simpletests +5 -5
- data/examples/code/snippets/argumentdefaults +2 -2
- data/examples/code/snippets/casestatement +16 -8
- data/examples/code/snippets/classheirarchy.pp +4 -4
- data/examples/code/snippets/classincludes.pp +4 -4
- data/examples/code/snippets/classpathtest +2 -2
- data/examples/code/snippets/componentmetaparams.pp +11 -0
- data/examples/code/snippets/dirchmod +5 -5
- data/examples/code/snippets/emptyclass.pp +9 -0
- data/examples/code/snippets/failmissingexecpath.pp +1 -1
- data/examples/code/snippets/falsevalues.pp +1 -1
- data/examples/code/snippets/filecreate +5 -5
- data/examples/code/snippets/implicititeration +5 -5
- data/examples/code/snippets/multipleinstances +4 -4
- data/examples/code/snippets/namevartest +3 -3
- data/examples/code/snippets/scopetest +1 -1
- data/examples/code/snippets/selectorvalues.pp +3 -3
- data/examples/code/snippets/simpledefaults +2 -2
- data/examples/code/snippets/simpleselector +5 -5
- data/examples/code/snippets/singleary.pp +19 -0
- data/examples/root/etc/init.d/sleeper +3 -2
- data/ext/emacs/puppet-mode-init.el +6 -0
- data/ext/emacs/puppet-mode.el +189 -0
- data/ext/ldap/puppet.schema +17 -0
- data/ext/{module:puppet → module_puppet} +30 -31
- data/ext/vim/filetype.vim +9 -0
- data/ext/vim/puppet.vim +87 -0
- data/install.rb +63 -30
- data/lib/puppet.rb +216 -122
- data/lib/puppet/client.rb +51 -416
- data/lib/puppet/client/ca.rb +17 -0
- data/lib/puppet/client/dipper.rb +78 -0
- data/lib/puppet/client/file.rb +20 -0
- data/lib/puppet/client/log.rb +17 -0
- data/lib/puppet/client/master.rb +246 -0
- data/lib/puppet/client/proxy.rb +27 -0
- data/lib/puppet/client/status.rb +7 -0
- data/lib/puppet/config.rb +563 -13
- data/lib/puppet/daemon.rb +50 -22
- data/lib/puppet/element.rb +4 -4
- data/lib/puppet/event-loop.rb +1 -0
- data/lib/puppet/event-loop/better-definers.rb +367 -0
- data/lib/puppet/event-loop/event-loop.rb +355 -0
- data/lib/puppet/event-loop/signal-system.rb +220 -0
- data/lib/puppet/event.rb +9 -11
- data/lib/puppet/filetype.rb +195 -0
- data/lib/puppet/log.rb +35 -12
- data/lib/puppet/metric.rb +2 -2
- data/lib/puppet/networkclient.rb +145 -0
- data/lib/puppet/parameter.rb +335 -0
- data/lib/puppet/parser/ast.rb +42 -1453
- data/lib/puppet/parser/ast/astarray.rb +88 -0
- data/lib/puppet/parser/ast/branch.rb +47 -0
- data/lib/puppet/parser/ast/caseopt.rb +66 -0
- data/lib/puppet/parser/ast/casestatement.rb +78 -0
- data/lib/puppet/parser/ast/classdef.rb +78 -0
- data/lib/puppet/parser/ast/compdef.rb +111 -0
- data/lib/puppet/parser/ast/component.rb +105 -0
- data/lib/puppet/parser/ast/hostclass.rb +82 -0
- data/lib/puppet/parser/ast/leaf.rb +86 -0
- data/lib/puppet/parser/ast/node.rb +103 -0
- data/lib/puppet/parser/ast/nodedef.rb +68 -0
- data/lib/puppet/parser/ast/objectdef.rb +336 -0
- data/lib/puppet/parser/ast/objectparam.rb +30 -0
- data/lib/puppet/parser/ast/objectref.rb +76 -0
- data/lib/puppet/parser/ast/selector.rb +60 -0
- data/lib/puppet/parser/ast/typedefaults.rb +45 -0
- data/lib/puppet/parser/ast/vardef.rb +44 -0
- data/lib/puppet/parser/interpreter.rb +31 -14
- data/lib/puppet/parser/lexer.rb +2 -4
- data/lib/puppet/parser/parser.rb +332 -242
- data/lib/puppet/parser/scope.rb +55 -38
- data/lib/puppet/server.rb +43 -44
- data/lib/puppet/server/authstore.rb +3 -6
- data/lib/puppet/server/ca.rb +5 -2
- data/lib/puppet/server/filebucket.rb +2 -4
- data/lib/puppet/server/fileserver.rb +28 -12
- data/lib/puppet/server/logger.rb +15 -4
- data/lib/puppet/server/master.rb +62 -7
- data/lib/puppet/sslcertificates.rb +41 -607
- data/lib/puppet/sslcertificates/ca.rb +291 -0
- data/lib/puppet/sslcertificates/certificate.rb +283 -0
- data/lib/puppet/statechange.rb +6 -1
- data/lib/puppet/storage.rb +67 -56
- data/lib/puppet/transaction.rb +25 -9
- data/lib/puppet/transportable.rb +102 -22
- data/lib/puppet/type.rb +1096 -315
- data/lib/puppet/type/component.rb +30 -21
- data/lib/puppet/type/cron.rb +409 -448
- data/lib/puppet/type/exec.rb +234 -174
- data/lib/puppet/type/group.rb +65 -82
- data/lib/puppet/type/nameservice.rb +247 -3
- data/lib/puppet/type/nameservice/netinfo.rb +29 -40
- data/lib/puppet/type/nameservice/objectadd.rb +52 -66
- data/lib/puppet/type/nameservice/posix.rb +6 -194
- data/lib/puppet/type/package.rb +447 -295
- data/lib/puppet/type/package/apt.rb +51 -50
- data/lib/puppet/type/package/bsd.rb +82 -0
- data/lib/puppet/type/package/dpkg.rb +85 -88
- data/lib/puppet/type/package/rpm.rb +67 -63
- data/lib/puppet/type/package/sun.rb +119 -98
- data/lib/puppet/type/package/yum.rb +41 -37
- data/lib/puppet/type/parsedtype.rb +295 -0
- data/lib/puppet/type/parsedtype/host.rb +143 -0
- data/lib/puppet/type/parsedtype/port.rb +232 -0
- data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
- data/lib/puppet/type/pfile.rb +484 -460
- data/lib/puppet/type/pfile/checksum.rb +237 -181
- data/lib/puppet/type/pfile/content.rb +67 -0
- data/lib/puppet/type/pfile/ensure.rb +212 -0
- data/lib/puppet/type/pfile/group.rb +106 -105
- data/lib/puppet/type/pfile/mode.rb +98 -101
- data/lib/puppet/type/pfile/source.rb +228 -209
- data/lib/puppet/type/pfile/type.rb +18 -21
- data/lib/puppet/type/pfile/uid.rb +127 -130
- data/lib/puppet/type/pfilebucket.rb +68 -63
- data/lib/puppet/type/schedule.rb +341 -0
- data/lib/puppet/type/service.rb +351 -255
- data/lib/puppet/type/service/base.rb +9 -14
- data/lib/puppet/type/service/debian.rb +32 -38
- data/lib/puppet/type/service/init.rb +130 -130
- data/lib/puppet/type/service/smf.rb +48 -20
- data/lib/puppet/type/state.rb +229 -16
- data/lib/puppet/type/symlink.rb +51 -63
- data/lib/puppet/type/tidy.rb +105 -102
- data/lib/puppet/type/user.rb +118 -180
- data/lib/puppet/util.rb +100 -6
- data/test/certmgr/certmgr.rb +0 -1
- data/test/client/client.rb +4 -4
- data/test/executables/puppetbin.rb +7 -14
- data/test/executables/puppetca.rb +18 -24
- data/test/executables/puppetd.rb +7 -16
- data/test/executables/puppetmasterd.rb +7 -9
- data/test/executables/puppetmodule.rb +11 -16
- data/test/language/ast.rb +11 -7
- data/test/language/interpreter.rb +1 -1
- data/test/language/scope.rb +2 -0
- data/test/language/snippets.rb +30 -5
- data/test/language/transportable.rb +77 -0
- data/test/other/config.rb +316 -0
- data/test/other/events.rb +22 -21
- data/test/other/log.rb +14 -14
- data/test/other/metrics.rb +4 -8
- data/test/other/overrides.rb +5 -5
- data/test/other/relationships.rb +4 -2
- data/test/other/storage.rb +64 -3
- data/test/other/transactions.rb +20 -20
- data/test/parser/parser.rb +7 -4
- data/test/puppet/conffiles.rb +12 -12
- data/test/puppet/defaults.rb +13 -11
- data/test/puppet/utiltest.rb +14 -11
- data/test/puppettest.rb +156 -48
- data/test/server/bucket.rb +2 -2
- data/test/server/fileserver.rb +6 -6
- data/test/server/logger.rb +19 -11
- data/test/server/master.rb +33 -4
- data/test/server/server.rb +2 -7
- data/test/types/basic.rb +5 -7
- data/test/types/component.rb +22 -18
- data/test/types/cron.rb +111 -44
- data/test/types/exec.rb +116 -59
- data/test/types/file.rb +262 -137
- data/test/types/filebucket.rb +13 -15
- data/test/types/fileignoresource.rb +12 -16
- data/test/types/filesources.rb +73 -48
- data/test/types/filetype.rb +13 -15
- data/test/types/group.rb +15 -13
- data/test/types/host.rb +146 -0
- data/test/types/package.rb +74 -63
- data/test/types/port.rb +139 -0
- data/test/types/query.rb +8 -8
- data/test/types/schedule.rb +335 -0
- data/test/types/service.rb +137 -21
- data/test/types/sshkey.rb +140 -0
- data/test/types/symlink.rb +3 -5
- data/test/types/tidy.rb +5 -14
- data/test/types/type.rb +67 -11
- data/test/types/user.rb +25 -23
- metadata +186 -122
- data/lib/puppet/type/pfile/create.rb +0 -108
- data/lib/puppet/type/pprocess.rb +0 -97
- data/lib/puppet/type/typegen.rb +0 -149
- data/lib/puppet/type/typegen/filerecord.rb +0 -243
- data/lib/puppet/type/typegen/filetype.rb +0 -316
- data/test/other/state.rb +0 -106
@@ -0,0 +1,17 @@
|
|
1
|
+
class Puppet::Client::CAClient < Puppet::Client::ProxyClient
|
2
|
+
@drivername = :CA
|
3
|
+
|
4
|
+
# set up the appropriate interface methods
|
5
|
+
@handler = Puppet::Server::CA
|
6
|
+
self.mkmethods
|
7
|
+
|
8
|
+
def initialize(hash = {})
|
9
|
+
if hash.include?(:CA)
|
10
|
+
hash[:CA] = Puppet::Server::CA.new()
|
11
|
+
end
|
12
|
+
|
13
|
+
super(hash)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# $Id: ca.rb 848 2006-01-24 06:01:58Z luke $
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Puppet
|
2
|
+
class Client
|
3
|
+
# The client class for filebuckets.
|
4
|
+
class Dipper < Puppet::Client
|
5
|
+
@drivername = :Bucket
|
6
|
+
|
7
|
+
def initialize(hash = {})
|
8
|
+
if hash.include?(:Path)
|
9
|
+
bucket = Puppet::Server::FileBucket.new(
|
10
|
+
:Bucket => hash[:Path]
|
11
|
+
)
|
12
|
+
hash.delete(:Path)
|
13
|
+
hash[:Bucket] = bucket
|
14
|
+
end
|
15
|
+
|
16
|
+
super(hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
def backup(file)
|
20
|
+
unless FileTest.exists?(file)
|
21
|
+
raise(BucketError, "File %s does not exist" % file, caller)
|
22
|
+
end
|
23
|
+
contents = File.open(file) { |of| of.read }
|
24
|
+
|
25
|
+
string = Base64.encode64(contents)
|
26
|
+
#puts "string is created"
|
27
|
+
|
28
|
+
sum = @driver.addfile(string,file)
|
29
|
+
#puts "file %s is added" % file
|
30
|
+
return sum
|
31
|
+
end
|
32
|
+
|
33
|
+
def restore(file,sum)
|
34
|
+
restore = true
|
35
|
+
if FileTest.exists?(file)
|
36
|
+
contents = File.open(file) { |of| of.read }
|
37
|
+
|
38
|
+
cursum = Digest::MD5.hexdigest(contents)
|
39
|
+
|
40
|
+
# if the checksum has changed...
|
41
|
+
# this might be extra effort
|
42
|
+
if cursum == sum
|
43
|
+
restore = false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if restore
|
48
|
+
#puts "Restoring %s" % file
|
49
|
+
if tmp = @driver.getfile(sum)
|
50
|
+
newcontents = Base64.decode64(tmp)
|
51
|
+
newsum = Digest::MD5.hexdigest(newcontents)
|
52
|
+
changed = nil
|
53
|
+
unless FileTest.writable?(file)
|
54
|
+
changed = File.stat(file).mode
|
55
|
+
File.chmod(changed | 0200, file)
|
56
|
+
end
|
57
|
+
File.open(file,File::WRONLY|File::TRUNC) { |of|
|
58
|
+
of.print(newcontents)
|
59
|
+
}
|
60
|
+
if changed
|
61
|
+
File.chmod(changed, file)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
Puppet.err "Could not find file with checksum %s" % sum
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
#puts "Done"
|
68
|
+
return newsum
|
69
|
+
else
|
70
|
+
return nil
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# $Id: dipper.rb 848 2006-01-24 06:01:58Z luke $
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Puppet::Client::FileClient < Puppet::Client::ProxyClient
|
2
|
+
@drivername = :FileServer
|
3
|
+
|
4
|
+
# set up the appropriate interface methods
|
5
|
+
@handler = Puppet::Server::FileServer
|
6
|
+
|
7
|
+
self.mkmethods
|
8
|
+
|
9
|
+
def initialize(hash = {})
|
10
|
+
if hash.include?(:FileServer)
|
11
|
+
unless hash[:FileServer].is_a?(Puppet::Server::FileServer)
|
12
|
+
raise Puppet::DevError, "Must pass an actual FS object"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
super(hash)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# $Id: file.rb 848 2006-01-24 06:01:58Z luke $
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Puppet::Client::LogClient < Puppet::Client::ProxyClient
|
2
|
+
@drivername = :Logger
|
3
|
+
|
4
|
+
# set up the appropriate interface methods
|
5
|
+
@handler = Puppet::Server::Logger
|
6
|
+
self.mkmethods
|
7
|
+
|
8
|
+
def initialize(hash = {})
|
9
|
+
if hash.include?(:Logger)
|
10
|
+
hash[:Logger] = Puppet::Server::Logger.new()
|
11
|
+
end
|
12
|
+
|
13
|
+
super(hash)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# $Id: log.rb 848 2006-01-24 06:01:58Z luke $
|
@@ -0,0 +1,246 @@
|
|
1
|
+
# The client for interacting with the puppetmaster config server.
|
2
|
+
class Puppet::Client::MasterClient < Puppet::Client
|
3
|
+
@drivername = :Master
|
4
|
+
|
5
|
+
def self.facts
|
6
|
+
facts = {}
|
7
|
+
Facter.each { |name,fact|
|
8
|
+
facts[name] = fact.downcase
|
9
|
+
}
|
10
|
+
|
11
|
+
facts
|
12
|
+
end
|
13
|
+
|
14
|
+
# This method is how the client receives the tree of Transportable
|
15
|
+
# objects. For now, just descend into the tree and perform and
|
16
|
+
# necessary manipulations.
|
17
|
+
def apply
|
18
|
+
Puppet.notice "Beginning configuration run"
|
19
|
+
dostorage()
|
20
|
+
unless defined? @objects
|
21
|
+
raise Puppet::Error, "Cannot apply; objects not defined"
|
22
|
+
end
|
23
|
+
|
24
|
+
#Puppet.err :yay
|
25
|
+
#p @objects
|
26
|
+
#Puppet.err :mark
|
27
|
+
#@objects = @objects.to_type
|
28
|
+
# this is a gross hack... but i don't see a good way around it
|
29
|
+
# set all of the variables to empty
|
30
|
+
Puppet::Transaction.init
|
31
|
+
|
32
|
+
# For now we just evaluate the top-level object, but eventually
|
33
|
+
# there will be schedules and such associated with each object,
|
34
|
+
# and probably with the container itself.
|
35
|
+
transaction = @objects.evaluate
|
36
|
+
#transaction = Puppet::Transaction.new(objects)
|
37
|
+
transaction.toplevel = true
|
38
|
+
begin
|
39
|
+
transaction.evaluate
|
40
|
+
rescue Puppet::Error => detail
|
41
|
+
Puppet.err "Could not apply complete configuration: %s" %
|
42
|
+
detail
|
43
|
+
rescue => detail
|
44
|
+
Puppet.err "Found a bug: %s" % detail
|
45
|
+
if Puppet[:debug]
|
46
|
+
puts detail.backtrace
|
47
|
+
end
|
48
|
+
ensure
|
49
|
+
Puppet::Storage.store
|
50
|
+
end
|
51
|
+
Puppet::Metric.gather
|
52
|
+
Puppet::Metric.tally
|
53
|
+
if Puppet[:rrdgraph] == true
|
54
|
+
Metric.store
|
55
|
+
Metric.graph
|
56
|
+
end
|
57
|
+
Puppet.notice "Finished configuration run"
|
58
|
+
|
59
|
+
return transaction
|
60
|
+
end
|
61
|
+
|
62
|
+
# Cache the config
|
63
|
+
def cache(text)
|
64
|
+
Puppet.info "Caching configuration at %s" % self.cachefile
|
65
|
+
confdir = File.dirname(Puppet[:localconfig])
|
66
|
+
unless FileTest.exists?(confdir)
|
67
|
+
Puppet.recmkdir(confdir, 0770)
|
68
|
+
end
|
69
|
+
File.open(self.cachefile + ".tmp", "w", 0660) { |f|
|
70
|
+
f.print text
|
71
|
+
}
|
72
|
+
File.rename(self.cachefile + ".tmp", self.cachefile)
|
73
|
+
end
|
74
|
+
|
75
|
+
def cachefile
|
76
|
+
unless defined? @cachefile
|
77
|
+
@cachefile = Puppet[:localconfig] + ".yaml"
|
78
|
+
end
|
79
|
+
@cachefile
|
80
|
+
end
|
81
|
+
|
82
|
+
# Initialize and load storage
|
83
|
+
def dostorage
|
84
|
+
begin
|
85
|
+
Puppet::Storage.init
|
86
|
+
Puppet::Storage.load
|
87
|
+
rescue => detail
|
88
|
+
Puppet.err "Corrupt state file %s: %s" % [Puppet[:statefile], detail]
|
89
|
+
begin
|
90
|
+
File.unlink(Puppet[:statefile])
|
91
|
+
retry
|
92
|
+
rescue => detail
|
93
|
+
raise Puppet::Error.new("Cannot remove %s: %s" %
|
94
|
+
[Puppet[statefile], detail])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Check whether our configuration is up to date
|
100
|
+
def fresh?
|
101
|
+
unless defined? @configstamp
|
102
|
+
return false
|
103
|
+
end
|
104
|
+
|
105
|
+
# We're willing to give a 2 second drift
|
106
|
+
if @driver.freshness - @configstamp < 1
|
107
|
+
return true
|
108
|
+
else
|
109
|
+
return false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Retrieve the config from a remote server. If this fails, then
|
114
|
+
# use the cached copy.
|
115
|
+
def getconfig
|
116
|
+
if self.fresh?
|
117
|
+
Puppet.info "Config is up to date"
|
118
|
+
return
|
119
|
+
end
|
120
|
+
Puppet.debug("getting config")
|
121
|
+
dostorage()
|
122
|
+
|
123
|
+
facts = self.class.facts
|
124
|
+
|
125
|
+
unless facts.length > 0
|
126
|
+
raise Puppet::ClientError.new(
|
127
|
+
"Could not retrieve any facts"
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
objects = nil
|
132
|
+
if @local
|
133
|
+
# If we're local, we don't have to do any of the conversion
|
134
|
+
# stuff.
|
135
|
+
objects = @driver.getconfig(facts, "yaml")
|
136
|
+
@configstamp = Time.now.to_i
|
137
|
+
|
138
|
+
if objects == ""
|
139
|
+
raise Puppet::Error, "Could not retrieve configuration"
|
140
|
+
end
|
141
|
+
else
|
142
|
+
textobjects = ""
|
143
|
+
|
144
|
+
textfacts = CGI.escape(YAML.dump(facts))
|
145
|
+
|
146
|
+
# error handling for this is done in the network client
|
147
|
+
begin
|
148
|
+
textobjects = @driver.getconfig(textfacts, "yaml")
|
149
|
+
rescue => detail
|
150
|
+
Puppet.err "Could not retrieve configuration: %s" % detail
|
151
|
+
end
|
152
|
+
|
153
|
+
fromcache = false
|
154
|
+
if textobjects == ""
|
155
|
+
textobjects = self.retrievecache
|
156
|
+
if textobjects == ""
|
157
|
+
raise Puppet::Error.new(
|
158
|
+
"Cannot connect to server and there is no cached configuration"
|
159
|
+
)
|
160
|
+
end
|
161
|
+
Puppet.notice "Could not get config; using cached copy"
|
162
|
+
fromcache = true
|
163
|
+
end
|
164
|
+
|
165
|
+
begin
|
166
|
+
textobjects = CGI.unescape(textobjects)
|
167
|
+
@configstamp = Time.now.to_i
|
168
|
+
rescue => detail
|
169
|
+
raise Puppet::Error, "Could not CGI.unescape configuration"
|
170
|
+
end
|
171
|
+
|
172
|
+
if @cache and ! fromcache
|
173
|
+
self.cache(textobjects)
|
174
|
+
end
|
175
|
+
|
176
|
+
begin
|
177
|
+
objects = YAML.load(textobjects)
|
178
|
+
rescue => detail
|
179
|
+
raise Puppet::Error,
|
180
|
+
"Could not understand configuration: %s" %
|
181
|
+
detail.to_s
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
unless objects.is_a?(Puppet::TransBucket)
|
186
|
+
raise NetworkClientError,
|
187
|
+
"Invalid returned objects of type %s" % objects.class
|
188
|
+
end
|
189
|
+
|
190
|
+
if classes = objects.classes
|
191
|
+
self.setclasses(classes)
|
192
|
+
else
|
193
|
+
Puppet.info "No classes to store"
|
194
|
+
end
|
195
|
+
|
196
|
+
# Clear all existing objects, so we can recreate our stack.
|
197
|
+
if defined? @objects
|
198
|
+
Puppet::Type.allclear
|
199
|
+
end
|
200
|
+
@objects = nil
|
201
|
+
|
202
|
+
# First create the default scheduling objects
|
203
|
+
Puppet.type(:schedule).mkdefaultschedules
|
204
|
+
|
205
|
+
# Now convert the objects to real Puppet objects
|
206
|
+
@objects = objects.to_type
|
207
|
+
|
208
|
+
if @objects.nil?
|
209
|
+
raise Puppet::Error, "Configuration could not be processed"
|
210
|
+
end
|
211
|
+
#@objects = objects
|
212
|
+
|
213
|
+
# and perform any necessary final actions before we evaluate.
|
214
|
+
Puppet::Type.finalize
|
215
|
+
|
216
|
+
return @objects
|
217
|
+
end
|
218
|
+
|
219
|
+
# Retrieve the cached config
|
220
|
+
def retrievecache
|
221
|
+
if FileTest.exists?(self.cachefile)
|
222
|
+
return File.read(self.cachefile)
|
223
|
+
else
|
224
|
+
return ""
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# The code that actually runs the configuration.
|
229
|
+
def run
|
230
|
+
self.getconfig
|
231
|
+
self.apply
|
232
|
+
end
|
233
|
+
|
234
|
+
def setclasses(ary)
|
235
|
+
begin
|
236
|
+
File.open(Puppet[:classfile], "w") { |f|
|
237
|
+
f.puts ary.join("\n")
|
238
|
+
}
|
239
|
+
rescue => detail
|
240
|
+
Puppet.err "Could not create class file %s: %s" %
|
241
|
+
[Puppet[:classfile], detail]
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# $Id: master.rb 872 2006-02-07 17:07:15Z luke $
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# unlike the other client classes (again, this design sucks) this class
|
2
|
+
# is basically just a proxy class -- it calls its methods on the driver
|
3
|
+
# and that's about it
|
4
|
+
class Puppet::Client::ProxyClient < Puppet::Client
|
5
|
+
def self.mkmethods
|
6
|
+
interface = @handler.interface
|
7
|
+
namespace = interface.prefix
|
8
|
+
|
9
|
+
interface.methods.each { |ary|
|
10
|
+
method = ary[0]
|
11
|
+
Puppet.debug "%s: defining %s.%s" % [self, namespace, method]
|
12
|
+
self.send(:define_method,method) { |*args|
|
13
|
+
begin
|
14
|
+
@driver.send(method, *args)
|
15
|
+
rescue XMLRPC::FaultException => detail
|
16
|
+
#Puppet.err "Could not call %s.%s: %s" %
|
17
|
+
# [namespace, method, detail.faultString]
|
18
|
+
#raise NetworkClientError,
|
19
|
+
# "XMLRPC Error: %s" % detail.faultString
|
20
|
+
raise NetworkClientError, detail.faultString
|
21
|
+
end
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# $Id: proxy.rb 848 2006-01-24 06:01:58Z luke $
|
data/lib/puppet/config.rb
CHANGED
@@ -1,17 +1,183 @@
|
|
1
|
-
module Puppet
|
1
|
+
module Puppet
|
2
2
|
# The class for handling configuration files.
|
3
|
-
class Config
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
class Config
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
# Retrieve a config value
|
7
|
+
def [](param)
|
8
|
+
param = convert(param)
|
9
|
+
if @config.include?(param)
|
10
|
+
if @config[param]
|
11
|
+
val = @config[param].value
|
12
|
+
return val
|
13
|
+
end
|
14
|
+
else
|
15
|
+
raise ArgumentError, "Invalid argument %s" % param
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Set a config value. This doesn't set the defaults, it sets the value itself.
|
20
|
+
def []=(param, value)
|
21
|
+
param = convert(param)
|
22
|
+
unless @config.include?(param)
|
23
|
+
raise Puppet::Error, "Unknown configuration parameter %s" % param.inspect
|
24
|
+
end
|
25
|
+
unless @order.include?(param)
|
26
|
+
@order << param
|
27
|
+
end
|
28
|
+
@config[param].value = value
|
29
|
+
end
|
30
|
+
|
31
|
+
# A simplified equality operator.
|
32
|
+
def ==(other)
|
33
|
+
self.each { |myname, myobj|
|
34
|
+
unless other[myname] == myobj.value
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
}
|
38
|
+
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
|
42
|
+
# Generate the list of valid arguments, in a format that GetoptLong can
|
43
|
+
# understand, and add them to the passed option list.
|
44
|
+
def addargs(options)
|
45
|
+
require 'getoptlong'
|
46
|
+
# Add all of the config parameters as valid options.
|
47
|
+
self.each { |param, obj|
|
48
|
+
if self.boolean?(param)
|
49
|
+
options << ["--#{param}", GetoptLong::NO_ARGUMENT]
|
50
|
+
options << ["--no-#{param}", GetoptLong::NO_ARGUMENT]
|
51
|
+
else
|
52
|
+
options << ["--#{param}", GetoptLong::REQUIRED_ARGUMENT]
|
53
|
+
end
|
54
|
+
}
|
55
|
+
|
56
|
+
return options
|
57
|
+
end
|
58
|
+
|
59
|
+
# Turn the config into a transaction and apply it
|
60
|
+
def apply
|
61
|
+
trans = self.to_transportable
|
62
|
+
begin
|
63
|
+
comp = trans.to_type
|
64
|
+
trans = comp.evaluate
|
65
|
+
trans.evaluate
|
66
|
+
comp.remove
|
67
|
+
rescue => detail
|
68
|
+
puts detail.backtrace
|
69
|
+
Puppet.err "Could not configure myself: %s" % detail
|
9
70
|
end
|
10
|
-
super
|
11
71
|
end
|
12
72
|
|
13
|
-
|
73
|
+
# Is our parameter a boolean parameter?
|
74
|
+
def boolean?(param)
|
75
|
+
param = convert(param)
|
76
|
+
if @config.include?(param) and @config[param].kind_of? CBoolean
|
77
|
+
return true
|
78
|
+
else
|
79
|
+
return false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Remove all set values.
|
84
|
+
def clear
|
85
|
+
@config.each { |name, obj|
|
86
|
+
obj.clear
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def convert(param)
|
91
|
+
case param
|
92
|
+
when String: return param.intern
|
93
|
+
when Symbol: return param
|
94
|
+
else
|
95
|
+
raise ArgumentError, "Invalid param type %s" % param.class
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def each
|
100
|
+
@order.each { |name|
|
101
|
+
if @config.include?(name)
|
102
|
+
yield name, @config[name]
|
103
|
+
else
|
104
|
+
raise Puppet::DevError, "%s is in the order but does not exist" % name
|
105
|
+
end
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
# Iterate over each section name.
|
110
|
+
def eachsection
|
111
|
+
yielded = []
|
112
|
+
@order.each { |name|
|
113
|
+
if @config.include?(name)
|
114
|
+
section = @config[name].section
|
115
|
+
unless yielded.include? section
|
116
|
+
yield section
|
117
|
+
yielded << section
|
118
|
+
end
|
119
|
+
else
|
120
|
+
raise Puppet::DevError, "%s is in the order but does not exist" % name
|
121
|
+
end
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
# Return an object by name.
|
126
|
+
def element(param)
|
127
|
+
param = convert(param)
|
128
|
+
@config[param]
|
129
|
+
end
|
130
|
+
|
131
|
+
# Handle a command-line argument.
|
132
|
+
def handlearg(opt, value = nil)
|
133
|
+
if value == "true"
|
134
|
+
value = true
|
135
|
+
end
|
136
|
+
if value == "false"
|
137
|
+
value = false
|
138
|
+
end
|
139
|
+
str = opt.sub(/^--/,'')
|
140
|
+
bool = true
|
141
|
+
newstr = str.sub(/^no-/, '')
|
142
|
+
if newstr != str
|
143
|
+
str = newstr
|
144
|
+
bool = false
|
145
|
+
end
|
146
|
+
if self.valid?(str)
|
147
|
+
if self.boolean?(str)
|
148
|
+
self[str] = bool
|
149
|
+
else
|
150
|
+
self[str] = value
|
151
|
+
end
|
152
|
+
|
153
|
+
# Mark that this was set on the cli, so it's not overridden if the config
|
154
|
+
# gets reread.
|
155
|
+
@config[str.intern].setbycli = true
|
156
|
+
else
|
157
|
+
raise ArgumentError, "Invalid argument %s" % opt
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Create a new config object
|
162
|
+
def initialize
|
163
|
+
@order = []
|
164
|
+
@config = {}
|
165
|
+
end
|
166
|
+
|
167
|
+
# Return all of the parameters associated with a given section.
|
168
|
+
def params(section)
|
169
|
+
section = section.intern if section.is_a? String
|
170
|
+
@config.find_all { |name, obj|
|
171
|
+
obj.section == section
|
172
|
+
}.collect { |name, obj|
|
173
|
+
name
|
174
|
+
}
|
175
|
+
end
|
176
|
+
|
177
|
+
# Parse a configuration file.
|
178
|
+
def parse(file)
|
14
179
|
text = nil
|
180
|
+
@file = file
|
15
181
|
|
16
182
|
begin
|
17
183
|
text = File.read(file)
|
@@ -29,21 +195,405 @@ class Config < Hash
|
|
29
195
|
}
|
30
196
|
|
31
197
|
section = "puppet"
|
198
|
+
metas = %w{owner group mode}
|
199
|
+
values = Hash.new { |hash, key| hash[key] = {} }
|
32
200
|
text.split(/\n/).each { |line|
|
33
201
|
case line
|
34
202
|
when /^\[(\w+)\]$/: section = $1 # Section names
|
35
203
|
when /^\s*#/: next # Skip comments
|
36
204
|
when /^\s*$/: next # Skip blanks
|
37
|
-
when /^\s*(\w+)\s
|
38
|
-
var = $1
|
205
|
+
when /^\s*(\w+)\s*=\s*(.+)$/: # settings
|
206
|
+
var = $1.intern
|
39
207
|
value = $2
|
40
|
-
|
208
|
+
|
209
|
+
# Mmm, "special" attributes
|
210
|
+
if metas.include?(var.to_s)
|
211
|
+
unless values.include?(section)
|
212
|
+
values[section] = {}
|
213
|
+
end
|
214
|
+
values[section][var.to_s] = value
|
215
|
+
next
|
216
|
+
end
|
217
|
+
|
218
|
+
# Don't override set parameters, since the file is parsed
|
219
|
+
# after cli arguments are handled.
|
220
|
+
unless @config.include?(var) and @config[var].setbycli
|
221
|
+
Puppet.debug "%s: Setting %s to '%s'" % [section, var, value]
|
222
|
+
self[var] = value
|
223
|
+
end
|
224
|
+
@config[var].section = section
|
225
|
+
|
226
|
+
metas.each { |meta|
|
227
|
+
if values[section][meta]
|
228
|
+
if @config[var].respond_to?(meta + "=")
|
229
|
+
@config[var].send(meta + "=", values[section][meta])
|
230
|
+
end
|
231
|
+
end
|
232
|
+
}
|
41
233
|
else
|
42
234
|
raise Puppet::Error, "Could not match line %s" % line
|
43
235
|
end
|
44
236
|
}
|
45
237
|
end
|
238
|
+
|
239
|
+
# Create a new element. The value is passed in because it's used to determine
|
240
|
+
# what kind of element we're creating, but the value itself might be either
|
241
|
+
# a default or a value, so we can't actually assign it.
|
242
|
+
def newelement(param, desc, value)
|
243
|
+
param = convert(param)
|
244
|
+
mod = nil
|
245
|
+
case value
|
246
|
+
when true, false, "true", "false":
|
247
|
+
mod = CBoolean
|
248
|
+
when /^\$/, /^\//:
|
249
|
+
mod = CFile
|
250
|
+
when String, Integer, Float: # nothing
|
251
|
+
else
|
252
|
+
raise Puppet::Error, "Invalid value '%s' for %s" % [value, param]
|
253
|
+
end
|
254
|
+
element = CElement.new(param, desc)
|
255
|
+
element.parent = self
|
256
|
+
if mod
|
257
|
+
element.extend(mod)
|
258
|
+
end
|
259
|
+
|
260
|
+
@order << param
|
261
|
+
|
262
|
+
return element
|
263
|
+
end
|
264
|
+
|
265
|
+
# Iterate across all of the objects in a given section.
|
266
|
+
def persection(section)
|
267
|
+
self.each { |name, obj|
|
268
|
+
if obj.section == section
|
269
|
+
yield obj
|
270
|
+
end
|
271
|
+
}
|
272
|
+
end
|
273
|
+
|
274
|
+
# Get a list of objects per section
|
275
|
+
def sectionlist
|
276
|
+
sectionlist = []
|
277
|
+
self.each { |name, obj|
|
278
|
+
section = obj.section || "puppet"
|
279
|
+
sections[section] ||= []
|
280
|
+
unless sectionlist.include?(section)
|
281
|
+
sectionlist << section
|
282
|
+
end
|
283
|
+
sections[section] << obj
|
284
|
+
}
|
285
|
+
|
286
|
+
return sectionlist, sections
|
287
|
+
end
|
288
|
+
|
289
|
+
# Convert a single section into transportable objects.
|
290
|
+
def section_to_transportable(section, done)
|
291
|
+
objects = []
|
292
|
+
persection(section) { |obj|
|
293
|
+
[:owner, :group].each { |type|
|
294
|
+
if obj.respond_to? type and val = obj.send(type)
|
295
|
+
# Skip owners and groups we've already done, but tag them with
|
296
|
+
# our section if necessary
|
297
|
+
if done[type].include?(val)
|
298
|
+
next unless defined? @section and @section
|
299
|
+
|
300
|
+
tags = done[type][val].tags
|
301
|
+
unless tags.include?(@section)
|
302
|
+
done[type][val].tags = tags << @section
|
303
|
+
end
|
304
|
+
else
|
305
|
+
newobj = TransObject.new(val, type.to_s)
|
306
|
+
newobj[:ensure] = "exists"
|
307
|
+
done[type] << newobj
|
308
|
+
end
|
309
|
+
end
|
310
|
+
}
|
311
|
+
|
312
|
+
if obj.respond_to? :to_transportable
|
313
|
+
unless done[:file].include? obj.value
|
314
|
+
trans = obj.to_transportable
|
315
|
+
# transportable could return nil
|
316
|
+
next unless trans
|
317
|
+
objects << trans
|
318
|
+
done[:file] << obj.value
|
319
|
+
end
|
320
|
+
end
|
321
|
+
}
|
322
|
+
|
323
|
+
bucket = Puppet::TransBucket.new
|
324
|
+
bucket.autoname = true
|
325
|
+
bucket.name = "autosection-%s" % bucket.object_id
|
326
|
+
bucket.type = section
|
327
|
+
bucket.push(*objects)
|
328
|
+
bucket.keyword = "class"
|
329
|
+
|
330
|
+
return bucket
|
331
|
+
end
|
332
|
+
|
333
|
+
# Set a bunch of defaults in a given section. The sections are actually pretty
|
334
|
+
# pointless, but they help break things up a bit, anyway.
|
335
|
+
def setdefaults(section, *defs)
|
336
|
+
section = section.intern unless section.is_a? Symbol
|
337
|
+
#hash.each { |param, value|
|
338
|
+
defs.each { |param, value, desc|
|
339
|
+
param = convert(param)
|
340
|
+
if @config.include?(param) and @config[param].default
|
341
|
+
raise Puppet::Error, "Default %s is already defined" % param
|
342
|
+
end
|
343
|
+
unless @config.include?(param)
|
344
|
+
@config[param] = newelement(param, desc, value)
|
345
|
+
end
|
346
|
+
@config[param].default = value
|
347
|
+
@config[param].section = section
|
348
|
+
}
|
349
|
+
end
|
350
|
+
|
351
|
+
# Convert our list of objects into a component that can be applied.
|
352
|
+
def to_component
|
353
|
+
transport = self.to_transportable
|
354
|
+
return transport.to_type
|
355
|
+
end
|
356
|
+
|
357
|
+
# Convert our list of objects into a configuration file.
|
358
|
+
def to_config
|
359
|
+
str = %{The configuration file for #{Puppet.name}. Note that this file
|
360
|
+
is likely to have unused configuration parameters in it; any parameter that's
|
361
|
+
valid anywhere in Puppet can be in any config file, even if it's not used.
|
362
|
+
|
363
|
+
Every section can specify three special parameters: owner, group, and mode.
|
364
|
+
These parameters affect the required permissions of any files specified after
|
365
|
+
their specification. Puppet will sometimes use these parameters to check its
|
366
|
+
own configured state, so they can be used to make Puppet a bit more self-managing.
|
367
|
+
|
368
|
+
Note also that the section names are entirely for human-level organizational
|
369
|
+
purposes; they don't provide separate namespaces. All parameters are in a
|
370
|
+
single namespace.
|
371
|
+
|
372
|
+
Generated on #{Time.now}.
|
373
|
+
|
374
|
+
}.gsub(/^/, "# ")
|
375
|
+
|
376
|
+
eachsection do |section|
|
377
|
+
str += "[#{section}]\n"
|
378
|
+
persection(section) do |obj|
|
379
|
+
str += obj.to_config + "\n"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
return str
|
384
|
+
end
|
385
|
+
|
386
|
+
# Convert our configuration into a list of transportable objects.
|
387
|
+
def to_transportable
|
388
|
+
done = {
|
389
|
+
:owner => [],
|
390
|
+
:group => [],
|
391
|
+
:file => []
|
392
|
+
}
|
393
|
+
|
394
|
+
topbucket = Puppet::TransBucket.new
|
395
|
+
if defined? @file and @file
|
396
|
+
topbucket.name = @file
|
397
|
+
else
|
398
|
+
topbucket.name = "configtop"
|
399
|
+
end
|
400
|
+
topbucket.type = "puppetconfig"
|
401
|
+
topbucket.top = true
|
402
|
+
topbucket.autoname = true
|
403
|
+
|
404
|
+
# Now iterate over each section
|
405
|
+
eachsection do |section|
|
406
|
+
topbucket.push section_to_transportable(section, done)
|
407
|
+
end
|
408
|
+
|
409
|
+
topbucket
|
410
|
+
end
|
411
|
+
|
412
|
+
# Convert to a parseable manifest
|
413
|
+
def to_manifest
|
414
|
+
transport = self.to_transportable
|
415
|
+
|
416
|
+
manifest = transport.to_manifest + "\n"
|
417
|
+
eachsection { |section|
|
418
|
+
manifest += "include #{section}\n"
|
419
|
+
}
|
420
|
+
|
421
|
+
return manifest
|
422
|
+
end
|
423
|
+
|
424
|
+
def valid?(param)
|
425
|
+
param = convert(param)
|
426
|
+
@config.has_key?(param)
|
427
|
+
end
|
428
|
+
|
429
|
+
# The base element type.
|
430
|
+
class CElement
|
431
|
+
attr_accessor :name, :section, :default, :parent, :desc, :setbycli
|
432
|
+
|
433
|
+
# Unset any set value.
|
434
|
+
def clear
|
435
|
+
@value = nil
|
436
|
+
end
|
437
|
+
|
438
|
+
# Create the new element. Pretty much just sets the name.
|
439
|
+
def initialize(name, desc, value = nil)
|
440
|
+
@name = name
|
441
|
+
@desc = desc.gsub(/^\s*/, '')
|
442
|
+
if value
|
443
|
+
@value = value
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
def set?
|
448
|
+
if defined? @value and ! @value.nil?
|
449
|
+
return true
|
450
|
+
else
|
451
|
+
return false
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
# Convert the object to a config statement.
|
456
|
+
def to_config
|
457
|
+
str = @desc.gsub(/^/, "# ") + "\n"
|
458
|
+
|
459
|
+
# Add in a statement about the default.
|
460
|
+
if defined? @default and @default
|
461
|
+
str += "# The default value is '%s'.\n" % @default
|
462
|
+
end
|
463
|
+
|
464
|
+
line = "%s = %s" % [@name, self.value]
|
465
|
+
|
466
|
+
# If the value has not been overridden, then print it out commented
|
467
|
+
# and unconverted, so it's clear that that's the default and how it
|
468
|
+
# works.
|
469
|
+
if defined? @value and ! @value.nil?
|
470
|
+
line = "%s = %s" % [@name, self.value]
|
471
|
+
else
|
472
|
+
line = "# %s = %s" % [@name, @default]
|
473
|
+
end
|
474
|
+
|
475
|
+
str += line + "\n"
|
476
|
+
|
477
|
+
str.gsub(/^/, " ")
|
478
|
+
end
|
479
|
+
|
480
|
+
# Retrieves the value, or if it's not set, retrieves the default.
|
481
|
+
def value
|
482
|
+
retval = nil
|
483
|
+
if defined? @value and ! @value.nil?
|
484
|
+
retval = @value
|
485
|
+
elsif defined? @default
|
486
|
+
retval = @default
|
487
|
+
else
|
488
|
+
return nil
|
489
|
+
end
|
490
|
+
|
491
|
+
if respond_to?(:convert)
|
492
|
+
return convert(retval)
|
493
|
+
else
|
494
|
+
return retval
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
# Set the value.
|
499
|
+
def value=(value)
|
500
|
+
if respond_to?(:validate)
|
501
|
+
validate(value)
|
502
|
+
end
|
503
|
+
if respond_to?(:munge)
|
504
|
+
@value = munge(value)
|
505
|
+
else
|
506
|
+
@value = value
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
# A file.
|
512
|
+
module CFile
|
513
|
+
attr_accessor :owner, :group, :mode
|
514
|
+
|
515
|
+
def convert(value)
|
516
|
+
return value unless value
|
517
|
+
return value unless value.is_a? String
|
518
|
+
if value =~ /\$(\w+)/
|
519
|
+
parent = $1
|
520
|
+
if pval = @parent[parent]
|
521
|
+
newval = value.sub(/\$#{parent}/, pval)
|
522
|
+
return File.join(newval.split("/"))
|
523
|
+
else
|
524
|
+
raise Puppet::DevError, "Could not find value for %s" % parent
|
525
|
+
end
|
526
|
+
else
|
527
|
+
return value
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
# Set the type appropriately. Yep, a hack. This supports either naming
|
532
|
+
# the variable 'dir', or adding a slash at the end.
|
533
|
+
def munge(value)
|
534
|
+
if value.to_s =~ /\/$/
|
535
|
+
@type = :directory
|
536
|
+
return value.sub(/\/$/, '')
|
537
|
+
end
|
538
|
+
return value
|
539
|
+
end
|
540
|
+
|
541
|
+
# Return the appropriate type.
|
542
|
+
def type
|
543
|
+
value = self.value
|
544
|
+
if @name.to_s =~ /dir/
|
545
|
+
return :directory
|
546
|
+
elsif value.to_s =~ /\/$/
|
547
|
+
return :directory
|
548
|
+
elsif value.is_a? String
|
549
|
+
return :file
|
550
|
+
else
|
551
|
+
return nil
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
# Convert the object to a TransObject instance.
|
556
|
+
def to_transportable
|
557
|
+
type = self.type
|
558
|
+
return nil unless type
|
559
|
+
obj = Puppet::TransObject.new(self.value, "file")
|
560
|
+
obj[:ensure] = type
|
561
|
+
[:owner, :group, :mode].each { |var|
|
562
|
+
if value = self.send(var)
|
563
|
+
obj[var] = value
|
564
|
+
end
|
565
|
+
}
|
566
|
+
if self.section
|
567
|
+
obj.tags = ["puppet", "configuration", self.section]
|
568
|
+
end
|
569
|
+
obj
|
570
|
+
end
|
571
|
+
|
572
|
+
# Make sure any provided variables look up to something.
|
573
|
+
def validate(value)
|
574
|
+
return true unless value.is_a? String
|
575
|
+
value.scan(/\$(\w+)/) { |name|
|
576
|
+
name = name[0]
|
577
|
+
unless @parent[name]
|
578
|
+
raise Puppet::Error, "'%s' is unset" % name
|
579
|
+
end
|
580
|
+
}
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
# A simple boolean.
|
585
|
+
module CBoolean
|
586
|
+
def munge(value)
|
587
|
+
case value
|
588
|
+
when true, "true": return true
|
589
|
+
when false, "false": return false
|
590
|
+
else
|
591
|
+
raise Puppet::Error, "Invalid value '%s' for %s" %
|
592
|
+
[value.inspect, @name]
|
593
|
+
end
|
594
|
+
end
|
595
|
+
end
|
46
596
|
end
|
47
597
|
end
|
48
598
|
|
49
|
-
# $Id: config.rb
|
599
|
+
# $Id: config.rb 873 2006-02-07 23:12:33Z luke $
|