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.

Files changed (213) hide show
  1. data/CHANGELOG +58 -0
  2. data/README +21 -18
  3. data/Rakefile +176 -36
  4. data/bin/puppet +34 -48
  5. data/bin/puppetca +41 -28
  6. data/bin/puppetd +87 -65
  7. data/bin/puppetdoc +99 -23
  8. data/bin/puppetmasterd +72 -91
  9. data/conf/redhat/client.init +80 -0
  10. data/conf/redhat/client.sysconfig +11 -0
  11. data/conf/redhat/fileserver.conf +12 -0
  12. data/conf/redhat/puppet.spec +130 -0
  13. data/conf/redhat/server.init +89 -0
  14. data/conf/redhat/server.sysconfig +9 -0
  15. data/examples/code/allatonce +2 -2
  16. data/examples/code/assignments +1 -1
  17. data/examples/code/classing +2 -2
  18. data/examples/code/components +2 -2
  19. data/examples/code/file.bl +5 -5
  20. data/examples/code/filedefaults +2 -2
  21. data/examples/code/fileparsing +1 -1
  22. data/examples/code/filerecursion +1 -1
  23. data/examples/code/functions +1 -1
  24. data/examples/code/groups +1 -1
  25. data/examples/code/importing +1 -1
  26. data/examples/code/nodes +1 -1
  27. data/examples/code/one +1 -1
  28. data/examples/code/relationships +2 -2
  29. data/examples/code/simpletests +5 -5
  30. data/examples/code/snippets/argumentdefaults +2 -2
  31. data/examples/code/snippets/casestatement +16 -8
  32. data/examples/code/snippets/classheirarchy.pp +4 -4
  33. data/examples/code/snippets/classincludes.pp +4 -4
  34. data/examples/code/snippets/classpathtest +2 -2
  35. data/examples/code/snippets/componentmetaparams.pp +11 -0
  36. data/examples/code/snippets/dirchmod +5 -5
  37. data/examples/code/snippets/emptyclass.pp +9 -0
  38. data/examples/code/snippets/failmissingexecpath.pp +1 -1
  39. data/examples/code/snippets/falsevalues.pp +1 -1
  40. data/examples/code/snippets/filecreate +5 -5
  41. data/examples/code/snippets/implicititeration +5 -5
  42. data/examples/code/snippets/multipleinstances +4 -4
  43. data/examples/code/snippets/namevartest +3 -3
  44. data/examples/code/snippets/scopetest +1 -1
  45. data/examples/code/snippets/selectorvalues.pp +3 -3
  46. data/examples/code/snippets/simpledefaults +2 -2
  47. data/examples/code/snippets/simpleselector +5 -5
  48. data/examples/code/snippets/singleary.pp +19 -0
  49. data/examples/root/etc/init.d/sleeper +3 -2
  50. data/ext/emacs/puppet-mode-init.el +6 -0
  51. data/ext/emacs/puppet-mode.el +189 -0
  52. data/ext/ldap/puppet.schema +17 -0
  53. data/ext/{module:puppet → module_puppet} +30 -31
  54. data/ext/vim/filetype.vim +9 -0
  55. data/ext/vim/puppet.vim +87 -0
  56. data/install.rb +63 -30
  57. data/lib/puppet.rb +216 -122
  58. data/lib/puppet/client.rb +51 -416
  59. data/lib/puppet/client/ca.rb +17 -0
  60. data/lib/puppet/client/dipper.rb +78 -0
  61. data/lib/puppet/client/file.rb +20 -0
  62. data/lib/puppet/client/log.rb +17 -0
  63. data/lib/puppet/client/master.rb +246 -0
  64. data/lib/puppet/client/proxy.rb +27 -0
  65. data/lib/puppet/client/status.rb +7 -0
  66. data/lib/puppet/config.rb +563 -13
  67. data/lib/puppet/daemon.rb +50 -22
  68. data/lib/puppet/element.rb +4 -4
  69. data/lib/puppet/event-loop.rb +1 -0
  70. data/lib/puppet/event-loop/better-definers.rb +367 -0
  71. data/lib/puppet/event-loop/event-loop.rb +355 -0
  72. data/lib/puppet/event-loop/signal-system.rb +220 -0
  73. data/lib/puppet/event.rb +9 -11
  74. data/lib/puppet/filetype.rb +195 -0
  75. data/lib/puppet/log.rb +35 -12
  76. data/lib/puppet/metric.rb +2 -2
  77. data/lib/puppet/networkclient.rb +145 -0
  78. data/lib/puppet/parameter.rb +335 -0
  79. data/lib/puppet/parser/ast.rb +42 -1453
  80. data/lib/puppet/parser/ast/astarray.rb +88 -0
  81. data/lib/puppet/parser/ast/branch.rb +47 -0
  82. data/lib/puppet/parser/ast/caseopt.rb +66 -0
  83. data/lib/puppet/parser/ast/casestatement.rb +78 -0
  84. data/lib/puppet/parser/ast/classdef.rb +78 -0
  85. data/lib/puppet/parser/ast/compdef.rb +111 -0
  86. data/lib/puppet/parser/ast/component.rb +105 -0
  87. data/lib/puppet/parser/ast/hostclass.rb +82 -0
  88. data/lib/puppet/parser/ast/leaf.rb +86 -0
  89. data/lib/puppet/parser/ast/node.rb +103 -0
  90. data/lib/puppet/parser/ast/nodedef.rb +68 -0
  91. data/lib/puppet/parser/ast/objectdef.rb +336 -0
  92. data/lib/puppet/parser/ast/objectparam.rb +30 -0
  93. data/lib/puppet/parser/ast/objectref.rb +76 -0
  94. data/lib/puppet/parser/ast/selector.rb +60 -0
  95. data/lib/puppet/parser/ast/typedefaults.rb +45 -0
  96. data/lib/puppet/parser/ast/vardef.rb +44 -0
  97. data/lib/puppet/parser/interpreter.rb +31 -14
  98. data/lib/puppet/parser/lexer.rb +2 -4
  99. data/lib/puppet/parser/parser.rb +332 -242
  100. data/lib/puppet/parser/scope.rb +55 -38
  101. data/lib/puppet/server.rb +43 -44
  102. data/lib/puppet/server/authstore.rb +3 -6
  103. data/lib/puppet/server/ca.rb +5 -2
  104. data/lib/puppet/server/filebucket.rb +2 -4
  105. data/lib/puppet/server/fileserver.rb +28 -12
  106. data/lib/puppet/server/logger.rb +15 -4
  107. data/lib/puppet/server/master.rb +62 -7
  108. data/lib/puppet/sslcertificates.rb +41 -607
  109. data/lib/puppet/sslcertificates/ca.rb +291 -0
  110. data/lib/puppet/sslcertificates/certificate.rb +283 -0
  111. data/lib/puppet/statechange.rb +6 -1
  112. data/lib/puppet/storage.rb +67 -56
  113. data/lib/puppet/transaction.rb +25 -9
  114. data/lib/puppet/transportable.rb +102 -22
  115. data/lib/puppet/type.rb +1096 -315
  116. data/lib/puppet/type/component.rb +30 -21
  117. data/lib/puppet/type/cron.rb +409 -448
  118. data/lib/puppet/type/exec.rb +234 -174
  119. data/lib/puppet/type/group.rb +65 -82
  120. data/lib/puppet/type/nameservice.rb +247 -3
  121. data/lib/puppet/type/nameservice/netinfo.rb +29 -40
  122. data/lib/puppet/type/nameservice/objectadd.rb +52 -66
  123. data/lib/puppet/type/nameservice/posix.rb +6 -194
  124. data/lib/puppet/type/package.rb +447 -295
  125. data/lib/puppet/type/package/apt.rb +51 -50
  126. data/lib/puppet/type/package/bsd.rb +82 -0
  127. data/lib/puppet/type/package/dpkg.rb +85 -88
  128. data/lib/puppet/type/package/rpm.rb +67 -63
  129. data/lib/puppet/type/package/sun.rb +119 -98
  130. data/lib/puppet/type/package/yum.rb +41 -37
  131. data/lib/puppet/type/parsedtype.rb +295 -0
  132. data/lib/puppet/type/parsedtype/host.rb +143 -0
  133. data/lib/puppet/type/parsedtype/port.rb +232 -0
  134. data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
  135. data/lib/puppet/type/pfile.rb +484 -460
  136. data/lib/puppet/type/pfile/checksum.rb +237 -181
  137. data/lib/puppet/type/pfile/content.rb +67 -0
  138. data/lib/puppet/type/pfile/ensure.rb +212 -0
  139. data/lib/puppet/type/pfile/group.rb +106 -105
  140. data/lib/puppet/type/pfile/mode.rb +98 -101
  141. data/lib/puppet/type/pfile/source.rb +228 -209
  142. data/lib/puppet/type/pfile/type.rb +18 -21
  143. data/lib/puppet/type/pfile/uid.rb +127 -130
  144. data/lib/puppet/type/pfilebucket.rb +68 -63
  145. data/lib/puppet/type/schedule.rb +341 -0
  146. data/lib/puppet/type/service.rb +351 -255
  147. data/lib/puppet/type/service/base.rb +9 -14
  148. data/lib/puppet/type/service/debian.rb +32 -38
  149. data/lib/puppet/type/service/init.rb +130 -130
  150. data/lib/puppet/type/service/smf.rb +48 -20
  151. data/lib/puppet/type/state.rb +229 -16
  152. data/lib/puppet/type/symlink.rb +51 -63
  153. data/lib/puppet/type/tidy.rb +105 -102
  154. data/lib/puppet/type/user.rb +118 -180
  155. data/lib/puppet/util.rb +100 -6
  156. data/test/certmgr/certmgr.rb +0 -1
  157. data/test/client/client.rb +4 -4
  158. data/test/executables/puppetbin.rb +7 -14
  159. data/test/executables/puppetca.rb +18 -24
  160. data/test/executables/puppetd.rb +7 -16
  161. data/test/executables/puppetmasterd.rb +7 -9
  162. data/test/executables/puppetmodule.rb +11 -16
  163. data/test/language/ast.rb +11 -7
  164. data/test/language/interpreter.rb +1 -1
  165. data/test/language/scope.rb +2 -0
  166. data/test/language/snippets.rb +30 -5
  167. data/test/language/transportable.rb +77 -0
  168. data/test/other/config.rb +316 -0
  169. data/test/other/events.rb +22 -21
  170. data/test/other/log.rb +14 -14
  171. data/test/other/metrics.rb +4 -8
  172. data/test/other/overrides.rb +5 -5
  173. data/test/other/relationships.rb +4 -2
  174. data/test/other/storage.rb +64 -3
  175. data/test/other/transactions.rb +20 -20
  176. data/test/parser/parser.rb +7 -4
  177. data/test/puppet/conffiles.rb +12 -12
  178. data/test/puppet/defaults.rb +13 -11
  179. data/test/puppet/utiltest.rb +14 -11
  180. data/test/puppettest.rb +156 -48
  181. data/test/server/bucket.rb +2 -2
  182. data/test/server/fileserver.rb +6 -6
  183. data/test/server/logger.rb +19 -11
  184. data/test/server/master.rb +33 -4
  185. data/test/server/server.rb +2 -7
  186. data/test/types/basic.rb +5 -7
  187. data/test/types/component.rb +22 -18
  188. data/test/types/cron.rb +111 -44
  189. data/test/types/exec.rb +116 -59
  190. data/test/types/file.rb +262 -137
  191. data/test/types/filebucket.rb +13 -15
  192. data/test/types/fileignoresource.rb +12 -16
  193. data/test/types/filesources.rb +73 -48
  194. data/test/types/filetype.rb +13 -15
  195. data/test/types/group.rb +15 -13
  196. data/test/types/host.rb +146 -0
  197. data/test/types/package.rb +74 -63
  198. data/test/types/port.rb +139 -0
  199. data/test/types/query.rb +8 -8
  200. data/test/types/schedule.rb +335 -0
  201. data/test/types/service.rb +137 -21
  202. data/test/types/sshkey.rb +140 -0
  203. data/test/types/symlink.rb +3 -5
  204. data/test/types/tidy.rb +5 -14
  205. data/test/types/type.rb +67 -11
  206. data/test/types/user.rb +25 -23
  207. metadata +186 -122
  208. data/lib/puppet/type/pfile/create.rb +0 -108
  209. data/lib/puppet/type/pprocess.rb +0 -97
  210. data/lib/puppet/type/typegen.rb +0 -149
  211. data/lib/puppet/type/typegen/filerecord.rb +0 -243
  212. data/lib/puppet/type/typegen/filetype.rb +0 -316
  213. data/test/other/state.rb +0 -106
@@ -1,16 +1,6 @@
1
1
  require 'puppet'
2
2
 
3
3
  module Puppet
4
- class State
5
- def self.objectaddflag
6
- if defined? @objectaddflag and @objectaddflag
7
- return @objectaddflag
8
- else
9
- return @name
10
- end
11
- end
12
- end
13
-
14
4
  module NameService
15
5
  module ObjectAdd
16
6
  # Verify that we've got the commands necessary to manage flat files.
@@ -25,6 +15,7 @@ module Puppet
25
15
  end
26
16
  end
27
17
 
18
+ # Does the object already exist?
28
19
  def self.exists?(obj)
29
20
  if obj.getinfo
30
21
  return true
@@ -33,16 +24,45 @@ module Puppet
33
24
  end
34
25
  end
35
26
 
36
- class ObjectAddGroup < POSIX::POSIXState
37
- def self.allatonce?
38
- true
27
+ # The base state class for <object>add operations.
28
+ class ObjectAddState < Puppet::State::NSSState
29
+ class << self
30
+ # Determine the flag to pass to our command.
31
+ def objectaddflag
32
+ unless defined? @objectaddflag
33
+ # Else, return the first letter of the name. I have to
34
+ # user a range here, else the character will show up
35
+ # as a number, rather than as a string, for some reason.
36
+ @objectaddflag = "-" + self.name.to_s[0,1]
37
+ Puppet.debug "Setting flag on %s to %s" %
38
+ [self.name, @objectaddflag]
39
+ end
40
+ return @objectaddflag
41
+ end
42
+
43
+ # Set the flag manually.
44
+ def setflag(value)
45
+ @objectaddflag = value
46
+ end
47
+ end
48
+ end
49
+
50
+ # The state class for doing group operations using groupadd or whatever.
51
+ # I could probably have abstracted the User and Group classes into
52
+ # a single class, but eh, it just didn't seem worth it.
53
+ class ObjectAddGroup < ObjectAddState
54
+ class << self
55
+ # This is hackish, but hey, it works.
56
+ def finish
57
+ @allatonce = true
58
+ end
39
59
  end
40
60
 
41
61
  def addcmd
42
62
  cmd = ["groupadd"]
43
63
  if gid = @parent.should(:gid)
44
64
  unless gid == :auto
45
- cmd << "-g" << gid
65
+ cmd << self.class.objectaddflag << gid
46
66
  end
47
67
  end
48
68
  cmd << @parent.name
@@ -64,25 +84,27 @@ module Puppet
64
84
  end
65
85
  end
66
86
 
67
- class GroupGID < ObjectAddGroup
68
- @objectaddflag = "-g"
69
- @autogen = true
70
- end
71
-
72
- class ObjectAddUser < POSIX::POSIXState
73
- def self.allatonce?
74
- true
87
+ # The class for adding users using 'adduser'.
88
+ class ObjectAddUser < ObjectAddState
89
+ class << self
90
+ # This is hackish, but hey, it works.
91
+ def finish
92
+ @allatonce = true
93
+ case self.name
94
+ when :home: setflag "-d"
95
+ end
96
+ end
75
97
  end
76
-
77
98
  def addcmd
78
99
  cmd = ["useradd"]
79
100
  @parent.eachstate { |state|
101
+ next if state.name == :ensure
80
102
  # the value needs to be quoted, mostly because -c might
81
103
  # have spaces in it
82
104
  cmd << state.class.objectaddflag << "'%s'" % state.should
83
105
  }
84
106
  # stupid fedora
85
- case Facter["distro"].value
107
+ case Facter["operatingsystem"].value
86
108
  when "Fedora", "RedHat":
87
109
  cmd << "-M"
88
110
  else
@@ -97,50 +119,14 @@ module Puppet
97
119
  end
98
120
 
99
121
  def modifycmd
100
- cmd = [
101
- "usermod",
102
- self.class.objectaddflag,
103
- "'%s'" % self.should,
104
- @parent.name
105
- ].join(" ")
122
+ cmd = [
123
+ "usermod",
124
+ self.class.objectaddflag,
125
+ "'%s'" % self.should,
126
+ @parent.name
127
+ ].join(" ")
106
128
  end
107
129
  end
108
- class UserUID < ObjectAddUser
109
- @objectaddflag = "-u"
110
- @autogen = true
111
- end
112
-
113
- class UserGID < ObjectAddUser
114
- @objectaddflag = "-g"
115
- @autogen = true
116
- end
117
-
118
- class UserComment < ObjectAddUser
119
- @objectaddflag = "-c"
120
- end
121
-
122
- class UserHome < ObjectAddUser
123
- @objectaddflag = "-d"
124
- @autogen = true
125
- end
126
-
127
- class UserShell < ObjectAddUser
128
- @objectaddflag = "-s"
129
- @autogen = true
130
- end
131
-
132
- class UserLocked < ObjectAddUser
133
- end
134
-
135
- class UserExpire < ObjectAddUser
136
- @objectaddflag = "-e"
137
- @autogen = true
138
- end
139
-
140
- class UserInactive < ObjectAddUser
141
- @objectaddflag = "-f"
142
- @autogen = true
143
- end
144
130
  end
145
131
  end
146
132
  end
@@ -1,200 +1,12 @@
1
1
  require 'puppet'
2
+ require 'puppet/type/nameservice'
2
3
 
3
4
  module Puppet
4
- class Type
5
- def self.posixmethod
6
- if defined? @posixmethod and @posixmethod
7
- return @posixmethod
8
- else
9
- return @name
10
- end
11
- end
12
- end
13
-
14
- module NameService
15
- # This is the base module for basically all of the NSS stuff. It
16
- # should be able to retrieve the info for almost any system, but
17
- # it can't create any information on its own. You need to define
18
- # a subclass of these classes to actually modify the system.
19
- module POSIX
20
- class POSIXState < Puppet::State
21
- class << self
22
- attr_accessor :extender
23
-
24
- def autogen?
25
- if defined? @autogen
26
- return @autogen
27
- else
28
- return false
29
- end
30
- end
31
-
32
- def optional?
33
- if defined? @optional
34
- return @optional
35
- else
36
- return false
37
- end
38
- end
39
- end
40
-
41
- def self.doc
42
- if defined? @extender
43
- @extender.doc
44
- else
45
- nil
46
- end
47
- end
48
-
49
- def self.complete
50
- mod = "Puppet::State::%s" %
51
- self.to_s.sub(/.+::/,'')
52
- begin
53
- modklass = eval(mod)
54
- rescue NameError
55
- raise Puppet::Error,
56
- "Could not find extender module %s for %s" %
57
- [mod, self.to_s]
58
- end
59
- include modklass
60
-
61
- self.extender = modklass
62
- end
63
-
64
- def self.posixmethod
65
- if defined? @extender
66
- if @extender.respond_to?(:posixmethod)
67
- return @extender.posixmethod
68
- else
69
- return @extender.name
70
- end
71
- else
72
- raise Puppet::DevError,
73
- "%s could not retrieve posixmethod" % self
74
- end
75
- end
76
-
77
- def self.name
78
- @extender.name
79
- end
80
-
81
- # we use the POSIX interfaces to retrieve all information,
82
- # so we don't have to worry about abstracting that across
83
- # the system
84
- def retrieve
85
- if obj = @parent.getinfo(true)
86
-
87
- if method = self.class.posixmethod || self.class.name
88
- @is = obj.send(method)
89
- else
90
- raise Puppet::DevError,
91
- "%s has no posixmethod" % self.class
92
- end
93
- else
94
- @is = :notfound
95
- end
96
- end
97
-
98
- def sync
99
- event = nil
100
- # they're in sync some other way
101
- if self.insync?
102
- return nil
103
- end
104
- if @is == :notfound
105
- self.retrieve
106
- if self.insync?
107
- return nil
108
- end
109
- end
110
- # if the object needs to be created or deleted,
111
- # depend on another method to do it all at once
112
- if @is == :notfound or self.should == :notfound
113
- event = syncname()
114
-
115
- return event
116
- # if the whole object is created at once, just return
117
- # an event saying so
118
- #if self.class.allatonce?
119
- # return event
120
- #end
121
- end
122
-
123
- unless @parent.exists?
124
- raise Puppet::DevError,
125
- "%s %s does not exist; cannot set %s" %
126
- [@parent.class.name, @parent.name, self.class.name]
127
- end
128
-
129
- # this needs to be set either by the individual state
130
- # or its parent class
131
- cmd = self.modifycmd
132
-
133
- self.debug "Executing %s" % cmd.inspect
134
-
135
- output = %x{#{cmd} 2>&1}
136
-
137
-
138
- unless $? == 0
139
- raise Puppet::Error, "Could not modify %s on %s %s: %s" %
140
- [self.class.name, @parent.class.name,
141
- @parent.name, output]
142
- end
143
-
144
- if event
145
- return event
146
- else
147
- return "#{@parent.class.name}_modified".intern
148
- end
149
- end
150
-
151
- private
152
- def syncname
153
- cmd = nil
154
- event = nil
155
- if self.should == :notfound
156
- # we need to remove the object...
157
- unless @parent.exists?
158
- # the group already doesn't exist
159
- return nil
160
- end
161
-
162
- # again, needs to be set by the ind. state or its
163
- # parent
164
- cmd = self.deletecmd
165
- type = "delete"
166
- else
167
- if @parent.exists?
168
- return nil
169
- end
170
-
171
- # blah blah, define elsewhere, blah blah
172
- cmd = self.addcmd
173
- type = "create"
174
- end
175
- self.debug "Executing %s" % cmd.inspect
176
-
177
- output = %x{#{cmd} 2>&1}
178
-
179
- unless $? == 0
180
- raise Puppet::Error, "Could not %s %s %s: %s" %
181
- [type, @parent.class.name, @parent.name, output]
182
- end
183
-
184
- # we want object creation to show up as one event,
185
- # not many
186
- unless self.class.allatonce?
187
- if type == "create"
188
- @parent.eachstate { |state|
189
- state.sync
190
- state.retrieve
191
- }
192
- end
193
- end
194
-
195
- return "#{@parent.class.name}_#{type}d".intern
196
- end
197
- end
5
+ class State
6
+ # The lowest-level state class for managing NSS/POSIX information. It
7
+ # at least knows how to retrieve information, but it does not know how
8
+ # to sync anything.
9
+ class POSIXState < NSSState
198
10
  end
199
11
  end
200
12
  end
@@ -4,43 +4,175 @@
4
4
  # systems.
5
5
 
6
6
  require 'puppet/type/state'
7
- require 'puppet/type/package/dpkg.rb'
8
- require 'puppet/type/package/apt.rb'
9
- require 'puppet/type/package/rpm.rb'
10
- require 'puppet/type/package/yum.rb'
11
- require 'puppet/type/package/sun.rb'
12
7
 
13
8
  module Puppet
14
9
  class PackageError < Puppet::Error; end
15
- class State
16
- class PackageInstalled < Puppet::State
17
- @name = :install
10
+ newtype(:package) do
11
+ @doc = "Manage packages. There is a basic dichotomy in package
12
+ support right now: Some package types (e.g., yum and apt) can
13
+ retrieve their own package files, while others (e.g., rpm and
14
+ sunpkg) cannot. For those package formats that cannot retrieve
15
+ their own files, you can use the ``source`` parameter to point to
16
+ the correct file.
17
+
18
+ Puppet will automatically guess the packaging format that you are
19
+ using based on the platform you are on, but you can override it
20
+ using the ``type`` parameter; obviously, if you specify that you
21
+ want to use ``rpm`` then the ``rpm`` tools must be available."
22
+
23
+ # Create a new packaging type
24
+ def self.newpkgtype(name, parent = nil, &block)
25
+ @pkgtypes ||= {}
26
+
27
+ if @pkgtypes.include?(name)
28
+ raise Puppet::DevError, "Package type %s already defined" % name
29
+ end
30
+
31
+ mod = Module.new
32
+ const_set("PkgType" + name.to_s.capitalize,mod)
33
+
34
+ # Add our parent, if it exists
35
+ if parent
36
+ unless @pkgtypes.include?(parent)
37
+ raise Puppet::DevError,
38
+ "No parent type %s for package type %s" %
39
+ [parent, name]
40
+ end
41
+ mod.send(:include, @pkgtypes[parent])
42
+ end
43
+
44
+ # And now define the support methods
45
+ code = %{
46
+ def self.name
47
+ "#{name}"
48
+ end
49
+
50
+ def self.to_s
51
+ "PkgType(#{name})"
52
+ end
53
+
54
+ def pkgtype
55
+ "#{name}"
56
+ end
57
+ }
58
+
59
+ mod.module_eval(code)
60
+
61
+ mod.module_eval(&block)
18
62
 
19
- @doc = "What state the package should be in. Specifying *true* will
20
- only result in a change if the package is not installed at all; use
21
- *latest* to keep the package (and, depending on the package system, its
22
- prerequisites) up to date. Specifying *false* will uninstall the
23
- package if it is installed. *true*/*false*/*latest*/``version``"
63
+ @pkgtypes[name] = mod
64
+ end
65
+
66
+ def self.pkgtype(name)
67
+ @pkgtypes[name]
68
+ end
69
+
70
+ def self.pkgtypes
71
+ @pkgtypes.keys
72
+ end
73
+
74
+ ensurable do
75
+ desc "What state the package should be in. The primary options
76
+ are *installed* (also called *present*), *uninstalled* (also
77
+ called *absent*), and *latest*. *latest* only makes sense for
78
+ those packaging formats that can retrieve new packages on
79
+ their own."
80
+
81
+ #munge do |value|
82
+ # # possible values are: true, false, and a version number
83
+ # case value
84
+ # when "latest":
85
+ # unless @parent.respond_to?(:latest)
86
+ # self.err @parent.inspect
87
+ # raise Puppet::Error,
88
+ # "Package type %s cannot install later versions" %
89
+ # @parent[:type].name
90
+ # end
91
+ # return :latest
92
+ # when true, :present:
93
+ # return :present
94
+ # when false, :absent:
95
+ # return :absent
96
+ # else
97
+ # # We allow them to set a should value however they want,
98
+ # # but only specific package types will be able to use this
99
+ # # value
100
+ # return value
101
+ # end
102
+ #end
103
+
104
+ newvalue(:present) do
105
+ @parent.install
106
+ end
107
+
108
+ newvalue(:absent) do
109
+ @parent.uninstall
110
+ end
111
+
112
+ # Alias the 'present' value.
113
+ aliasvalue(:installed, :present)
114
+ #newvalue(:installed) do
115
+ # self.set(:present)
116
+ #end
117
+
118
+ newvalue(:latest) do
119
+ unless @parent.respond_to?(:latest)
120
+ self.fail(
121
+ "Package type %s does not support specifying 'latest'" %
122
+ @parent[:type]
123
+ )
124
+ end
125
+ begin
126
+ @parent.update
127
+ rescue => detail
128
+ self.fail "Could not update: %s" % detail
129
+ end
130
+
131
+ if self.is == :absent
132
+ return :package_created
133
+ else
134
+ return :package_changed
135
+ end
136
+ end
24
137
 
25
138
  # Override the parent method, because we've got all kinds of
26
139
  # funky definitions of 'in sync'.
27
140
  def insync?
28
- # Iterate across all of the should values, and see how they turn out.
141
+ @should ||= []
142
+ # Iterate across all of the should values, and see how they
143
+ # turn out.
29
144
  @should.each { |should|
30
145
  case should
31
- when :installed
32
- unless @is == :notinstalled
146
+ when :present
147
+ unless @is == :absent
33
148
  return true
34
149
  end
35
150
  when :latest
36
- latest = @parent.latest
37
- if @is == latest
151
+ unless @parent.respond_to?(:latest)
152
+ self.fail(
153
+ "Package type %s does not support specifying 'latest'" %
154
+ @parent[:type]
155
+ )
156
+ end
157
+
158
+ begin
159
+ latest = @parent.latest
160
+ rescue => detail
161
+ self.fail "Could not get latest version: %s" % detail
162
+ end
163
+ case @is
164
+ when latest:
38
165
  return true
166
+ when :present:
167
+ if @parent[:version] == latest
168
+ return true
169
+ end
39
170
  else
40
- self.debug "latest %s is %s" % [@parent.name, latest]
171
+ self.debug "@is is %s, latest %s is %s" %
172
+ [@is, @parent.name, latest]
41
173
  end
42
- when :notinstalled
43
- if @is == :notinstalled
174
+ when :absent
175
+ if @is == :absent
44
176
  return true
45
177
  end
46
178
  when @is
@@ -53,324 +185,336 @@ module Puppet
53
185
 
54
186
  # This retrieves the current state
55
187
  def retrieve
56
- unless defined? @is
57
- @parent.retrieve
58
- end
188
+ #unless defined? @is
189
+ @parent.retrieve
190
+ #end
59
191
  end
60
192
 
61
- def shouldprocess(value)
62
- # possible values are: true, false, and a version number
63
- case value
64
- when "latest":
65
- unless @parent.respond_to?(:latest)
66
- self.err @parent.inspect
67
- raise Puppet::Error,
68
- "Package type %s does not support querying versions" %
69
- @parent[:type]
70
- end
71
- return :latest
72
- when true, :installed:
73
- return :installed
74
- when false, :notinstalled:
75
- return :notinstalled
193
+ def sync
194
+ value = self.should
195
+ unless value.is_a?(Symbol)
196
+ value = value.intern
197
+ end
198
+ # If we're a normal value, then just pass to the parent method
199
+ if self.class.values.include?(value)
200
+ #self.info "setting %s" % value
201
+ super
76
202
  else
77
- # We allow them to set a should value however they want,
78
- # but only specific package types will be able to use this
79
- # value
80
- return value
203
+ #self.info "updating from %s" % value
204
+ @parent.update
81
205
  end
82
206
  end
207
+ end
83
208
 
84
- def sync
85
- method = nil
86
- event = nil
87
- case @should[0]
88
- when :installed:
89
- method = :install
90
- event = :package_installed
91
- when :notinstalled:
92
- method = :remove
93
- event = :package_removed
94
- when :latest
95
- if @is == :notinstalled
96
- method = :install
97
- event = :package_installed
98
- else
99
- method = :update
100
- event = :package_updated
101
- end
102
- else
103
- unless ! @parent.respond_to?(:versionable?) or @parent.versionable?
104
- self.warning value
105
- raise Puppet::Error,
106
- "Package type %s does not support specifying versions" %
107
- @parent[:type]
108
- else
109
- method = :install
110
- event = :package_installed
111
- end
112
- end
209
+ # Packages are complicated because each package format has completely
210
+ # different commands.
211
+ attr_reader :pkgtype
212
+
213
+ newparam(:name) do
214
+ desc "The package name. This is the name that the packaging
215
+ system uses internally, which is sometimes (especially on Solaris)
216
+ a name that is basically useless to humans. If you want to
217
+ abstract package installation, then you can use aliases to provide
218
+ a common name to packages::
219
+
220
+ # In the 'openssl' class
221
+ $ssl = $operationgsystem ? {
222
+ solaris => SMCossl,
223
+ default => openssl
224
+ }
113
225
 
114
- if @parent.respond_to?(method)
115
- begin
116
- @parent.send(method)
117
- rescue => detail
118
- self.err "Could not run %s: %s" % [method, detail.to_s]
119
- raise
120
- end
121
- else
122
- raise Puppet::Error, "Packages of type %s do not support %s" %
123
- [@parent[:type], method]
124
- end
226
+ # It is not an error to set an alias to the same value as the
227
+ # object name.
228
+ package { $ssl:
229
+ ensure => installed,
230
+ alias => openssl
231
+ }
125
232
 
126
- return event
233
+ . etc. .
234
+
235
+ $ssh = $operationgsystem ? {
236
+ solaris => SMCossh,
237
+ default => openssh
238
+ }
239
+
240
+ # Use the alias to specify a dependency, rather than
241
+ # having another selector to figure it out again.
242
+ package { $ssh:
243
+ ensure => installed,
244
+ alias => openssh,
245
+ require => package[openssl]
246
+ }
247
+
248
+ "
249
+ isnamevar
250
+ end
251
+
252
+ newparam(:type) do
253
+ desc "The package format. You will seldom need to specify this --
254
+ Puppet will discover the appropriate format for your platform."
255
+
256
+ defaultto { @parent.class.default }
257
+
258
+ # We cannot log in this routine, because this gets called before
259
+ # there's a name for the package.
260
+ munge do |type|
261
+ @parent.type2module(type)
127
262
  end
128
263
  end
129
- end
130
264
 
131
- class Type
132
- # packages are complicated because each package format has completely
133
- # different commands. We need some way to convert specific packages
134
- # into the general package object...
135
- class Package < Type
136
- attr_reader :version, :pkgtype
137
-
138
- @pkgtypes = [
139
- Puppet::PackagingType::APT,
140
- Puppet::PackagingType::DPKG,
141
- Puppet::PackagingType::RPM,
142
- Puppet::PackagingType::Yum,
143
- Puppet::PackagingType::Sun
144
- ]
145
-
146
- @pkgtypehash = {}
147
-
148
- # Now collect the name of each type and store it thusly
149
- @pkgtypes.each { |type|
150
- if type.respond_to?(:typename)
151
- @pkgtypehash[type.typename] = type
152
- else
153
- name = type.to_s.sub(/.+::/, '').downcase.intern
154
- @pkgtypehash[name] = type
265
+ newparam(:source) do
266
+ desc "From where to retrieve the package."
267
+
268
+ validate do |value|
269
+ unless value =~ /^#{File::SEPARATOR}/ or value =~ /\w+:\/\//
270
+ self.fail(
271
+ "Package sources must be fully qualified files or URLs, depending on the platform."
272
+ )
155
273
  end
156
- }
274
+ end
275
+ end
276
+ newparam(:instance) do
277
+ desc "A read-only parameter set by the package."
278
+ end
279
+ newparam(:status) do
280
+ desc "A read-only parameter set by the package."
281
+ end
157
282
 
158
- @states = [
159
- Puppet::State::PackageInstalled
160
- ]
161
- #:version,
162
- @parameters = [
163
- :name,
164
- :type,
165
- :instance,
166
- :status,
167
- :category,
168
- :platform,
169
- :root,
170
- :vendor,
171
- :description
172
- ]
173
-
174
- @paramdoc[:name] = "The package name."
175
- @paramdoc[:type] = "The package format. Currently supports " +
176
- @pkgtypes.collect {|t|
177
- "``" + t.name.to_s + "``"
178
- }.join(", ") + "."
179
- @paramdoc[:instance] = "A read-only parameter set by the package."
180
- @paramdoc[:status] = "A read-only parameter set by the package."
181
- #@paramdoc[:version] = "A read-only parameter set by the package."
182
- @paramdoc[:category] = "A read-only parameter set by the package."
183
- @paramdoc[:platform] = "A read-only parameter set by the package."
184
- @paramdoc[:root] = "A read-only parameter set by the package."
185
- @paramdoc[:vendor] = "A read-only parameter set by the package."
186
- @paramdoc[:description] = "A read-only parameter set by the package."
187
-
188
- @doc = "Manage packages. Eventually will support retrieving packages
189
- from remote sources but currently only supports packaging
190
- systems which can retrieve their own packages, like ``apt``."
191
- @name = :package
192
- @namevar = :name
193
- @listed = false
283
+ newparam(:answerfile) do
284
+ desc "A file containing any necessary answers to questions asked by
285
+ the package. This is currently only used on Solaris. The
286
+ value will be validated according to system rules, which in
287
+ the case of Solaris means that it should either be a fully qualified
288
+ path or it should be in /var/sadm/install/admin."
289
+ end
194
290
 
195
- @allowedmethods = [:types]
291
+ # FIXME Version is screwy -- most package systems can't specify a
292
+ # version, but people will definitely want to query versions, so
293
+ # it almost seems like versions should be a read-only state,
294
+ # supporting syncing only in certain cases.
295
+ newparam(:version) do
296
+ desc "For some platforms this is a read-only parameter set by the
297
+ package, but for others, setting this parameter will cause
298
+ the package of that version to be installed. It just depends
299
+ on the features of the packaging system."
300
+
301
+ # validate do |value|
302
+ # unless @parent.respond_to?(:versionable?) and @parent.versionable?
303
+ # raise Puppet::Error,
304
+ # "Package type %s does not support specifying versions." %
305
+ # @parent.pkgtype
306
+ # end
307
+ # end
308
+ end
309
+ newparam(:category) do
310
+ desc "A read-only parameter set by the package."
311
+ end
312
+ newparam(:platform) do
313
+ desc "A read-only parameter set by the package."
314
+ end
315
+ newparam(:root) do
316
+ desc "A read-only parameter set by the package."
317
+ end
318
+ newparam(:vendor) do
319
+ desc "A read-only parameter set by the package."
320
+ end
321
+ newparam(:description) do
322
+ desc "A read-only parameter set by the package."
323
+ end
324
+ @listed = false
196
325
 
197
- @default = nil
198
- @platform = nil
326
+ @allowedmethods = [:types]
199
327
 
200
- class << self
201
- attr_reader :listed
202
- end
328
+ @default = nil
329
+ @platform = nil
203
330
 
204
- def self.clear
205
- @listed = false
206
- super
207
- end
331
+ class << self
332
+ attr_reader :listed
333
+ end
208
334
 
209
- # Cache and return the default package type for our current
210
- # platform.
211
- def self.default
212
- if @default.nil?
213
- self.init
214
- end
335
+ def self.clear
336
+ @listed = false
337
+ super
338
+ end
215
339
 
216
- return @default
340
+ # Cache and return the default package type for our current
341
+ # platform.
342
+ def self.default
343
+ if @default.nil?
344
+ self.init
217
345
  end
218
346
 
219
- # Figure out what the default package type is for the platform
220
- # on which we're running.
221
- def self.init
222
- unless @platform = Facter["operatingsystem"].value.downcase
223
- raise Puppet::DevError.new(
224
- "Must know platform for package management"
225
- )
226
- end
227
- case @platform
228
- when "sunos": @default = :sun
229
- when "linux":
230
- case Facter["distro"].value.downcase
231
- when "gentoo":
232
- Puppet.notice "No support for gentoo yet"
233
- @default = nil
234
- when "debian": @default = :apt
235
- when "fedora": @default = :yum
236
- when "redhat": @default = :rpm
237
- else
238
- Puppet.warning "Using rpm as default type for %s" %
239
- Facter["distro"].value
240
- @default = :rpm
241
- end
347
+ return @default
348
+ end
349
+
350
+ # Figure out what the default package type is for the platform
351
+ # on which we're running.
352
+ def self.init
353
+ unless @platform = Facter["operatingsystem"].value.downcase
354
+ raise Puppet::DevError.new(
355
+ "Must know platform for package management"
356
+ )
357
+ end
358
+ case @platform
359
+ when "solaris": @default = :sunpkg
360
+ when "gentoo":
361
+ Puppet.notice "No support for gentoo yet"
362
+ @default = nil
363
+ when "debian": @default = :apt
364
+ when "fedora": @default = :yum
365
+ when "redhat": @default = :rpm
366
+ when "openbsd": @default = :bsd
367
+ else
368
+ if Facter["kernel"] == "Linux"
369
+ Puppet.warning "Defaulting to RPM for %s" %
370
+ Facter["operatingsystem"].value
371
+ @default = nil
242
372
  else
373
+ Puppet.warning "No default package system for %s" %
374
+ Facter["operatingsystem"].value
243
375
  @default = nil
244
376
  end
245
377
  end
378
+ end
246
379
 
247
- def self.getpkglist
248
- if @types.nil?
249
- if @default.nil?
250
- self.init
251
- end
252
- @types = [@default]
380
+ def self.getpkglist
381
+ if @types.nil?
382
+ if @default.nil?
383
+ self.init
253
384
  end
385
+ @types = [@default]
386
+ end
254
387
 
255
- list = @types.collect { |type|
256
- if typeobj = Puppet::PackagingType[type]
257
- # pull all of the objects
258
- typeobj.list
388
+ list = @types.collect { |type|
389
+ if typeobj = Puppet::PackagingType[type]
390
+ # pull all of the objects
391
+ typeobj.list
392
+ else
393
+ raise Puppet::Error, "Could not find package type '%s'" % type
394
+ end
395
+ }.flatten
396
+ @listed = true
397
+ return list
398
+ end
399
+
400
+ def self.installedpkg(hash)
401
+ # this is from code, so we don't have to do as much checking
402
+ name = hash[:name]
403
+ hash.delete(:name)
404
+
405
+ # if it already exists, modify the existing one
406
+ if object = Package[name]
407
+ states = {}
408
+ object.eachstate { |state|
409
+ Puppet.debug "Adding %s" % state.name.inspect
410
+ states[state.name] = state
411
+ }
412
+ hash.each { |var,value|
413
+ if states.include?(var)
414
+ Puppet.debug "%s is a set state" % var.inspect
415
+ states[var].is = value
259
416
  else
260
- raise "Could not find package type '%s'" % type
261
- end
262
- }.flatten
263
- @listed = true
264
- return list
265
- end
417
+ Puppet.debug "%s is not a set state" % var.inspect
418
+ if object[var] and object[var] != value
419
+ Puppet.warning "Overriding %s => %s on %s with %s" %
420
+ [var,object[var],name,value]
421
+ end
266
422
 
267
- def Package.installedpkg(hash)
268
- # this is from code, so we don't have to do as much checking
269
- name = hash[:name]
270
- hash.delete(:name)
271
-
272
- # if it already exists, modify the existing one
273
- if object = Package[name]
274
- states = {}
275
- object.eachstate { |state|
276
- Puppet.debug "Adding %s" % state.name.inspect
277
- states[state.name] = state
278
- }
279
- hash.each { |var,value|
423
+ #object.state(var).is = value
424
+
425
+ # swap the values if we're a state
280
426
  if states.include?(var)
281
- Puppet.debug "%s is a set state" % var.inspect
427
+ Puppet.debug "Swapping %s because it's a state" % var
282
428
  states[var].is = value
429
+ states[var].should = nil
283
430
  else
284
- Puppet.debug "%s is not a set state" % var.inspect
285
- if object[var] and object[var] != value
286
- Puppet.warning "Overriding %s => %s on %s with %s" %
287
- [var,object[var],name,value]
288
- end
289
-
290
- #object.state(var).is = value
291
-
292
- # swap the values if we're a state
293
- if states.include?(var)
294
- Puppet.debug "Swapping %s because it's a state" % var
295
- states[var].is = value
296
- states[var].should = nil
297
- else
298
- Puppet.debug "%s is not a state" % var.inspect
299
- Puppet.debug "States are %s" % states.keys.collect { |st|
300
- st.inspect
301
- }.join(" ")
302
- end
431
+ Puppet.debug "%s is not a state" % var.inspect
432
+ Puppet.debug "States are %s" % states.keys.collect { |st|
433
+ st.inspect
434
+ }.join(" ")
303
435
  end
304
- }
305
- return object
306
- else # just create it
307
- obj = self.create(:name => name)
308
- hash.each { |var,value|
309
- obj.addis(var,value)
310
- }
311
- return obj
312
- end
436
+ end
437
+ }
438
+ return object
439
+ else # just create it
440
+ obj = self.create(:name => name)
441
+ hash.each { |var,value|
442
+ obj.addis(var,value)
443
+ }
444
+ return obj
313
445
  end
446
+ end
314
447
 
315
- # Retrieve a package type by name; names are symbols.
316
- def self.pkgtype(pkgtype)
317
- if pkgtype.is_a?(String)
318
- pkgtype = pkgtype.intern
448
+ # The 'query' method returns a hash of info if the package
449
+ # exists and returns nil if it does not.
450
+ def exists?
451
+ self.query
452
+ end
453
+
454
+ # okay, there are two ways that a package could be created...
455
+ # either through the language, in which case the hash's values should
456
+ # be set in 'should', or through comparing against the system, in which
457
+ # case the hash's values should be set in 'is'
458
+ def initialize(hash)
459
+ self.initvars
460
+ type = nil
461
+ [:type, "type"].each { |label|
462
+ if hash.include?(label)
463
+ type = hash[label]
464
+ hash.delete(label)
319
465
  end
320
- return @pkgtypehash[pkgtype]
466
+ }
467
+ if type
468
+ self[:type] = type
469
+ else
470
+ self.setdefaults(:type)
321
471
  end
322
472
 
323
- # okay, there are two ways that a package could be created...
324
- # either through the language, in which case the hash's values should
325
- # be set in 'should', or through comparing against the system, in which
326
- # case the hash's values should be set in 'is'
327
- def initialize(hash)
328
- type = hash["type"] || hash[:type] || self.class.default
329
- self.type2module(type)
330
-
331
- super
473
+ super
332
474
 
333
- self.debug "Extending to package type %s" % [@type]
475
+ #unless @states.include?(:ensure)
476
+ # self.debug "Defaulting to installing a package"
477
+ # self[:ensure] = true
478
+ #end
334
479
 
335
- unless @states.include?(:install)
336
- self.debug "Defaulting to installing a package"
337
- self[:install] = true
338
- end
339
-
340
- unless @parameters.include?(:type)
341
- self[:type] = self.class.default
342
- end
480
+ unless @parameters.include?(:type)
481
+ self[:type] = self.class.default
343
482
  end
483
+ end
344
484
 
345
- def retrieve
346
- if hash = self.query
347
- hash.each { |param, value|
348
- unless self.class.validarg?(param)
349
- hash.delete(param)
350
- end
351
- }
485
+ def retrieve
486
+ # If the package is installed, then retrieve all of the information
487
+ # about it and set it appropriately.
488
+ #@states[:ensure].retrieve
489
+ if hash = self.query
490
+ hash.each { |param, value|
491
+ unless self.class.validattr?(param)
492
+ hash.delete(param)
493
+ end
494
+ }
352
495
 
353
- hash.each { |param, value|
354
- self.is = [param, value]
355
- }
356
- else
357
- self.class.validstates.each { |name|
358
- self.is = [name, :notinstalled]
359
- }
360
- end
496
+ hash.each { |param, value|
497
+ self.is = [param, value]
498
+ }
499
+ else
500
+ # Else just mark all of the states absent.
501
+ self.class.validstates.each { |name|
502
+ self.is = [name, :absent]
503
+ }
361
504
  end
505
+ end
362
506
 
363
- # Extend the package with the appropriate package type.
364
- def type2module(typename)
365
- if type = self.class.pkgtype(typename)
366
- @type = type
367
- self.extend(type)
368
- else
369
- raise Puppet::Error, "Invalid package type %s" % typename
370
- end
507
+ # Extend the package with the appropriate package type.
508
+ def type2module(typename)
509
+ if type = self.class.pkgtype(typename)
510
+ self.extend(type)
511
+
512
+ return type
513
+ else
514
+ self.fail "Invalid package type %s" % typename
371
515
  end
372
- end # Puppet::Type::Package
373
- end
516
+ end
517
+ end # Puppet.type(:package)
374
518
 
375
519
  # this is how we retrieve packages
376
520
  class PackageSource
@@ -385,7 +529,7 @@ module Puppet
385
529
  if source = @@sources[type]
386
530
  return source.retrieve(file)
387
531
  else
388
- raise "Unknown package source: %s" % type
532
+ raise Puppet::Error, "Unknown package source: %s" % type
389
533
  end
390
534
  end
391
535
 
@@ -411,10 +555,18 @@ module Puppet
411
555
  if FileTest.exists?(file)
412
556
  return file
413
557
  else
414
- raise "File %s does not exist" % file
558
+ raise Puppet::Error, "File %s does not exist" % file
415
559
  end
416
560
  }
417
561
  }
418
562
  end
419
563
 
420
- # $Id: package.rb 731 2005-10-26 04:44:25Z luke $
564
+ # The order these are loaded is important.
565
+ require 'puppet/type/package/dpkg.rb'
566
+ require 'puppet/type/package/apt.rb'
567
+ require 'puppet/type/package/rpm.rb'
568
+ require 'puppet/type/package/yum.rb'
569
+ require 'puppet/type/package/sun.rb'
570
+ require 'puppet/type/package/bsd.rb'
571
+
572
+ # $Id: package.rb 888 2006-02-08 22:57:07Z luke $