puppet 2.7.9 → 2.7.11

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 (187) hide show
  1. data/CHANGELOG +413 -0
  2. data/README_DEVELOPER.md +28 -0
  3. data/conf/redhat/puppet.spec +10 -1
  4. data/conf/solaris/pkginfo +1 -1
  5. data/conf/suse/puppet.spec +7 -4
  6. data/ext/envpuppet.bat +13 -0
  7. data/ext/rack/files/apache2.conf +4 -0
  8. data/install.rb +4 -8
  9. data/lib/puppet.rb +1 -1
  10. data/lib/puppet/agent.rb +7 -0
  11. data/lib/puppet/agent/disabler.rb +27 -0
  12. data/lib/puppet/agent/locker.rb +0 -10
  13. data/lib/puppet/application.rb +3 -0
  14. data/lib/puppet/application/agent.rb +13 -3
  15. data/lib/puppet/application/apply.rb +6 -6
  16. data/lib/puppet/application/cert.rb +5 -5
  17. data/lib/puppet/application/instrumentation_data.rb +4 -0
  18. data/lib/puppet/application/instrumentation_listener.rb +4 -0
  19. data/lib/puppet/application/instrumentation_probe.rb +4 -0
  20. data/lib/puppet/configurer.rb +3 -1
  21. data/lib/puppet/configurer/downloader.rb +4 -2
  22. data/lib/puppet/configurer/fact_handler.rb +0 -21
  23. data/lib/puppet/daemon.rb +3 -4
  24. data/lib/puppet/defaults.rb +2 -2
  25. data/lib/puppet/face/instrumentation_data.rb +28 -0
  26. data/lib/puppet/face/instrumentation_listener.rb +96 -0
  27. data/lib/puppet/face/instrumentation_probe.rb +77 -0
  28. data/lib/puppet/face/module/list.rb +64 -0
  29. data/lib/puppet/face/module/uninstall.rb +50 -0
  30. data/lib/puppet/face/node/clean.rb +1 -4
  31. data/lib/puppet/feature/base.rb +1 -0
  32. data/lib/puppet/file_serving/content.rb +1 -1
  33. data/lib/puppet/indirector/facts/facter.rb +20 -7
  34. data/lib/puppet/indirector/facts/inventory_active_record.rb +14 -11
  35. data/lib/puppet/indirector/indirection.rb +7 -0
  36. data/lib/puppet/indirector/instrumentation_data.rb +3 -0
  37. data/lib/puppet/indirector/instrumentation_data/local.rb +19 -0
  38. data/lib/puppet/indirector/instrumentation_data/rest.rb +5 -0
  39. data/lib/puppet/indirector/instrumentation_listener.rb +3 -0
  40. data/lib/puppet/indirector/instrumentation_listener/local.rb +23 -0
  41. data/lib/puppet/indirector/instrumentation_listener/rest.rb +5 -0
  42. data/lib/puppet/indirector/instrumentation_probe.rb +3 -0
  43. data/lib/puppet/indirector/instrumentation_probe/local.rb +24 -0
  44. data/lib/puppet/indirector/instrumentation_probe/rest.rb +5 -0
  45. data/lib/puppet/indirector/rest.rb +1 -1
  46. data/lib/puppet/module.rb +13 -17
  47. data/lib/puppet/module_tool/applications.rb +1 -0
  48. data/lib/puppet/module_tool/applications/uninstaller.rb +33 -0
  49. data/lib/puppet/module_tool/contents_description.rb +1 -1
  50. data/lib/puppet/network/server.rb +2 -3
  51. data/lib/puppet/node/environment.rb +16 -3
  52. data/lib/puppet/parser/ast/leaf.rb +1 -1
  53. data/lib/puppet/parser/functions/create_resources.rb +1 -1
  54. data/lib/puppet/parser/type_loader.rb +1 -1
  55. data/lib/puppet/property.rb +46 -14
  56. data/lib/puppet/provider.rb +13 -4
  57. data/lib/puppet/provider/augeas/augeas.rb +6 -4
  58. data/lib/puppet/provider/group/pw.rb +24 -10
  59. data/lib/puppet/provider/nameservice/directoryservice.rb +146 -37
  60. data/lib/puppet/provider/package/pip.rb +1 -1
  61. data/lib/puppet/provider/package/yum.rb +1 -2
  62. data/lib/puppet/provider/service/debian.rb +14 -0
  63. data/lib/puppet/provider/service/launchd.rb +1 -1
  64. data/lib/puppet/provider/service/smf.rb +2 -2
  65. data/lib/puppet/provider/user/pw.rb +56 -2
  66. data/lib/puppet/provider/user/user_role_add.rb +32 -22
  67. data/lib/puppet/provider/user/windows_adsi.rb +1 -0
  68. data/lib/puppet/rails/benchmark.rb +1 -1
  69. data/lib/puppet/reports/store.rb +8 -1
  70. data/lib/puppet/resource/catalog.rb +5 -1
  71. data/lib/puppet/simple_graph.rb +11 -14
  72. data/lib/puppet/transaction.rb +10 -4
  73. data/lib/puppet/transaction/report.rb +9 -3
  74. data/lib/puppet/type.rb +19 -7
  75. data/lib/puppet/type/exec.rb +1 -1
  76. data/lib/puppet/type/file.rb +4 -1
  77. data/lib/puppet/type/file/ensure.rb +5 -1
  78. data/lib/puppet/type/file/mode.rb +45 -10
  79. data/lib/puppet/type/file/source.rb +4 -0
  80. data/lib/puppet/type/host.rb +17 -3
  81. data/lib/puppet/type/k5login.rb +3 -2
  82. data/lib/puppet/type/schedule.rb +3 -2
  83. data/lib/puppet/util.rb +83 -27
  84. data/lib/puppet/util/anonymous_filelock.rb +36 -0
  85. data/lib/puppet/util/docs.rb +18 -2
  86. data/lib/puppet/util/instrumentation.rb +173 -0
  87. data/lib/puppet/util/instrumentation/data.rb +34 -0
  88. data/lib/puppet/util/instrumentation/indirection_probe.rb +29 -0
  89. data/lib/puppet/util/instrumentation/instrumentable.rb +143 -0
  90. data/lib/puppet/util/instrumentation/listener.rb +60 -0
  91. data/lib/puppet/util/instrumentation/listeners/log.rb +29 -0
  92. data/lib/puppet/util/instrumentation/listeners/performance.rb +30 -0
  93. data/lib/puppet/util/monkey_patches.rb +8 -0
  94. data/lib/puppet/util/pidlock.rb +21 -25
  95. data/lib/puppet/util/rdoc/parser.rb +2 -2
  96. data/lib/puppet/util/reference.rb +8 -23
  97. data/lib/puppet/util/retryaction.rb +48 -0
  98. data/lib/puppet/util/suidmanager.rb +70 -39
  99. data/lib/puppet/util/symbolic_file_mode.rb +140 -0
  100. data/spec/integration/configurer_spec.rb +5 -0
  101. data/spec/integration/indirector/direct_file_server_spec.rb +1 -1
  102. data/spec/integration/indirector/file_content/file_server_spec.rb +7 -7
  103. data/spec/integration/provider/package_spec.rb +7 -0
  104. data/spec/unit/agent/disabler_spec.rb +60 -0
  105. data/spec/unit/agent/locker_spec.rb +0 -12
  106. data/spec/unit/agent_spec.rb +8 -0
  107. data/spec/unit/application/agent_spec.rb +38 -1
  108. data/spec/unit/application/apply_spec.rb +34 -40
  109. data/spec/unit/application/cert_spec.rb +1 -1
  110. data/spec/unit/application_spec.rb +6 -0
  111. data/spec/unit/configurer/downloader_spec.rb +29 -10
  112. data/spec/unit/configurer/fact_handler_spec.rb +5 -29
  113. data/spec/unit/configurer_spec.rb +8 -8
  114. data/spec/unit/daemon_spec.rb +12 -26
  115. data/spec/unit/face/instrumentation_data.rb +7 -0
  116. data/spec/unit/face/instrumentation_listener.rb +38 -0
  117. data/spec/unit/face/instrumentation_probe.rb +21 -0
  118. data/spec/unit/face/node_spec.rb +111 -111
  119. data/spec/unit/file_serving/content_spec.rb +2 -2
  120. data/spec/unit/indirector/facts/facter_spec.rb +25 -3
  121. data/spec/unit/indirector/facts/inventory_active_record_spec.rb +14 -4
  122. data/spec/unit/indirector/instrumentation_data/local_spec.rb +52 -0
  123. data/spec/unit/indirector/instrumentation_data/rest_spec.rb +11 -0
  124. data/spec/unit/indirector/instrumentation_listener/local_spec.rb +65 -0
  125. data/spec/unit/indirector/instrumentation_listener/rest_spec.rb +11 -0
  126. data/spec/unit/indirector/instrumentation_probe/local_spec.rb +65 -0
  127. data/spec/unit/indirector/instrumentation_probe/rest_spec.rb +11 -0
  128. data/spec/unit/module_spec.rb +39 -125
  129. data/spec/unit/module_tool/uninstaller_spec.rb +44 -0
  130. data/spec/unit/network/server_spec.rb +2 -20
  131. data/spec/unit/node/environment_spec.rb +76 -58
  132. data/spec/unit/parser/ast/asthash_spec.rb +1 -2
  133. data/spec/unit/parser/ast/leaf_spec.rb +16 -0
  134. data/spec/unit/property/keyvalue_spec.rb +5 -2
  135. data/spec/unit/property_spec.rb +260 -159
  136. data/spec/unit/provider/augeas/augeas_spec.rb +2 -2
  137. data/spec/unit/provider/group/pw_spec.rb +81 -0
  138. data/spec/unit/provider/nameservice/directoryservice_spec.rb +102 -0
  139. data/spec/unit/provider/package/pip_spec.rb +7 -0
  140. data/spec/unit/provider/package/yum_spec.rb +45 -1
  141. data/spec/unit/provider/service/debian_spec.rb +15 -0
  142. data/spec/unit/provider/service/launchd_spec.rb +48 -43
  143. data/spec/unit/provider/service/smf_spec.rb +3 -3
  144. data/spec/unit/provider/user/pw_spec.rb +183 -0
  145. data/spec/unit/provider/user/user_role_add_spec.rb +46 -39
  146. data/spec/unit/provider/user/windows_adsi_spec.rb +1 -0
  147. data/spec/unit/provider_spec.rb +32 -0
  148. data/spec/unit/reports/store_spec.rb +19 -1
  149. data/spec/unit/simple_graph_spec.rb +34 -19
  150. data/spec/unit/ssl/certificate_factory_spec.rb +3 -3
  151. data/spec/unit/transaction/report_spec.rb +29 -1
  152. data/spec/unit/transaction_spec.rb +32 -46
  153. data/spec/unit/type/file/mode_spec.rb +1 -1
  154. data/spec/unit/type/file/source_spec.rb +28 -3
  155. data/spec/unit/type/file_spec.rb +17 -16
  156. data/spec/unit/type/host_spec.rb +527 -0
  157. data/spec/unit/type/k5login_spec.rb +115 -0
  158. data/spec/unit/type/schedule_spec.rb +6 -6
  159. data/spec/unit/type_spec.rb +51 -0
  160. data/spec/unit/util/anonymous_filelock_spec.rb +78 -0
  161. data/spec/unit/util/execution_stub_spec.rb +2 -1
  162. data/spec/unit/util/instrumentation/data_spec.rb +44 -0
  163. data/spec/unit/util/instrumentation/indirection_probe_spec.rb +19 -0
  164. data/spec/unit/util/instrumentation/instrumentable_spec.rb +186 -0
  165. data/spec/unit/util/instrumentation/listener_spec.rb +100 -0
  166. data/spec/unit/util/instrumentation/listeners/log_spec.rb +34 -0
  167. data/spec/unit/util/instrumentation/listeners/performance_spec.rb +36 -0
  168. data/spec/unit/util/instrumentation_spec.rb +181 -0
  169. data/spec/unit/util/pidlock_spec.rb +208 -0
  170. data/spec/unit/util/rdoc/parser_spec.rb +1 -1
  171. data/spec/unit/util/reference_spec.rb +16 -6
  172. data/spec/unit/util/retryaction_spec.rb +62 -0
  173. data/spec/unit/util/suidmanager_spec.rb +101 -83
  174. data/spec/unit/util/symbolic_file_mode_spec.rb +182 -0
  175. data/spec/unit/util_spec.rb +126 -0
  176. data/tasks/rake/apple.rake +176 -0
  177. data/tasks/rake/templates/prototype.plist.erb +38 -0
  178. metadata +61 -13
  179. data/lib/puppet/application/module.rb +0 -3
  180. data/lib/puppet/face/module.rb +0 -12
  181. data/spec/unit/face/module/build_spec.rb +0 -30
  182. data/spec/unit/face/module/changes_spec.rb +0 -30
  183. data/spec/unit/face/module/clean_spec.rb +0 -30
  184. data/spec/unit/face/module/generate_spec.rb +0 -30
  185. data/spec/unit/face/module/install_spec.rb +0 -75
  186. data/spec/unit/face/module/search_spec.rb +0 -40
  187. data/test/util/pidlock.rb +0 -126
@@ -1,12 +1,19 @@
1
1
  require 'puppet/util/docs'
2
2
  require 'puppet/indirector/envelope'
3
3
  require 'puppet/indirector/request'
4
+ require 'puppet/util/instrumentation/instrumentable'
4
5
 
5
6
  # The class that connects functional classes with their different collection
6
7
  # back-ends. Each indirection has a set of associated terminus classes,
7
8
  # each of which is a subclass of Puppet::Indirector::Terminus.
8
9
  class Puppet::Indirector::Indirection
9
10
  include Puppet::Util::Docs
11
+ extend Puppet::Util::Instrumentation::Instrumentable
12
+
13
+ probe :find, :label => Proc.new { |parent, key, *args| "find_#{parent.name}_#{parent.terminus_class}" }, :data => Proc.new { |parent, key, *args| { :key => key }}
14
+ probe :save, :label => Proc.new { |parent, key, *args| "save_#{parent.name}_#{parent.terminus_class}" }, :data => Proc.new { |parent, key, *args| { :key => key }}
15
+ probe :search, :label => Proc.new { |parent, key, *args| "search_#{parent.name}_#{parent.terminus_class}" }, :data => Proc.new { |parent, key, *args| { :key => key }}
16
+ probe :destroy, :label => Proc.new { |parent, key, *args| "destroy_#{parent.name}_#{parent.terminus_class}" }, :data => Proc.new { |parent, key, *args| { :key => key }}
10
17
 
11
18
  @@indirections = []
12
19
 
@@ -0,0 +1,3 @@
1
+ # A stub class, so our constants work.
2
+ class Puppet::Indirector::InstrumentationData
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'puppet/indirector/instrumentation_data'
2
+
3
+ class Puppet::Indirector::InstrumentationData::Local < Puppet::Indirector::Code
4
+ def find(request)
5
+ model.new(request.key)
6
+ end
7
+
8
+ def search(request)
9
+ raise Puppet::DevError, "You cannot search for instrumentation data"
10
+ end
11
+
12
+ def save(request)
13
+ raise Puppet::DevError, "You cannot save instrumentation data"
14
+ end
15
+
16
+ def destroy(request)
17
+ raise Puppet::DevError, "You cannot remove instrumentation data"
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ require 'puppet/indirector/rest'
2
+ require 'puppet/indirector/instrumentation_data'
3
+
4
+ class Puppet::Indirector::InstrumentationData::Rest < Puppet::Indirector::REST
5
+ end
@@ -0,0 +1,3 @@
1
+ # A stub class, so our constants work.
2
+ class Puppet::Indirector::InstrumentationListener
3
+ end
@@ -0,0 +1,23 @@
1
+ require 'puppet/indirector/instrumentation_listener'
2
+
3
+ class Puppet::Indirector::InstrumentationListener::Local < Puppet::Indirector::Code
4
+ def find(request)
5
+ Puppet::Util::Instrumentation[request.key]
6
+ end
7
+
8
+ def search(request)
9
+ Puppet::Util::Instrumentation.listeners
10
+ end
11
+
12
+ def save(request)
13
+ res = request.instance
14
+ Puppet::Util::Instrumentation[res.name] = res
15
+ nil # don't leak the listener
16
+ end
17
+
18
+ def destroy(request)
19
+ listener = Puppet::Util::Instrumentation[request.key]
20
+ raise "Listener #{request.key} hasn't been subscribed" unless listener
21
+ Puppet::Util::Instrumentation.unsubscribe(listener)
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ require 'puppet/indirector/instrumentation_listener'
2
+ require 'puppet/indirector/rest'
3
+
4
+ class Puppet::Indirector::InstrumentationListener::Rest < Puppet::Indirector::REST
5
+ end
@@ -0,0 +1,3 @@
1
+ # A stub class, so our constants work.
2
+ class Puppet::Indirector::InstrumentationProbe
3
+ end
@@ -0,0 +1,24 @@
1
+ require 'puppet/indirector/instrumentation_probe'
2
+ require 'puppet/indirector/code'
3
+ require 'puppet/util/instrumentation/indirection_probe'
4
+
5
+ class Puppet::Indirector::InstrumentationProbe::Local < Puppet::Indirector::Code
6
+ def find(request)
7
+ end
8
+
9
+ def search(request)
10
+ probes = []
11
+ Puppet::Util::Instrumentation::Instrumentable.each_probe do |probe|
12
+ probes << Puppet::Util::Instrumentation::IndirectionProbe.new("#{probe.klass}.#{probe.method}")
13
+ end
14
+ probes
15
+ end
16
+
17
+ def save(request)
18
+ Puppet::Util::Instrumentation::Instrumentable.enable_probes
19
+ end
20
+
21
+ def destroy(request)
22
+ Puppet::Util::Instrumentation::Instrumentable.disable_probes
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ require 'puppet/indirector/rest'
2
+ require 'puppet/indirector/instrumentation_probe'
3
+
4
+ class Puppet::Indirector::InstrumentationProbe::Rest < Puppet::Indirector::REST
5
+ end
@@ -95,7 +95,7 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
95
95
  rescue OpenSSL::SSL::SSLError => error
96
96
  if error.message.include? "certificate verify failed"
97
97
  raise Puppet::Error, "#{error.message}. This is often because the time is out of sync on the server or client"
98
- elsif error.message.include? "hostname was not match"
98
+ elsif error.message =~ /hostname (was )?not match/
99
99
  raise unless cert = peer_certs.find { |c| c.name !~ /^puppet ca/i }
100
100
 
101
101
  valid_certnames = [cert.name, *cert.subject_alt_names].uniq
@@ -19,13 +19,6 @@ class Puppet::Module
19
19
 
20
20
  FILETYPES = [MANIFESTS, FILES, TEMPLATES, PLUGINS]
21
21
 
22
- # Return an array of paths by splitting the +modulepath+ config
23
- # parameter. Only consider paths that are absolute and existing
24
- # directories
25
- def self.modulepath(environment = nil)
26
- Puppet::Node::Environment.new(environment).modulepath
27
- end
28
-
29
22
  # Find and return the +module+ that +path+ belongs to. If +path+ is
30
23
  # absolute, or if there is no module whose name is the first component
31
24
  # of +path+, return +nil+
@@ -48,15 +41,16 @@ class Puppet::Module
48
41
  return metadata.is_a?(Hash) && !metadata.keys.empty?
49
42
  end
50
43
 
51
- def initialize(name, environment = nil)
44
+ def initialize(name, options = {})
52
45
  @name = name
46
+ @path = options[:path]
53
47
 
54
48
  assert_validity
55
49
 
56
- if environment.is_a?(Puppet::Node::Environment)
57
- @environment = environment
50
+ if options[:environment].is_a?(Puppet::Node::Environment)
51
+ @environment = options[:environment]
58
52
  else
59
- @environment = Puppet::Node::Environment.new(environment)
53
+ @environment = Puppet::Node::Environment.new(options[:environment])
60
54
  end
61
55
 
62
56
  load_metadata if has_metadata?
@@ -141,7 +135,7 @@ class Puppet::Module
141
135
 
142
136
  # Find this module in the modulepath.
143
137
  def path
144
- environment.modulepath.collect { |path| File.join(path, name) }.find { |d| FileTest.directory?(d) }
138
+ @path ||= environment.modulepath.collect { |path| File.join(path, name) }.find { |d| FileTest.directory?(d) }
145
139
  end
146
140
 
147
141
  # Find all plugin directories. This is used by the Plugins fileserving mount.
@@ -149,11 +143,6 @@ class Puppet::Module
149
143
  subpath("plugins")
150
144
  end
151
145
 
152
- def requires(name, version = nil)
153
- @requires ||= []
154
- @requires << [name, version]
155
- end
156
-
157
146
  def supports(name, version = nil)
158
147
  @supports ||= []
159
148
  @supports << [name, version]
@@ -204,4 +193,11 @@ class Puppet::Module
204
193
  def assert_validity
205
194
  raise InvalidName, "Invalid module name; module names must be alphanumeric (plus '-'), not '#{name}'" unless name =~ /^[-\w]+$/
206
195
  end
196
+
197
+ def ==(other)
198
+ self.name == other.name &&
199
+ self.version == other.version &&
200
+ self.path == other.path &&
201
+ self.environment == other.environment
202
+ end
207
203
  end
@@ -8,5 +8,6 @@ module Puppet::Module::Tool
8
8
  require 'puppet/module_tool/applications/installer'
9
9
  require 'puppet/module_tool/applications/searcher'
10
10
  require 'puppet/module_tool/applications/unpacker'
11
+ require 'puppet/module_tool/applications/uninstaller'
11
12
  end
12
13
  end
@@ -0,0 +1,33 @@
1
+ module Puppet::Module::Tool
2
+ module Applications
3
+ class Uninstaller < Application
4
+
5
+ def initialize(name, options = {})
6
+ @name = name
7
+ @target_directories = options[:target_directories]
8
+ @removed_dirs = []
9
+ end
10
+
11
+ def run
12
+ uninstall
13
+ Puppet.notice "#{@name} is not installed" if @removed_dirs.empty?
14
+ @removed_dirs
15
+ end
16
+
17
+ private
18
+
19
+ def uninstall
20
+ # TODO: #11803 Check for broken dependencies before uninstalling modules.
21
+ #
22
+ # Search each path in the target directories for the specified module
23
+ # and delete the directory.
24
+ @target_directories.each do |target|
25
+ if File.directory? target
26
+ module_path = File.join(target, @name)
27
+ @removed_dirs << FileUtils.rm_rf(module_path).first if File.directory?(module_path)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -73,7 +73,7 @@ module Puppet::Module::Tool
73
73
  # containing :name and :doc.
74
74
  def provider_doc(type)
75
75
  [].tap do |providers|
76
- type.providers.sort_by{ |o| o.to_s }.each do |prov|
76
+ type.providers.sort.each do |prov|
77
77
  providers.push(:name => prov, :doc => type.provider(prov).doc)
78
78
  end
79
79
  end
@@ -22,7 +22,7 @@ class Puppet::Network::Server
22
22
  $stderr.reopen $stdout
23
23
  Puppet::Util::Log.reopen
24
24
  rescue => detail
25
- Puppet::Util.secure_open("/tmp/daemonout", "w") { |f|
25
+ Puppet::Util.replace_file("/tmp/daemonout", 0644) { |f|
26
26
  f.puts "Could not start #{Puppet[:name]}: #{detail}"
27
27
  }
28
28
  raise "Could not start #{Puppet[:name]}: #{detail}"
@@ -40,8 +40,7 @@ class Puppet::Network::Server
40
40
  # Remove the pid file for our daemon.
41
41
  def remove_pidfile
42
42
  Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do
43
- locker = Puppet::Util::Pidlock.new(pidfile)
44
- locker.unlock or Puppet.err "Could not remove PID file #{pidfile}" if locker.locked?
43
+ Puppet::Util::Pidlock.new(pidfile).unlock
45
44
  end
46
45
  end
47
46
 
@@ -54,7 +54,6 @@ class Puppet::Node::Environment
54
54
  @root
55
55
  end
56
56
 
57
- # This is only used for testing.
58
57
  def self.clear
59
58
  @seen.clear
60
59
  end
@@ -88,7 +87,7 @@ class Puppet::Node::Environment
88
87
  end
89
88
 
90
89
  def module(name)
91
- mod = Puppet::Module.new(name, self)
90
+ mod = Puppet::Module.new(name, :environment => self)
92
91
  return nil unless mod.exist?
93
92
  mod
94
93
  end
@@ -107,13 +106,27 @@ class Puppet::Node::Environment
107
106
  module_names = modulepath.collect { |path| Dir.entries(path) }.flatten.uniq
108
107
  module_names.collect do |path|
109
108
  begin
110
- Puppet::Module.new(path, self)
109
+ Puppet::Module.new(path, :environment => self)
111
110
  rescue Puppet::Module::Error => e
112
111
  nil
113
112
  end
114
113
  end.compact
115
114
  end
116
115
 
116
+ # Modules broken out by directory in the modulepath
117
+ def modules_by_path
118
+ modules_by_path = {}
119
+ modulepath.each do |path|
120
+ Dir.chdir(path) do
121
+ module_names = Dir.glob('*').select { |d| FileTest.directory? d }
122
+ modules_by_path[path] = module_names.map do |name|
123
+ Puppet::Module.new(name, :environment => self, :path => File.join(path, name))
124
+ end
125
+ end
126
+ end
127
+ modules_by_path
128
+ end
129
+
117
130
  def to_s
118
131
  name.to_s
119
132
  end
@@ -161,7 +161,7 @@ class Puppet::Parser::AST
161
161
 
162
162
  raise Puppet::ParseError, "#{variable} is not an hash or array when accessing it with #{accesskey}" unless object.is_a?(Hash) or object.is_a?(Array)
163
163
 
164
- object[array_index_or_key(object, accesskey)]
164
+ object[array_index_or_key(object, accesskey)] || :undef
165
165
  end
166
166
 
167
167
  # Assign value to this hashkey or array index
@@ -14,7 +14,7 @@ Puppet::Parser::Functions::newfunction(:create_resources, :doc => <<-'ENDHEREDOC
14
14
  groups => ['developers', 'prosvc', 'release'], }
15
15
  }
16
16
 
17
- create_resource(user, $myusers)
17
+ create_resources(user, $myusers)
18
18
 
19
19
  A third, optional parameter may be given, also as a hash:
20
20
 
@@ -112,7 +112,7 @@ class Puppet::Parser::TypeLoader
112
112
  # behavior) only load files from the first module of a given name. E.g.,
113
113
  # given first/foo and second/foo, only files from first/foo will be loaded.
114
114
  module_names.each do |name|
115
- mod = Puppet::Module.new(name, environment)
115
+ mod = Puppet::Module.new(name, :environment => environment)
116
116
  Find.find(File.join(mod.path, "manifests")) do |path|
117
117
  if path =~ /\.pp$/ or path =~ /\.rb$/
118
118
  import(path)
@@ -166,22 +166,57 @@ class Puppet::Property < Puppet::Parameter
166
166
  raise "Puppet::Property#safe_insync? shouldn't be overridden; please override insync? instead" if sym == :safe_insync?
167
167
  end
168
168
 
169
- # This method should be overridden by derived classes if necessary
169
+ # This method may be overridden by derived classes if necessary
170
170
  # to provide extra logic to determine whether the property is in
171
- # sync.
171
+ # sync. In most cases, however, only `property_matches?` needs to be
172
+ # overridden to give the correct outcome - without reproducing all the array
173
+ # matching logic, etc, found here.
172
174
  def insync?(is)
173
175
  self.devfail "#{self.class.name}'s should is not array" unless @should.is_a?(Array)
174
176
 
175
177
  # an empty array is analogous to no should values
176
178
  return true if @should.empty?
177
179
 
178
- # Look for a matching value
179
- return (is == @should or is == @should.collect { |v| v.to_s }) if match_all?
180
-
181
- @should.each { |val| return true if is == val or is == val.to_s }
180
+ # Look for a matching value, either for all the @should values, or any of
181
+ # them, depending on the configuration of this property.
182
+ if match_all? then
183
+ # Emulate Array#== using our own comparison function.
184
+ # A non-array was not equal to an array, which @should always is.
185
+ return false unless is.is_a? Array
186
+
187
+ # If they were different lengths, they are not equal.
188
+ return false unless is.length == @should.length
189
+
190
+ # Finally, are all the elements equal? In order to preserve the
191
+ # behaviour of previous 2.7.x releases, we need to impose some fun rules
192
+ # on "equality" here.
193
+ #
194
+ # Specifically, we need to implement *this* comparison: the two arrays
195
+ # are identical if the is values are == the should values, or if the is
196
+ # values are == the should values, stringified.
197
+ #
198
+ # This does mean that property equality is not commutative, and will not
199
+ # work unless the `is` value is carefully arranged to match the should.
200
+ return (is == @should or is == @should.map(&:to_s))
201
+
202
+ # When we stop being idiots about this, and actually have meaningful
203
+ # semantics, this version is the thing we actually want to do.
204
+ #
205
+ # return is.zip(@should).all? {|a, b| property_matches?(a, b) }
206
+ else
207
+ return @should.any? {|want| property_matches?(is, want) }
208
+ end
209
+ end
182
210
 
183
- # otherwise, return false
184
- false
211
+ # Compare the current and desired value of a property in a property-specific
212
+ # way. Invoked by `insync?`; this should be overridden if your property
213
+ # has a different comparison type but does not actually differentiate the
214
+ # overall insync? logic.
215
+ def property_matches?(current, desired)
216
+ # This preserves the older Puppet behaviour of doing raw and string
217
+ # equality comparisons for all equality. I am not clear this is globally
218
+ # desirable, but at least it is not a breaking change. --daniel 2011-11-11
219
+ current == desired or current == desired.to_s
185
220
  end
186
221
 
187
222
  # because the @should and @is vars might be in weird formats,
@@ -194,13 +229,10 @@ class Puppet::Property < Puppet::Parameter
194
229
 
195
230
  # Send a log message.
196
231
  def log(msg)
197
-
198
- Puppet::Util::Log.create(
199
-
200
- :level => resource[:loglevel],
232
+ Puppet::Util::Log.create(
233
+ :level => resource[:loglevel],
201
234
  :message => msg,
202
-
203
- :source => self
235
+ :source => self
204
236
  )
205
237
  end
206
238
 
@@ -204,15 +204,15 @@ class Puppet::Provider
204
204
 
205
205
  dochook(:defaults) do
206
206
  if @defaults.length > 0
207
- return " Default for " + @defaults.collect do |f, v|
208
- "`#{f}` == `#{v}`"
207
+ return "Default for " + @defaults.collect do |f, v|
208
+ "`#{f}` == `#{[v].flatten.join(', ')}`"
209
209
  end.join(" and ") + "."
210
210
  end
211
211
  end
212
212
 
213
213
  dochook(:commands) do
214
214
  if @commands.length > 0
215
- return " Required binaries: " + @commands.collect do |n, c|
215
+ return "Required binaries: " + @commands.collect do |n, c|
216
216
  "`#{c}`"
217
217
  end.join(", ") + "."
218
218
  end
@@ -220,7 +220,7 @@ class Puppet::Provider
220
220
 
221
221
  dochook(:features) do
222
222
  if features.length > 0
223
- return " Supported features: " + features.collect do |f|
223
+ return "Supported features: " + features.collect do |f|
224
224
  "`#{f}`"
225
225
  end.join(", ") + "."
226
226
  end
@@ -277,5 +277,14 @@ class Puppet::Provider
277
277
  def to_s
278
278
  "#{@resource}(provider=#{self.class.name})"
279
279
  end
280
+
281
+ # Make providers comparable.
282
+ include Comparable
283
+ def <=>(other)
284
+ # We can only have ordering against other providers.
285
+ return nil unless other.is_a? Puppet::Provider
286
+ # Otherwise, order by the providers class name.
287
+ return self.class.name <=> other.class.name
288
+ end
280
289
  end
281
290