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
@@ -0,0 +1,48 @@
1
+ module Puppet::Util::RetryAction
2
+ class RetryException < Exception; end
3
+ class RetryException::NoBlockGiven < RetryException; end
4
+ class RetryException::NoRetriesGiven < RetryException;end
5
+ class RetryException::RetriesExceeded < RetryException; end
6
+
7
+ def self.retry_action( parameters = { :retry_exceptions => nil, :retries => nil } )
8
+ # Retry actions for a specified amount of time. This method will allow the final
9
+ # retry to complete even if that extends beyond the timeout period.
10
+ unless block_given?
11
+ raise RetryException::NoBlockGiven
12
+ end
13
+
14
+ raise RetryException::NoRetriesGiven if parameters[:retries].nil?
15
+ parameters[:retry_exceptions] ||= Hash.new
16
+
17
+ start = Time.now
18
+ failures = 0
19
+
20
+ begin
21
+ yield
22
+ rescue Exception => e
23
+ # If we were giving exceptions to catch,
24
+ # catch the excptions we care about and retry.
25
+ # All others fail hard
26
+
27
+ raise RetryException::RetriesExceeded if parameters[:retries] == 0
28
+
29
+ if (not parameters[:retry_exceptions].keys.empty?) and parameters[:retry_exceptions].keys.include?(e.class)
30
+ Puppet.info("Caught exception #{e.class}:#{e}")
31
+ Puppet.info(parameters[:retry_exceptions][e.class])
32
+ elsif (not parameters[:retry_exceptions].keys.empty?)
33
+ # If the exceptions is not in the list of retry_exceptions re-raise.
34
+ raise e
35
+ end
36
+
37
+ failures += 1
38
+ parameters[:retries] -= 1
39
+
40
+ # Increase the amount of time that we sleep after every
41
+ # failed retry attempt.
42
+ sleep (((2 ** failures) -1) * 0.1)
43
+
44
+ retry
45
+
46
+ end
47
+ end
48
+ end
@@ -1,11 +1,13 @@
1
1
  require 'puppet/util/warnings'
2
2
  require 'forwardable'
3
+ require 'etc'
3
4
 
4
5
  module Puppet::Util::SUIDManager
5
6
  include Puppet::Util::Warnings
6
7
  extend Forwardable
7
8
 
8
- # Note groups= is handled specially due to a bug in OS X 10.6
9
+ # Note groups= is handled specially due to a bug in OS X 10.6, 10.7,
10
+ # and probably upcoming releases...
9
11
  to_delegate_to_process = [ :euid=, :euid, :egid=, :egid, :uid=, :uid, :gid=, :gid, :groups ]
10
12
 
11
13
  to_delegate_to_process.each do |method|
@@ -28,10 +30,25 @@ module Puppet::Util::SUIDManager
28
30
  module_function :osx_maj_ver
29
31
 
30
32
  def groups=(grouplist)
31
- if osx_maj_ver == '10.6'
32
- return true
33
- else
33
+ begin
34
34
  return Process.groups = grouplist
35
+ rescue Errno::EINVAL => e
36
+ #We catch Errno::EINVAL as some operating systems (OS X in particular) can
37
+ # cause troubles when using Process#groups= to change *this* user / process
38
+ # list of supplementary groups membership. This is done via Ruby's function
39
+ # "static VALUE proc_setgroups(VALUE obj, VALUE ary)" which is effectively
40
+ # a wrapper for "int setgroups(size_t size, const gid_t *list)" (part of SVr4
41
+ # and 4.3BSD but not in POSIX.1-2001) that fails and sets errno to EINVAL.
42
+ #
43
+ # This does not appear to be a problem with Ruby but rather an issue on the
44
+ # operating system side. Therefore we catch the exception and look whether
45
+ # we run under OS X or not -- if so, then we acknowledge the problem and
46
+ # re-throw the exception otherwise.
47
+ if osx_maj_ver and not osx_maj_ver.empty?
48
+ return true
49
+ else
50
+ raise e
51
+ end
35
52
  end
36
53
  end
37
54
  module_function :groups=
@@ -53,55 +70,76 @@ module Puppet::Util::SUIDManager
53
70
  group and group.members.index(Sys::Admin.get_login) != nil
54
71
  end
55
72
 
56
- # Runs block setting uid and gid if provided then restoring original ids
73
+ # Methods to handle changing uid/gid of the running process. In general,
74
+ # these will noop or fail on Windows, and require root to change to anything
75
+ # but the current uid/gid (which is a noop).
76
+
77
+ # Runs block setting euid and egid if provided then restoring original ids.
78
+ # If running on Windows or without root, the block will be run with the
79
+ # current euid/egid.
57
80
  def asuser(new_uid=nil, new_gid=nil)
58
- return yield if Puppet.features.microsoft_windows? or !root?
81
+ return yield if Puppet.features.microsoft_windows?
82
+ return yield unless root?
83
+ return yield unless new_uid or new_gid
59
84
 
60
85
  old_euid, old_egid = self.euid, self.egid
61
86
  begin
62
- change_group(new_gid) if new_gid
63
- change_user(new_uid) if new_uid
87
+ change_privileges(new_uid, new_gid, false)
64
88
 
65
89
  yield
66
90
  ensure
67
- change_group(old_egid)
68
- change_user(old_euid)
91
+ change_privileges(new_uid ? old_euid : nil, old_egid, false)
69
92
  end
70
93
  end
71
94
  module_function :asuser
72
95
 
96
+ # If `permanently` is set, will permanently change the uid/gid of the
97
+ # process. If not, it will only set the euid/egid. If only uid is supplied,
98
+ # the primary group of the supplied gid will be used. If only gid is
99
+ # supplied, only gid will be changed. This method will fail if used on
100
+ # Windows.
101
+ def change_privileges(uid=nil, gid=nil, permanently=false)
102
+ return unless uid or gid
103
+
104
+ unless gid
105
+ uid = convert_xid(:uid, uid)
106
+ gid = Etc.getpwuid(uid).gid
107
+ end
108
+
109
+ change_group(gid, permanently)
110
+ change_user(uid, permanently) if uid
111
+ end
112
+ module_function :change_privileges
113
+
114
+ # Changes the egid of the process if `permanently` is not set, otherwise
115
+ # changes gid. This method will fail if used on Windows, or attempting to
116
+ # change to a different gid without root.
73
117
  def change_group(group, permanently=false)
74
118
  gid = convert_xid(:gid, group)
75
119
  raise Puppet::Error, "No such group #{group}" unless gid
76
120
 
77
121
  if permanently
78
- begin
79
- Process::GID.change_privilege(gid)
80
- rescue NotImplementedError
81
- Process.egid = gid
82
- Process.gid = gid
83
- end
122
+ Process::GID.change_privilege(gid)
84
123
  else
85
124
  Process.egid = gid
86
125
  end
87
126
  end
88
127
  module_function :change_group
89
128
 
129
+ # As change_group, but operates on uids. If changing user permanently,
130
+ # supplementary groups will be set the to default groups for the new uid.
90
131
  def change_user(user, permanently=false)
91
132
  uid = convert_xid(:uid, user)
92
133
  raise Puppet::Error, "No such user #{user}" unless uid
93
134
 
94
135
  if permanently
95
- begin
96
- Process::UID.change_privilege(uid)
97
- rescue NotImplementedError
98
- # If changing uid, we must be root. So initgroups first here.
99
- initgroups(uid)
100
- Process.euid = uid
101
- Process.uid = uid
102
- end
136
+ # If changing uid, we must be root. So initgroups first here.
137
+ initgroups(uid)
138
+
139
+ Process::UID.change_privilege(uid)
103
140
  else
104
- # If we're already root, initgroups before changing euid. If we're not,
141
+ # We must be root to initgroups, so initgroups before dropping euid if
142
+ # we're root, otherwise elevate euid before initgroups.
105
143
  # change euid (to root) first.
106
144
  if Process.euid == 0
107
145
  initgroups(uid)
@@ -126,10 +164,13 @@ module Puppet::Util::SUIDManager
126
164
  end
127
165
  module_function :convert_xid
128
166
 
129
- # Initialize supplementary groups
130
- def initgroups(user)
131
- require 'etc'
132
- Process.initgroups(Etc.getpwuid(user).name, Process.gid)
167
+ # Initialize primary and supplemental groups to those of the target user. We
168
+ # take the UID and manually look up their details in the system database,
169
+ # including username and primary group. This method will fail on Windows, or
170
+ # if used without root to initgroups of another user.
171
+ def initgroups(uid)
172
+ pwent = Etc.getpwuid(uid)
173
+ Process.initgroups(pwent.name, pwent.gid)
133
174
  end
134
175
 
135
176
  module_function :initgroups
@@ -139,14 +180,4 @@ module Puppet::Util::SUIDManager
139
180
  [output, $CHILD_STATUS.dup]
140
181
  end
141
182
  module_function :run_and_capture
142
-
143
- def system(command, new_uid=nil, new_gid=nil)
144
- status = nil
145
- asuser(new_uid, new_gid) do
146
- Kernel.system(command)
147
- status = $CHILD_STATUS.dup
148
- end
149
- status
150
- end
151
- module_function :system
152
183
  end
@@ -0,0 +1,140 @@
1
+ require 'puppet/util'
2
+
3
+ module Puppet::Util::SymbolicFileMode
4
+ SetUIDBit = ReadBit = 4
5
+ SetGIDBit = WriteBit = 2
6
+ StickyBit = ExecBit = 1
7
+ SymbolicMode = { 'x' => ExecBit, 'w' => WriteBit, 'r' => ReadBit }
8
+ SymbolicSpecialToBit = {
9
+ 't' => { 'u' => StickyBit, 'g' => StickyBit, 'o' => StickyBit },
10
+ 's' => { 'u' => SetUIDBit, 'g' => SetGIDBit, 'o' => StickyBit }
11
+ }
12
+
13
+ def valid_symbolic_mode?(value)
14
+ value = normalize_symbolic_mode(value)
15
+ return true if value =~ /^0?[0-7]{1,4}$/
16
+ return true if value =~ /^([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*$/
17
+ return false
18
+ end
19
+
20
+ def normalize_symbolic_mode(value)
21
+ return nil if value.nil?
22
+
23
+ # We need to treat integers as octal numbers.
24
+ if value.is_a? Numeric then
25
+ return value.to_s(8)
26
+ elsif value =~ /^0?[0-7]{1,4}$/ then
27
+ return value.to_i(8).to_s(8)
28
+ else
29
+ return value
30
+ end
31
+ end
32
+
33
+ def symbolic_mode_to_int(modification, to_mode = 0, is_a_directory = false)
34
+ if modification.nil? or modification == '' then
35
+ raise Puppet::Error, "An empty mode string is illegal"
36
+ end
37
+ if modification =~ /^[0-7]+$/ then return modification.to_i(8) end
38
+ if modification =~ /^\d+$/ then
39
+ raise Puppet::Error, "Numeric modes must be in octal, not decimal!"
40
+ end
41
+
42
+ fail "non-numeric current mode (#{to_mode.inspect})" unless to_mode.is_a?(Numeric)
43
+
44
+ original_mode = {
45
+ 's' => (to_mode & 07000) >> 9,
46
+ 'u' => (to_mode & 00700) >> 6,
47
+ 'g' => (to_mode & 00070) >> 3,
48
+ 'o' => (to_mode & 00007) >> 0,
49
+ # Are there any execute bits set in the original mode?
50
+ 'any x?' => (to_mode & 00111) != 0
51
+ }
52
+ final_mode = {
53
+ 's' => original_mode['s'],
54
+ 'u' => original_mode['u'],
55
+ 'g' => original_mode['g'],
56
+ 'o' => original_mode['o'],
57
+ }
58
+
59
+ modification.split(/\s*,\s*/).each do |part|
60
+ begin
61
+ _, to, dsl = /^([ugoa]*)([-+=].*)$/.match(part).to_a
62
+ if dsl.nil? then raise Puppet::Error, 'Missing action' end
63
+ to = "a" unless to and to.length > 0
64
+
65
+ # We want a snapshot of the mode before we start messing with it to
66
+ # make actions like 'a-g' atomic. Various parts of the DSL refer to
67
+ # the original mode, the final mode, or the current snapshot of the
68
+ # mode, for added fun.
69
+ snapshot_mode = {}
70
+ final_mode.each {|k,v| snapshot_mode[k] = v }
71
+
72
+ to.gsub('a', 'ugo').split('').uniq.each do |who|
73
+ value = snapshot_mode[who]
74
+
75
+ action = '!'
76
+ actions = {
77
+ '!' => lambda {|_,_| raise Puppet::Error, 'Missing operation (-, =, or +)' },
78
+ '=' => lambda {|m,v| m | v },
79
+ '+' => lambda {|m,v| m | v },
80
+ '-' => lambda {|m,v| m & ~v },
81
+ }
82
+
83
+ dsl.split('').each do |op|
84
+ case op
85
+ when /[-+=]/ then
86
+ action = op
87
+ # Clear all bits, if this is assignment
88
+ value = 0 if op == '='
89
+
90
+ when /[ugo]/ then
91
+ value = actions[action].call(value, snapshot_mode[op])
92
+
93
+ when /[rwx]/ then
94
+ value = actions[action].call(value, SymbolicMode[op])
95
+
96
+ when 'X' then
97
+ # Only meaningful in combination with "set" actions.
98
+ if action != '+' then
99
+ raise Puppet::Error, "X only works with the '+' operator"
100
+ end
101
+
102
+ # As per the BSD manual page, set if this is a directory, or if
103
+ # any execute bit is set on the original (unmodified) mode.
104
+ # Ignored otherwise; it is "add if", not "add or clear".
105
+ if is_a_directory or original_mode['any x?'] then
106
+ value = actions[action].call(value, ExecBit)
107
+ end
108
+
109
+ when /[st]/ then
110
+ bit = SymbolicSpecialToBit[op][who] or fail "internal error"
111
+ final_mode['s'] = actions[action].call(final_mode['s'], bit)
112
+
113
+ else
114
+ raise Puppet::Error, 'Unknown operation'
115
+ end
116
+ end
117
+
118
+ # Now, assign back the value.
119
+ final_mode[who] = value
120
+ end
121
+
122
+ rescue Puppet::Error => e
123
+ if part.inspect != modification.inspect then
124
+ rest = " at #{part.inspect}"
125
+ else
126
+ rest = ''
127
+ end
128
+
129
+ raise Puppet::Error, "#{e}#{rest} in symbolic mode #{modification.inspect}"
130
+ end
131
+ end
132
+
133
+ result =
134
+ final_mode['s'] << 9 |
135
+ final_mode['u'] << 6 |
136
+ final_mode['g'] << 3 |
137
+ final_mode['o'] << 0
138
+ return result
139
+ end
140
+ end
@@ -47,6 +47,7 @@ describe Puppet::Configurer do
47
47
  Puppet::Transaction::Report.indirection.stubs(:save)
48
48
 
49
49
  Puppet[:lastrunfile] = tmpfile("lastrunfile")
50
+ Puppet.settings.setting(:lastrunfile).mode = 0666
50
51
  Puppet[:report] = true
51
52
 
52
53
  # We only record integer seconds in the timestamp, and truncate
@@ -56,6 +57,10 @@ describe Puppet::Configurer do
56
57
  @configurer.run :catalog => @catalog, :report => report
57
58
  t2 = Time.now.tv_sec
58
59
 
60
+ file_mode = Puppet.features.microsoft_windows? ? '100644' : '100666'
61
+
62
+ File.stat(Puppet[:lastrunfile]).mode.to_s(8).should == file_mode
63
+
59
64
  summary = nil
60
65
  File.open(Puppet[:lastrunfile], "r") do |fd|
61
66
  summary = YAML.load(fd.read)
@@ -22,7 +22,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with the files
22
22
  it "should return an instance capable of returning its content" do
23
23
  FileTest.expects(:exists?).with(@filepath).returns(true)
24
24
  File.stubs(:lstat).with(@filepath).returns(stub("stat", :ftype => "file"))
25
- File.expects(:read).with(@filepath).returns("my content")
25
+ Puppet::Util.expects(:binread).with(@filepath).returns("my content")
26
26
 
27
27
  instance = @terminus.find(@terminus.indirection.request(:find, "file://host#{@filepath}"))
28
28
 
@@ -24,7 +24,7 @@ describe Puppet::Indirector::FileContent::FileServer, " when finding files" do
24
24
  modpath = File.join(path, "mod")
25
25
  FileUtils.mkdir_p(File.join(modpath, "lib"))
26
26
  file = File.join(modpath, "lib", "file.rb")
27
- File.open(file, "w") { |f| f.puts "1" }
27
+ File.open(file, "wb") { |f| f.write "1\r\n" }
28
28
 
29
29
  Puppet.settings[:modulepath] = "/no/such/file"
30
30
 
@@ -35,8 +35,8 @@ describe Puppet::Indirector::FileContent::FileServer, " when finding files" do
35
35
 
36
36
  result.should_not be_nil
37
37
  result.length.should == 2
38
- result[1].should be_instance_of(Puppet::FileServing::Content)
39
- result[1].content.should == "1\n"
38
+ result.map {|x| x.should be_instance_of(Puppet::FileServing::Content) }
39
+ result.find {|x| x.relative_path == 'file.rb' }.content.should == "1\r\n"
40
40
  end
41
41
 
42
42
  it "should find file content in modules" do
@@ -47,7 +47,7 @@ describe Puppet::Indirector::FileContent::FileServer, " when finding files" do
47
47
  modpath = File.join(path, "mymod")
48
48
  FileUtils.mkdir_p(File.join(modpath, "files"))
49
49
  file = File.join(modpath, "files", "myfile")
50
- File.open(file, "w") { |f| f.puts "1" }
50
+ File.open(file, "wb") { |f| f.write "1\r\n" }
51
51
 
52
52
  Puppet.settings[:modulepath] = path
53
53
 
@@ -55,7 +55,7 @@ describe Puppet::Indirector::FileContent::FileServer, " when finding files" do
55
55
 
56
56
  result.should_not be_nil
57
57
  result.should be_instance_of(Puppet::FileServing::Content)
58
- result.content.should == "1\n"
58
+ result.content.should == "1\r\n"
59
59
  end
60
60
 
61
61
  it "should find file content in files when node name expansions are used" do
@@ -67,7 +67,7 @@ describe Puppet::Indirector::FileContent::FileServer, " when finding files" do
67
67
  Dir.mkdir(@path)
68
68
  subdir = File.join(@path, "mynode")
69
69
  Dir.mkdir(subdir)
70
- File.open(File.join(subdir, "myfile"), "w") { |f| f.puts "1" }
70
+ File.open(File.join(subdir, "myfile"), "wb") { |f| f.write "1\r\n" }
71
71
 
72
72
  # Use a real mount, so the integration is a bit deeper.
73
73
  @mount1 = Puppet::FileServing::Configuration::Mount::File.new("one")
@@ -85,6 +85,6 @@ describe Puppet::Indirector::FileContent::FileServer, " when finding files" do
85
85
 
86
86
  result.should_not be_nil
87
87
  result.should be_instance_of(Puppet::FileServing::Content)
88
- result.content.should == "1\n"
88
+ result.content.should == "1\r\n"
89
89
  end
90
90
  end
@@ -27,6 +27,13 @@ describe "Package provider", :'fails_on_ruby_1.9.2' => true do
27
27
  Puppet[:vardir] = tmpdir('msi_package_var_dir')
28
28
  end
29
29
 
30
+ # the instances method requires root priviledges on gentoo
31
+ # if the eix cache is outdated (to run eix-update) so make
32
+ # sure we dont actually run eix-update
33
+ if provider.name == :portage
34
+ provider.stubs(:update_eix).returns('Database contains 15240 packages in 155 categories')
35
+ end
36
+
30
37
  provider.instances.each do |package|
31
38
  package.should be_instance_of(provider)
32
39
  package.properties[:provider].should == provider.name