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
@@ -0,0 +1,17 @@
|
|
1
|
+
module Puppet
|
2
|
+
module ServiceTypes
|
3
|
+
module BaseSvc
|
4
|
+
|
5
|
+
# The command used to start. Generated if the 'binary' argument
|
6
|
+
# is passed.
|
7
|
+
def startcmd
|
8
|
+
if self[:binary]
|
9
|
+
return self[:binary]
|
10
|
+
else
|
11
|
+
raise Puppet::Error,
|
12
|
+
"Services must specify a start command or a binary"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'puppet/type/service/init'
|
2
|
+
|
3
|
+
# Manage debian services. Start/stop is the same as InitSvc, but enable/disable
|
4
|
+
# is special.
|
5
|
+
module Puppet
|
6
|
+
module ServiceTypes
|
7
|
+
module DebianSvc
|
8
|
+
include Puppet::ServiceTypes::InitSvc
|
9
|
+
|
10
|
+
# Remove the symlinks
|
11
|
+
def disable
|
12
|
+
output = %x{update-rc.d -f #{self.name} remove 2>/dev/null}
|
13
|
+
|
14
|
+
unless $? == 0
|
15
|
+
raise Puppet::Error, "Could not disable %s: %s" %
|
16
|
+
[self.name, output]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def enabled?
|
21
|
+
output = %x{update-rc.d -n -f #{self.name} remove 2>/dev/null}
|
22
|
+
unless $? == 0
|
23
|
+
raise Puppet::Error, "Could not check %s: %s" %
|
24
|
+
[self.name, output]
|
25
|
+
end
|
26
|
+
|
27
|
+
# If it's enabled, then it will print output showing removal of
|
28
|
+
# links.
|
29
|
+
if output =~ /etc\/rc\d.d/
|
30
|
+
return true
|
31
|
+
else
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def enable(runlevel)
|
37
|
+
if runlevel
|
38
|
+
raise Puppet::Error, "Specification of runlevels is not supported"
|
39
|
+
else
|
40
|
+
output = %x{update-rc.d #{self.name} defaults 2>/dev/null}
|
41
|
+
end
|
42
|
+
|
43
|
+
unless $? == 0
|
44
|
+
raise Puppet::Error, "Could not check %s: %s" %
|
45
|
+
[self.name, output]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module Puppet
|
2
|
+
module ServiceTypes
|
3
|
+
module InitSvc
|
4
|
+
# Make sure we've got a search path set up. If they don't
|
5
|
+
# specify one, try to determine one.
|
6
|
+
def configchk
|
7
|
+
unless defined? @searchpaths
|
8
|
+
@searchpaths = []
|
9
|
+
end
|
10
|
+
unless @searchpaths.length > 0
|
11
|
+
if init = self.defaultinit
|
12
|
+
self.notice "Adding default init"
|
13
|
+
@searchpaths << init
|
14
|
+
else
|
15
|
+
self.notice "No default init for %s" %
|
16
|
+
Facter["operatingsystem"].value
|
17
|
+
|
18
|
+
raise Puppet::Error.new(
|
19
|
+
"You must specify a valid search path for service %s" %
|
20
|
+
self.name
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the default init path.
|
27
|
+
def defaultinit
|
28
|
+
unless defined? @defaultinit
|
29
|
+
case Facter["operatingsystem"].value
|
30
|
+
when "FreeBSD":
|
31
|
+
@defaultinit = "/etc/rc.d"
|
32
|
+
else
|
33
|
+
@defaultinit = "/etc/init.d"
|
34
|
+
@defaultrc = "/etc/rc%s.d"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
return @defaultinit
|
39
|
+
end
|
40
|
+
|
41
|
+
# Mark that our init script supports 'status' commands.
|
42
|
+
def hasstatus=(value)
|
43
|
+
case value
|
44
|
+
when true, "true": @parameters[:hasstatus] = true
|
45
|
+
when false, "false": @parameters[:hasstatus] = false
|
46
|
+
else
|
47
|
+
raise Puppet::Error, "Invalid 'hasstatus' value %s" %
|
48
|
+
value.inspect
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# it'd be nice if i didn't throw the output away...
|
53
|
+
# this command returns true if the exit code is 0, and returns
|
54
|
+
# false otherwise
|
55
|
+
def initcmd(cmd)
|
56
|
+
script = self.initscript
|
57
|
+
|
58
|
+
self.debug "Executing '%s %s' as initcmd for '%s'" %
|
59
|
+
[script,cmd,self]
|
60
|
+
|
61
|
+
rvalue = Kernel.system("%s %s" %
|
62
|
+
[script,cmd])
|
63
|
+
|
64
|
+
self.debug "'%s' ran with exit status '%s'" %
|
65
|
+
[cmd,rvalue]
|
66
|
+
|
67
|
+
|
68
|
+
rvalue
|
69
|
+
end
|
70
|
+
|
71
|
+
# Where is our init script?
|
72
|
+
def initscript
|
73
|
+
if defined? @initscript
|
74
|
+
return @initscript
|
75
|
+
else
|
76
|
+
@initscript = self.search(self.name)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Store the search path for init scripts. This will generally not
|
81
|
+
# be called.
|
82
|
+
def parampath=(ary)
|
83
|
+
unless ary.is_a?(Array)
|
84
|
+
ary = [ary]
|
85
|
+
end
|
86
|
+
@parameters[:path] = ary
|
87
|
+
@searchpaths = ary.find_all { |dir|
|
88
|
+
File.directory?(dir)
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
# Enable a service, so it's started at boot time. This basically
|
93
|
+
# just creates links in the RC directories, which means that, well,
|
94
|
+
# we need to know where the rc directories are.
|
95
|
+
# FIXME This should probably be a state or something, and
|
96
|
+
# it should actually create use Symlink objects...
|
97
|
+
# At this point, people should just link objects for enabling,
|
98
|
+
# if they're running on a system that doesn't have a tool to
|
99
|
+
# manage init script links.
|
100
|
+
#def enable
|
101
|
+
#end
|
102
|
+
|
103
|
+
#def disable
|
104
|
+
#end
|
105
|
+
|
106
|
+
def search(name)
|
107
|
+
@searchpaths.each { |path|
|
108
|
+
fqname = File.join(path,name)
|
109
|
+
begin
|
110
|
+
stat = File.stat(fqname)
|
111
|
+
rescue
|
112
|
+
# should probably rescue specific errors...
|
113
|
+
self.debug("Could not find %s in %s" % [name,path])
|
114
|
+
next
|
115
|
+
end
|
116
|
+
|
117
|
+
# if we've gotten this far, we found a valid script
|
118
|
+
return fqname
|
119
|
+
}
|
120
|
+
raise Puppet::Error, "Could not find init script for '%s'" % name
|
121
|
+
end
|
122
|
+
|
123
|
+
# The start command is just the init scriptwith 'start'.
|
124
|
+
def startcmd
|
125
|
+
self.initscript + " start"
|
126
|
+
end
|
127
|
+
|
128
|
+
# If it was specified that the init script has a 'status' command, then
|
129
|
+
# we just return that; otherwise, we return false, which causes it to
|
130
|
+
# fallback to other mechanisms.
|
131
|
+
def statuscmd
|
132
|
+
if self[:hasstatus]
|
133
|
+
return self.initscript + " status"
|
134
|
+
else
|
135
|
+
return false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# The stop command is just the init script with 'stop'.
|
140
|
+
def stopcmd
|
141
|
+
self.initscript + " stop"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Puppet
|
2
|
+
module ServiceTypes
|
3
|
+
module SMFSvc
|
4
|
+
def restartcmd
|
5
|
+
end
|
6
|
+
|
7
|
+
# The start command is just the init scriptwith 'start'.
|
8
|
+
def startcmd
|
9
|
+
self.initscript + " start"
|
10
|
+
end
|
11
|
+
|
12
|
+
# If it was specified that the init script has a 'status' command, then
|
13
|
+
# we just return that; otherwise, we return false, which causes it to
|
14
|
+
# fallback to other mechanisms.
|
15
|
+
def statuscmd
|
16
|
+
if self[:hasstatus]
|
17
|
+
return self.initscript + " status"
|
18
|
+
else
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# The stop command is just the init script with 'stop'.
|
24
|
+
def stopcmd
|
25
|
+
self.initscript + " stop"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# The virtual base class for states, which are the self-contained building
|
2
|
+
# blocks for actually doing work on the system.
|
3
|
+
|
4
|
+
require 'puppet'
|
5
|
+
require 'puppet/element'
|
6
|
+
require 'puppet/statechange'
|
7
|
+
|
8
|
+
module Puppet
|
9
|
+
class State < Puppet::Element
|
10
|
+
attr_accessor :is, :parent
|
11
|
+
|
12
|
+
# Because 'should' uses an array, we have a special method for handling
|
13
|
+
# it. We also want to keep copies of the original values, so that
|
14
|
+
# they can be retrieved and compared later when merging.
|
15
|
+
attr_reader :shouldorig
|
16
|
+
|
17
|
+
@virtual = true
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :unmanaged
|
21
|
+
attr_reader :name
|
22
|
+
end
|
23
|
+
|
24
|
+
# initialize our state
|
25
|
+
def initialize(hash)
|
26
|
+
@is = nil
|
27
|
+
|
28
|
+
unless hash.include?(:parent)
|
29
|
+
raise Puppet::DevError, "State %s was not passed a parent" % self
|
30
|
+
end
|
31
|
+
@parent = hash[:parent]
|
32
|
+
|
33
|
+
if hash.include?(:should)
|
34
|
+
self.should = hash[:should]
|
35
|
+
end
|
36
|
+
|
37
|
+
if hash.include?(:is)
|
38
|
+
self.is = hash[:is]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Determine whether the state is in-sync or not. If @should is
|
43
|
+
# not defined or is set to a non-true value, then we do not have
|
44
|
+
# a valid value for it and thus consider the state to be in-sync
|
45
|
+
# since we cannot fix it. Otherwise, we expect our should value
|
46
|
+
# to be an array, and if @is matches any of those values, then
|
47
|
+
# we consider it to be in-sync.
|
48
|
+
def insync?
|
49
|
+
#debug "%s value is '%s', should be '%s'" %
|
50
|
+
# [self,self.is.inspect,self.should.inspect]
|
51
|
+
unless defined? @should and @should
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
|
55
|
+
unless @should.is_a?(Array)
|
56
|
+
raise Puppet::DevError, "%s's should is not array" % self.class.name
|
57
|
+
end
|
58
|
+
|
59
|
+
# an empty array is analogous to no should values
|
60
|
+
if @should.empty?
|
61
|
+
return true
|
62
|
+
end
|
63
|
+
|
64
|
+
# Look for a matching value
|
65
|
+
@should.each { |val|
|
66
|
+
if @is == val
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
}
|
70
|
+
|
71
|
+
# otherwise, return false
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
|
75
|
+
def log(msg)
|
76
|
+
unless @parent[:loglevel]
|
77
|
+
raise Puppet::DevError, "Parent %s has no loglevel" %
|
78
|
+
@parent.to_s
|
79
|
+
end
|
80
|
+
Puppet::Log.create(
|
81
|
+
:level => @parent[:loglevel],
|
82
|
+
:message => msg,
|
83
|
+
:source => self
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
# each state class must define the name() method, and state instances
|
88
|
+
# do not change that name
|
89
|
+
# this implicitly means that a given object can only have one state
|
90
|
+
# instance of a given state class
|
91
|
+
def name
|
92
|
+
return self.class.name
|
93
|
+
end
|
94
|
+
|
95
|
+
# for testing whether we should actually do anything
|
96
|
+
def noop
|
97
|
+
unless defined? @noop
|
98
|
+
@noop = false
|
99
|
+
end
|
100
|
+
tmp = @noop || self.parent.noop || Puppet[:noop] || false
|
101
|
+
#debug "noop is %s" % tmp
|
102
|
+
return tmp
|
103
|
+
end
|
104
|
+
|
105
|
+
# return the full path to us, for logging and rollback; not currently
|
106
|
+
# used
|
107
|
+
def path
|
108
|
+
return [@parent.path, self.name].join("/")
|
109
|
+
end
|
110
|
+
|
111
|
+
# Only return the first value
|
112
|
+
def should
|
113
|
+
if defined? @should
|
114
|
+
unless @should.is_a?(Array)
|
115
|
+
self.warning @should.inspect
|
116
|
+
raise Puppet::DevError, "should for %s on %s is not an array" %
|
117
|
+
[self.class.name, @parent.name]
|
118
|
+
end
|
119
|
+
return @should[0]
|
120
|
+
else
|
121
|
+
return nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Set the should value.
|
126
|
+
def should=(values)
|
127
|
+
unless values.is_a?(Array)
|
128
|
+
values = [values]
|
129
|
+
end
|
130
|
+
|
131
|
+
@shouldorig = values
|
132
|
+
|
133
|
+
if self.respond_to?(:shouldprocess)
|
134
|
+
@should = values.collect { |val|
|
135
|
+
self.shouldprocess(val)
|
136
|
+
}
|
137
|
+
else
|
138
|
+
@should = values
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
# How should a state change be printed as a string?
|
144
|
+
def change_to_s
|
145
|
+
begin
|
146
|
+
if @is == :notfound
|
147
|
+
return "defined '%s' as '%s'" %
|
148
|
+
[self.name, self.should_to_s]
|
149
|
+
elsif self.should == :notfound
|
150
|
+
return "undefined %s from '%s'" %
|
151
|
+
[self.name, self.is_to_s]
|
152
|
+
else
|
153
|
+
return "%s changed '%s' to '%s'" %
|
154
|
+
[self.name, self.is_to_s, self.should_to_s]
|
155
|
+
end
|
156
|
+
rescue Puppet::Error, Puppet::DevError
|
157
|
+
raise
|
158
|
+
rescue => detail
|
159
|
+
raise Puppet::DevError, "Could not convert change %s to string: %s" %
|
160
|
+
[self.name, detail]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# because the @should and @is vars might be in weird formats,
|
165
|
+
# we need to set up a mechanism for pretty printing of the values
|
166
|
+
# default to just the values, but this way individual states can
|
167
|
+
# override these methods
|
168
|
+
def is_to_s
|
169
|
+
@is
|
170
|
+
end
|
171
|
+
|
172
|
+
def should_to_s
|
173
|
+
@should
|
174
|
+
end
|
175
|
+
|
176
|
+
def to_s
|
177
|
+
return "%s(%s)" % [@parent.name,self.name]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# $Id: state.rb 749 2005-11-22 05:33:42Z luke $
|
@@ -0,0 +1,183 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# $Id: symlink.rb 731 2005-10-26 04:44:25Z luke $
|
4
|
+
|
5
|
+
require 'etc'
|
6
|
+
require 'puppet/type/state'
|
7
|
+
require 'puppet/type/pfile'
|
8
|
+
|
9
|
+
module Puppet
|
10
|
+
# okay, how do we deal with parameters that don't have operations
|
11
|
+
# associated with them?
|
12
|
+
class State
|
13
|
+
class SymlinkTarget < Puppet::State
|
14
|
+
require 'etc'
|
15
|
+
attr_accessor :file
|
16
|
+
|
17
|
+
@doc = "Create a link to another file. Currently only symlinks
|
18
|
+
are supported, and attempts to replace normal files with
|
19
|
+
links will currently fail, while existing but incorrect symlinks
|
20
|
+
will be removed."
|
21
|
+
@name = :target
|
22
|
+
|
23
|
+
def create
|
24
|
+
begin
|
25
|
+
debug("Creating symlink '%s' to '%s'" %
|
26
|
+
[self.parent[:path],self.should])
|
27
|
+
unless File.symlink(self.should,self.parent[:path])
|
28
|
+
raise TypeError.new("Could not create symlink '%s'" %
|
29
|
+
self.parent[:path])
|
30
|
+
end
|
31
|
+
rescue => detail
|
32
|
+
raise TypeError.new("Cannot create symlink '%s': %s" %
|
33
|
+
[self.parent[:path],detail])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove
|
38
|
+
if FileTest.symlink?(self.parent[:path])
|
39
|
+
debug("Removing symlink '%s'" % self.parent[:path])
|
40
|
+
begin
|
41
|
+
File.unlink(self.parent[:path])
|
42
|
+
rescue
|
43
|
+
raise TypeError.new("Failed to remove symlink '%s'" %
|
44
|
+
self.parent[:path])
|
45
|
+
end
|
46
|
+
elsif FileTest.exists?(self.parent[:path])
|
47
|
+
raise TypeError.new("Cannot remove normal file '%s'" %
|
48
|
+
self.parent[:path])
|
49
|
+
else
|
50
|
+
debug("Symlink '%s' does not exist" %
|
51
|
+
self.parent[:path])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def retrieve
|
56
|
+
stat = nil
|
57
|
+
|
58
|
+
if FileTest.symlink?(self.parent[:path])
|
59
|
+
self.is = File.readlink(self.parent[:path])
|
60
|
+
debug("link value is '%s'" % self.is)
|
61
|
+
return
|
62
|
+
else
|
63
|
+
self.is = nil
|
64
|
+
return
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# this is somewhat complicated, because it could exist and be
|
69
|
+
# a file
|
70
|
+
def sync
|
71
|
+
if self.should.nil?
|
72
|
+
self.remove()
|
73
|
+
else # it should exist and be a symlink
|
74
|
+
if FileTest.symlink?(self.parent[:path])
|
75
|
+
path = File.readlink(self.parent[:path])
|
76
|
+
if path != self.should
|
77
|
+
self.remove()
|
78
|
+
self.create()
|
79
|
+
end
|
80
|
+
elsif FileTest.exists?(self.parent[:path])
|
81
|
+
raise TypeError.new("Cannot replace normal file '%s'" %
|
82
|
+
self.parent[:path])
|
83
|
+
else
|
84
|
+
self.create()
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
#self.parent.newevent(:event => :inode_changed)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Type
|
94
|
+
class Symlink < Type
|
95
|
+
attr_reader :stat, :path, :params
|
96
|
+
# class instance variable
|
97
|
+
@states = [
|
98
|
+
Puppet::State::SymlinkTarget
|
99
|
+
]
|
100
|
+
|
101
|
+
@parameters = [
|
102
|
+
:path,
|
103
|
+
:recurse
|
104
|
+
]
|
105
|
+
|
106
|
+
@paramdoc[:path] = "Path of link to create."
|
107
|
+
@paramdoc[:recurse] = "If target is a directory, recursively create
|
108
|
+
directories (using `file`'s `source` parameter) and link all
|
109
|
+
contained files."
|
110
|
+
@doc = "Create symbolic links to existing files."
|
111
|
+
@name = :symlink
|
112
|
+
@namevar = :path
|
113
|
+
|
114
|
+
def initialize(hash)
|
115
|
+
@arghash = self.argclean(hash.dup)
|
116
|
+
@arghash.delete(self.class.namevar)
|
117
|
+
|
118
|
+
super
|
119
|
+
end
|
120
|
+
|
121
|
+
def paramrecurse=(value)
|
122
|
+
@stat = nil
|
123
|
+
@target = self.state(:target).should
|
124
|
+
|
125
|
+
# we want to remove our state, because we're creating children
|
126
|
+
# to do the links
|
127
|
+
if FileTest.exist?(@target)
|
128
|
+
@stat = File.stat(@target)
|
129
|
+
else
|
130
|
+
self.info "Target %s must exist for recursive links" %
|
131
|
+
@target
|
132
|
+
return
|
133
|
+
end
|
134
|
+
|
135
|
+
# if we're a directory, then we descend into it; we only actually
|
136
|
+
# link to real files
|
137
|
+
unless @stat.directory?
|
138
|
+
return
|
139
|
+
end
|
140
|
+
|
141
|
+
self.delete(:target)
|
142
|
+
|
143
|
+
recurse = value
|
144
|
+
# we might have a string, rather than a number
|
145
|
+
if recurse.is_a?(String)
|
146
|
+
if recurse =~ /^[0-9]+$/
|
147
|
+
recurse = Integer(recurse)
|
148
|
+
#elsif recurse =~ /^inf/ # infinite recursion
|
149
|
+
else # anything else is infinite recursion
|
150
|
+
recurse = true
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# are we at the end of the recursion?
|
155
|
+
if recurse == 0
|
156
|
+
return
|
157
|
+
end
|
158
|
+
|
159
|
+
# okay, we're not going to recurse ourselves here; instead, we're
|
160
|
+
# going to rely on the fact that we've already got all of that
|
161
|
+
# working in pfile
|
162
|
+
|
163
|
+
args = {
|
164
|
+
:name => self.name,
|
165
|
+
:linkmaker => true,
|
166
|
+
:recurse => recurse,
|
167
|
+
:source => @target
|
168
|
+
}
|
169
|
+
|
170
|
+
dir = Puppet::Type::PFile.implicitcreate(args)
|
171
|
+
dir.parent = self
|
172
|
+
self.debug "Got dir %s" % dir.name
|
173
|
+
self.push dir
|
174
|
+
#Dir.foreach(@target) { |file|
|
175
|
+
# next if file =~ /^\.\.?$/ # skip . and ..
|
176
|
+
# newtarget = File.join(@target,file)
|
177
|
+
# #stat = File.stat(File.join(@target,file))
|
178
|
+
# self.newchild(file, :target => newtarget)
|
179
|
+
#}
|
180
|
+
end
|
181
|
+
end # Puppet::Type::Symlink
|
182
|
+
end # Puppet::Type
|
183
|
+
end
|