puppet 2.7.6 → 2.7.8

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 (206) hide show
  1. data/CHANGELOG +168 -0
  2. data/conf/auth.conf +5 -4
  3. data/conf/redhat/puppet.spec +16 -1
  4. data/conf/solaris/pkginfo +2 -2
  5. data/conf/suse/puppet.spec +9 -3
  6. data/ext/upload_facts.rb +120 -0
  7. data/install.rb +11 -16
  8. data/lib/puppet.rb +1 -1
  9. data/lib/puppet/application/agent.rb +0 -3
  10. data/lib/puppet/application/apply.rb +0 -3
  11. data/lib/puppet/application/queue.rb +21 -1
  12. data/lib/puppet/defaults.rb +6 -4
  13. data/lib/puppet/face/file/store.rb +1 -1
  14. data/lib/puppet/feature/base.rb +2 -1
  15. data/lib/puppet/file_bucket/dipper.rb +3 -2
  16. data/lib/puppet/file_serving/content.rb +1 -1
  17. data/lib/puppet/file_serving/metadata.rb +5 -2
  18. data/lib/puppet/indirector/facts/inventory_service.rb +20 -0
  19. data/lib/puppet/indirector/file_bucket_file/file.rb +3 -2
  20. data/lib/puppet/indirector/report/processor.rb +1 -1
  21. data/lib/puppet/network/handler/filebucket.rb +2 -0
  22. data/lib/puppet/network/handler/fileserver.rb +1 -1
  23. data/lib/puppet/network/handler/master.rb +1 -0
  24. data/lib/puppet/network/handler/report.rb +2 -0
  25. data/lib/puppet/network/handler/runner.rb +1 -0
  26. data/lib/puppet/network/handler/status.rb +2 -0
  27. data/lib/puppet/network/http/mongrel/rest.rb +8 -1
  28. data/lib/puppet/network/http_server.rb +3 -0
  29. data/lib/puppet/network/http_server/mongrel.rb +129 -0
  30. data/lib/puppet/network/rest_authconfig.rb +12 -4
  31. data/lib/puppet/parameter.rb +18 -0
  32. data/lib/puppet/parser/compiler.rb +1 -1
  33. data/lib/puppet/parser/grammar.ra +1 -1
  34. data/lib/puppet/parser/parser.rb +360 -350
  35. data/lib/puppet/property.rb +3 -3
  36. data/lib/puppet/provider/augeas/augeas.rb +1 -1
  37. data/lib/puppet/provider/exec/windows.rb +6 -7
  38. data/lib/puppet/provider/file/windows.rb +9 -2
  39. data/lib/puppet/provider/group/aix.rb +8 -8
  40. data/lib/puppet/provider/group/groupadd.rb +1 -3
  41. data/lib/puppet/provider/group/ldap.rb +8 -10
  42. data/lib/puppet/provider/group/windows_adsi.rb +8 -2
  43. data/lib/puppet/provider/package/aix.rb +1 -1
  44. data/lib/puppet/provider/package/macports.rb +3 -3
  45. data/lib/puppet/provider/package/msi.rb +12 -5
  46. data/lib/puppet/provider/package/nim.rb +1 -1
  47. data/lib/puppet/provider/package/pkgdmg.rb +3 -3
  48. data/lib/puppet/provider/package/ports.rb +1 -1
  49. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +560 -0
  50. data/lib/puppet/provider/service/base.rb +2 -2
  51. data/lib/puppet/provider/service/bsd.rb +4 -3
  52. data/lib/puppet/provider/service/daemontools.rb +25 -25
  53. data/lib/puppet/provider/service/debian.rb +6 -4
  54. data/lib/puppet/provider/service/freebsd.rb +1 -1
  55. data/lib/puppet/provider/service/gentoo.rb +4 -3
  56. data/lib/puppet/provider/service/init.rb +3 -8
  57. data/lib/puppet/provider/service/launchd.rb +129 -96
  58. data/lib/puppet/provider/service/redhat.rb +2 -3
  59. data/lib/puppet/provider/service/runit.rb +20 -20
  60. data/lib/puppet/provider/service/smf.rb +8 -7
  61. data/lib/puppet/provider/service/src.rb +5 -6
  62. data/lib/puppet/provider/service/systemd.rb +1 -1
  63. data/lib/puppet/provider/service/upstart.rb +3 -5
  64. data/lib/puppet/provider/service/windows.rb +7 -7
  65. data/lib/puppet/provider/sshkey/parsed.rb +2 -3
  66. data/lib/puppet/provider/user/aix.rb +21 -21
  67. data/lib/puppet/provider/user/hpux.rb +3 -1
  68. data/lib/puppet/provider/user/ldap.rb +7 -7
  69. data/lib/puppet/provider/user/user_role_add.rb +10 -6
  70. data/lib/puppet/provider/user/useradd.rb +3 -1
  71. data/lib/puppet/provider/user/windows_adsi.rb +4 -3
  72. data/lib/puppet/rb_tree_map.rb +388 -0
  73. data/lib/puppet/reference/configuration.rb +7 -7
  74. data/lib/puppet/reference/indirection.rb +5 -6
  75. data/lib/puppet/reference/metaparameter.rb +3 -1
  76. data/lib/puppet/reference/network.rb +8 -8
  77. data/lib/puppet/reference/providers.rb +17 -21
  78. data/lib/puppet/reference/type.rb +12 -9
  79. data/lib/puppet/resource.rb +2 -5
  80. data/lib/puppet/resource/catalog.rb +1 -1
  81. data/lib/puppet/ssl/certificate_request.rb +70 -0
  82. data/lib/puppet/ssl/host.rb +6 -0
  83. data/lib/puppet/transaction.rb +158 -55
  84. data/lib/puppet/transaction/event_manager.rb +1 -1
  85. data/lib/puppet/type.rb +60 -30
  86. data/lib/puppet/type/augeas.rb +83 -49
  87. data/lib/puppet/type/computer.rb +1 -1
  88. data/lib/puppet/type/cron.rb +11 -11
  89. data/lib/puppet/type/exec.rb +28 -21
  90. data/lib/puppet/type/file.rb +17 -7
  91. data/lib/puppet/type/file/content.rb +2 -2
  92. data/lib/puppet/type/file/ensure.rb +15 -12
  93. data/lib/puppet/type/file/mode.rb +30 -5
  94. data/lib/puppet/type/file/source.rb +11 -10
  95. data/lib/puppet/type/file/target.rb +2 -2
  96. data/lib/puppet/type/filebucket.rb +1 -1
  97. data/lib/puppet/type/group.rb +4 -5
  98. data/lib/puppet/type/host.rb +1 -1
  99. data/lib/puppet/type/interface.rb +13 -10
  100. data/lib/puppet/type/k5login.rb +6 -6
  101. data/lib/puppet/type/macauthorization.rb +37 -36
  102. data/lib/puppet/type/maillist.rb +2 -2
  103. data/lib/puppet/type/mcx.rb +6 -6
  104. data/lib/puppet/type/mount.rb +3 -2
  105. data/lib/puppet/type/notify.rb +1 -1
  106. data/lib/puppet/type/package.rb +24 -23
  107. data/lib/puppet/type/router.rb +4 -1
  108. data/lib/puppet/type/schedule.rb +52 -44
  109. data/lib/puppet/type/scheduled_task.rb +222 -0
  110. data/lib/puppet/type/selmodule.rb +10 -6
  111. data/lib/puppet/type/service.rb +11 -11
  112. data/lib/puppet/type/ssh_authorized_key.rb +2 -5
  113. data/lib/puppet/type/sshkey.rb +1 -1
  114. data/lib/puppet/type/stage.rb +1 -1
  115. data/lib/puppet/type/tidy.rb +10 -8
  116. data/lib/puppet/type/user.rb +61 -53
  117. data/lib/puppet/type/vlan.rb +4 -4
  118. data/lib/puppet/type/whit.rb +6 -2
  119. data/lib/puppet/type/yumrepo.rb +33 -31
  120. data/lib/puppet/type/zfs.rb +34 -32
  121. data/lib/puppet/type/zone.rb +21 -19
  122. data/lib/puppet/type/zpool.rb +3 -3
  123. data/lib/puppet/util.rb +24 -6
  124. data/lib/puppet/util/adsi.rb +12 -7
  125. data/lib/puppet/util/checksums.rb +1 -1
  126. data/lib/puppet/util/diff.rb +1 -1
  127. data/lib/puppet/util/nagios_maker.rb +2 -2
  128. data/lib/puppet/util/reference.rb +16 -17
  129. data/lib/puppet/util/settings/file_setting.rb +14 -2
  130. data/lib/puppet/util/windows/security.rb +96 -32
  131. data/spec/integration/file_serving/terminus_helper_spec.rb +1 -1
  132. data/spec/integration/indirector/direct_file_server_spec.rb +9 -15
  133. data/spec/integration/indirector/file_content/file_server_spec.rb +1 -1
  134. data/spec/integration/indirector/file_metadata/file_server_spec.rb +1 -1
  135. data/spec/integration/provider/package_spec.rb +4 -0
  136. data/spec/integration/provider/service/init_spec.rb +8 -2
  137. data/spec/integration/reference/providers_spec.rb +1 -1
  138. data/spec/integration/ssl/certificate_request_spec.rb +1 -2
  139. data/spec/integration/ssl/certificate_revocation_list_spec.rb +1 -2
  140. data/spec/integration/ssl/host_spec.rb +1 -2
  141. data/spec/integration/transaction_spec.rb +25 -17
  142. data/spec/integration/type/exec_spec.rb +77 -0
  143. data/spec/integration/type/file_spec.rb +322 -2
  144. data/spec/integration/util/windows/security_spec.rb +393 -230
  145. data/spec/integration/util_spec.rb +16 -0
  146. data/spec/lib/puppet_spec/files.rb +3 -7
  147. data/spec/unit/application/apply_spec.rb +0 -9
  148. data/spec/unit/application/inspect_spec.rb +1 -0
  149. data/spec/unit/configurer/downloader_spec.rb +3 -3
  150. data/spec/unit/face/certificate_spec.rb +6 -2
  151. data/spec/unit/file_bucket/dipper_spec.rb +67 -10
  152. data/spec/unit/file_bucket/file_spec.rb +22 -28
  153. data/spec/unit/file_serving/content_spec.rb +1 -1
  154. data/spec/unit/file_serving/metadata_spec.rb +30 -3
  155. data/spec/unit/indirector/facts/inventory_service_spec.rb +22 -0
  156. data/spec/unit/indirector/file_bucket_file/file_spec.rb +21 -24
  157. data/spec/unit/indirector/node/store_configs_spec.rb +1 -0
  158. data/spec/unit/indirector/resource/ral_spec.rb +1 -1
  159. data/spec/unit/indirector/resource_type/parser_spec.rb +2 -2
  160. data/spec/unit/indirector/rest_spec.rb +1 -1
  161. data/spec/unit/network/handler/ca_spec.rb +1 -1
  162. data/spec/unit/network/http/mongrel/rest_spec.rb +54 -25
  163. data/spec/unit/parameter_spec.rb +36 -0
  164. data/spec/unit/parser/parser_spec.rb +4 -0
  165. data/spec/unit/property_spec.rb +2 -2
  166. data/spec/unit/provider/exec/windows_spec.rb +2 -8
  167. data/spec/unit/provider/file/posix_spec.rb +6 -0
  168. data/spec/unit/provider/file/windows_spec.rb +18 -0
  169. data/spec/unit/provider/group/windows_adsi_spec.rb +22 -6
  170. data/spec/unit/provider/mount/parsed_spec.rb +1 -1
  171. data/spec/unit/provider/package/msi_spec.rb +2 -2
  172. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +1571 -0
  173. data/spec/unit/provider/service/launchd_spec.rb +143 -130
  174. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +5 -0
  175. data/spec/unit/provider/user/user_role_add_spec.rb +39 -9
  176. data/spec/unit/provider/user/useradd_spec.rb +1 -1
  177. data/spec/unit/provider/user/windows_adsi_spec.rb +8 -1
  178. data/spec/unit/rb_tree_map_spec.rb +572 -0
  179. data/spec/unit/resource/catalog_spec.rb +1 -1
  180. data/spec/unit/simple_graph_spec.rb +9 -9
  181. data/spec/unit/ssl/host_spec.rb +60 -12
  182. data/spec/unit/transaction/report_spec.rb +3 -3
  183. data/spec/unit/transaction_spec.rb +394 -11
  184. data/spec/unit/type/exec_spec.rb +35 -15
  185. data/spec/unit/type/file/content_spec.rb +11 -10
  186. data/spec/unit/type/file/mode_spec.rb +73 -19
  187. data/spec/unit/type/file/source_spec.rb +1 -1
  188. data/spec/unit/type/file_spec.rb +15 -0
  189. data/spec/unit/type/group_spec.rb +1 -1
  190. data/spec/unit/type/mount_spec.rb +5 -5
  191. data/spec/unit/type/resources_spec.rb +3 -3
  192. data/spec/unit/type/scheduled_task_spec.rb +102 -0
  193. data/spec/unit/type/ssh_authorized_key_spec.rb +2 -3
  194. data/spec/unit/type/user_spec.rb +2 -1
  195. data/spec/unit/type_spec.rb +48 -4
  196. data/spec/unit/util/adsi_spec.rb +18 -7
  197. data/spec/unit/util/checksums_spec.rb +20 -2
  198. data/spec/unit/util/execution_stub_spec.rb +10 -5
  199. data/spec/unit/util/logging_spec.rb +6 -6
  200. data/spec/unit/util/rdoc/parser_spec.rb +1 -1
  201. data/spec/unit/util/reference_spec.rb +29 -0
  202. data/spec/unit/util/settings/file_setting_spec.rb +8 -2
  203. data/spec/unit/util_spec.rb +115 -0
  204. data/test/other/transactions.rb +5 -11
  205. data/test/ral/type/exec.rb +1 -1
  206. metadata +24 -11
@@ -537,7 +537,7 @@ describe Puppet::Resource::Catalog, "when compiling" do
537
537
  @catalog.resource(:file, @basepath+"/something").should equal(resource)
538
538
  end
539
539
 
540
- it "should not create aliases for non-isomorphic resources whose names do not match their titles", :fails_on_windows => true do
540
+ it "should not create aliases for non-isomorphic resources whose names do not match their titles" do
541
541
  resource = Puppet::Type.type(:exec).new(:title => "testing", :command => "echo", :path => %w{/bin /usr/bin /usr/local/bin})
542
542
 
543
543
  @catalog.add_resource(resource)
@@ -585,11 +585,11 @@ describe Puppet::SimpleGraph do
585
585
  x
586
586
  end
587
587
 
588
- def admissible_sentinal_of(x)
588
+ def admissible_sentinel_of(x)
589
589
  @depgraph.vertex?(x) ? x : whit_called("admissible_#{x.ref}")
590
590
  end
591
591
 
592
- def completed_sentinal_of(x)
592
+ def completed_sentinel_of(x)
593
593
  @depgraph.vertex?(x) ? x : whit_called("completed_#{x.ref}")
594
594
  end
595
595
 
@@ -617,28 +617,28 @@ describe Puppet::SimpleGraph do
617
617
 
618
618
  # 0) completed_X depends on admissible_X
619
619
  #
620
- it "every container's completed sentinal should depend on its admissible sentinal" do
620
+ it "every container's completed sentinel should depend on its admissible sentinel" do
621
621
  containers.each { |container|
622
- @depgraph.path_between(admissible_sentinal_of(container),completed_sentinal_of(container)).should be
622
+ @depgraph.path_between(admissible_sentinel_of(container),completed_sentinel_of(container)).should be
623
623
  }
624
624
  end
625
625
 
626
626
  # 1) contents of X each depend on admissible_X
627
627
  #
628
- it "all contained objects should depend on their container's admissible sentinal" do
628
+ it "all contained objects should depend on their container's admissible sentinel" do
629
629
  containers.each { |container|
630
630
  contents_of(container).each { |leaf|
631
- @depgraph.should be_edge(admissible_sentinal_of(container),admissible_sentinal_of(leaf))
631
+ @depgraph.should be_edge(admissible_sentinel_of(container),admissible_sentinel_of(leaf))
632
632
  }
633
633
  }
634
634
  end
635
635
 
636
636
  # 2) completed_X depends on each on the contents of X
637
637
  #
638
- it "completed sentinals should depend on their container's contents" do
638
+ it "completed sentinels should depend on their container's contents" do
639
639
  containers.each { |container|
640
640
  contents_of(container).each { |leaf|
641
- @depgraph.should be_edge(completed_sentinal_of(leaf),completed_sentinal_of(container))
641
+ @depgraph.should be_edge(completed_sentinel_of(leaf),completed_sentinel_of(container))
642
642
  }
643
643
  }
644
644
  end
@@ -665,7 +665,7 @@ describe Puppet::SimpleGraph do
665
665
 
666
666
  it "should retain labels on non-containment edges" do
667
667
  @explicit_dependencies.each { |f,t|
668
- @depgraph.edges_between(completed_sentinal_of(f),admissible_sentinal_of(t))[0].label.should == {:callback => :refresh}
668
+ @depgraph.edges_between(completed_sentinel_of(f),admissible_sentinel_of(t))[0].label.should == {:callback => :refresh}
669
669
  }
670
670
  end
671
671
 
@@ -3,8 +3,7 @@ require 'spec_helper'
3
3
 
4
4
  require 'puppet/ssl/host'
5
5
 
6
- # REMIND: Fails on windows because there is no user provider yet
7
- describe Puppet::SSL::Host, :fails_on_windows => true do
6
+ describe Puppet::SSL::Host do
8
7
  include PuppetSpec::Files
9
8
 
10
9
  before do
@@ -80,7 +79,7 @@ describe Puppet::SSL::Host, :fails_on_windows => true do
80
79
  Puppet::SSL::Host.localhost.should equal(host)
81
80
  end
82
81
 
83
- it "should create a localhost cert if no cert is available and it is a CA with autosign and it is using DNS alt names" do
82
+ it "should create a localhost cert if no cert is available and it is a CA with autosign and it is using DNS alt names", :unless => Puppet.features.microsoft_windows? do
84
83
  Puppet[:autosign] = true
85
84
  Puppet[:confdir] = tmpdir('conf')
86
85
  Puppet[:dns_alt_names] = "foo,bar,baz"
@@ -96,8 +95,6 @@ describe Puppet::SSL::Host, :fails_on_windows => true do
96
95
 
97
96
  context "with dns_alt_names" do
98
97
  before :each do
99
- Puppet[:dns_alt_names] = 'one, two'
100
-
101
98
  @key = stub('key content')
102
99
  key = stub('key', :generate => true, :content => @key)
103
100
  Puppet::SSL::Key.stubs(:new).returns key
@@ -108,17 +105,68 @@ describe Puppet::SSL::Host, :fails_on_windows => true do
108
105
  Puppet::SSL::CertificateRequest.indirection.stubs(:save).with(@cr)
109
106
  end
110
107
 
111
- it "should not include subjectAltName if not the local node" do
112
- @cr.expects(:generate).with(@key, {})
108
+ describe "explicitly specified" do
109
+ before :each do
110
+ Puppet[:dns_alt_names] = 'one, two'
111
+ end
112
+
113
+ it "should not include subjectAltName if not the local node" do
114
+ @cr.expects(:generate).with(@key, {})
113
115
 
114
- Puppet::SSL::Host.new('not-the-' + Puppet[:certname]).generate
116
+ Puppet::SSL::Host.new('not-the-' + Puppet[:certname]).generate
117
+ end
118
+
119
+ it "should include subjectAltName if I am a CA" do
120
+ @cr.expects(:generate).
121
+ with(@key, { :dns_alt_names => Puppet[:dns_alt_names] })
122
+
123
+ Puppet::SSL::Host.localhost
124
+ end
115
125
  end
116
126
 
117
- it "should include subjectAltName if I am a CA" do
118
- @cr.expects(:generate).
119
- with(@key, { :dns_alt_names => Puppet[:dns_alt_names] })
127
+ describe "implicitly defaulted" do
128
+ let(:ca) { stub('ca', :sign => nil) }
120
129
 
121
- Puppet::SSL::Host.localhost
130
+ before :each do
131
+ Puppet[:dns_alt_names] = ''
132
+
133
+ Puppet::SSL::CertificateAuthority.stubs(:instance).returns ca
134
+ end
135
+
136
+ it "should not include defaults if we're not the CA" do
137
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns false
138
+
139
+ @cr.expects(:generate).with(@key, {})
140
+
141
+ Puppet::SSL::Host.localhost
142
+ end
143
+
144
+ it "should not include defaults if not the local node" do
145
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
146
+
147
+ @cr.expects(:generate).with(@key, {})
148
+
149
+ Puppet::SSL::Host.new('not-the-' + Puppet[:certname]).generate
150
+ end
151
+
152
+ it "should not include defaults if we can't resolve our fqdn" do
153
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
154
+ Facter.stubs(:value).with(:fqdn).returns nil
155
+
156
+ @cr.expects(:generate).with(@key, {})
157
+
158
+ Puppet::SSL::Host.localhost
159
+ end
160
+
161
+ it "should provide defaults if we're bootstrapping the local master" do
162
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
163
+ Facter.stubs(:value).with(:fqdn).returns 'web.foo.com'
164
+ Facter.stubs(:value).with(:domain).returns 'foo.com'
165
+
166
+ @cr.expects(:generate).with(@key, {:dns_alt_names => "puppet, web.foo.com, puppet.foo.com"})
167
+
168
+ Puppet::SSL::Host.localhost
169
+ end
122
170
  end
123
171
  end
124
172
 
@@ -204,14 +204,14 @@ describe Puppet::Transaction::Report do
204
204
  end
205
205
 
206
206
  describe "for times" do
207
- it "should provide the total amount of time for each resource type", :fails_on_windows => true do
207
+ it "should provide the total amount of time for each resource type" do
208
208
  add_statuses(3, :file) do |status|
209
209
  status.evaluation_time = 1
210
210
  end
211
211
  add_statuses(3, :exec) do |status|
212
212
  status.evaluation_time = 2
213
213
  end
214
- add_statuses(3, :mount) do |status|
214
+ add_statuses(3, :tidy) do |status|
215
215
  status.evaluation_time = 3
216
216
  end
217
217
 
@@ -219,7 +219,7 @@ describe Puppet::Transaction::Report do
219
219
 
220
220
  metric(:time, "file").should == 3
221
221
  metric(:time, "exec").should == 6
222
- metric(:time, "mount").should == 9
222
+ metric(:time, "tidy").should == 9
223
223
  end
224
224
 
225
225
  it "should add any provided times from external sources" do
@@ -2,6 +2,7 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  require 'puppet/transaction'
5
+ require 'fileutils'
5
6
 
6
7
  def without_warnings
7
8
  flag = $VERBOSE
@@ -182,6 +183,333 @@ describe Puppet::Transaction do
182
183
  end
183
184
  end
184
185
 
186
+ describe "#eval_generate" do
187
+ let(:path) { tmpdir('eval_generate') }
188
+ let(:resource) { Puppet::Type.type(:file).new(:path => path, :recurse => true) }
189
+ let(:graph) { @transaction.relationship_graph }
190
+
191
+ def find_vertex(type, title)
192
+ graph.vertices.find {|v| v.type == type and v.title == title}
193
+ end
194
+
195
+ before :each do
196
+ @filenames = []
197
+
198
+ 'a'.upto('c') do |x|
199
+ @filenames << File.join(path,x)
200
+
201
+ 'a'.upto('c') do |y|
202
+ @filenames << File.join(path,x,y)
203
+ FileUtils.mkdir_p(File.join(path,x,y))
204
+
205
+ 'a'.upto('c') do |z|
206
+ @filenames << File.join(path,x,y,z)
207
+ FileUtils.touch(File.join(path,x,y,z))
208
+ end
209
+ end
210
+ end
211
+
212
+ @transaction.catalog.add_resource(resource)
213
+ end
214
+
215
+ it "should add the generated resources to the catalog" do
216
+ @transaction.eval_generate(resource)
217
+
218
+ @filenames.each do |file|
219
+ @transaction.catalog.resource(:file, file).should be_a(Puppet::Type.type(:file))
220
+ end
221
+ end
222
+
223
+ it "should add a sentinel whit for the resource" do
224
+ @transaction.eval_generate(resource)
225
+
226
+ find_vertex(:whit, "completed_#{path}").should be_a(Puppet::Type.type(:whit))
227
+ end
228
+
229
+ it "should replace dependencies on the resource with dependencies on the sentinel" do
230
+ dependent = Puppet::Type.type(:notify).new(:name => "hello", :require => resource)
231
+
232
+ @transaction.catalog.add_resource(dependent)
233
+
234
+ res = find_vertex(resource.type, resource.title)
235
+ generated = find_vertex(dependent.type, dependent.title)
236
+
237
+ graph.should be_edge(res, generated)
238
+
239
+ @transaction.eval_generate(resource)
240
+
241
+ sentinel = find_vertex(:whit, "completed_#{path}")
242
+
243
+ graph.should be_edge(sentinel, generated)
244
+ graph.should_not be_edge(res, generated)
245
+ end
246
+
247
+ it "should add an edge from the nearest ancestor to the generated resource" do
248
+ @transaction.eval_generate(resource)
249
+
250
+ @filenames.each do |file|
251
+ v = find_vertex(:file, file)
252
+ p = find_vertex(:file, File.dirname(file))
253
+
254
+ graph.should be_edge(p, v)
255
+ end
256
+ end
257
+
258
+ it "should add an edge from each generated resource to the sentinel" do
259
+ @transaction.eval_generate(resource)
260
+
261
+ sentinel = find_vertex(:whit, "completed_#{path}")
262
+ @filenames.each do |file|
263
+ v = find_vertex(:file, file)
264
+
265
+ graph.should be_edge(v, sentinel)
266
+ end
267
+ end
268
+
269
+ it "should add an edge from the resource to the sentinel" do
270
+ @transaction.eval_generate(resource)
271
+
272
+ res = find_vertex(:file, path)
273
+ sentinel = find_vertex(:whit, "completed_#{path}")
274
+
275
+ graph.should be_edge(res, sentinel)
276
+ end
277
+
278
+ it "should return false if an error occured when generating resources" do
279
+ resource.stubs(:eval_generate).raises(Puppet::Error)
280
+
281
+ @transaction.eval_generate(resource).should == false
282
+ end
283
+
284
+ it "should return true if resources were generated" do
285
+ @transaction.eval_generate(resource).should == true
286
+ end
287
+
288
+ it "should not add a sentinel if no resources are generated" do
289
+ path2 = tmpfile('empty')
290
+ other_file = Puppet::Type.type(:file).new(:path => path2)
291
+
292
+ @transaction.catalog.add_resource(other_file)
293
+
294
+ @transaction.eval_generate(other_file).should == false
295
+
296
+ find_vertex(:whit, "completed_#{path2}").should be_nil
297
+ end
298
+ end
299
+
300
+ describe "#unblock" do
301
+ let(:graph) { @transaction.relationship_graph }
302
+ let(:resource) { Puppet::Type.type(:notify).new(:name => 'foo') }
303
+
304
+ it "should calculate the number of blockers if it's not known" do
305
+ graph.add_vertex(resource)
306
+ 3.times do |i|
307
+ other = Puppet::Type.type(:notify).new(:name => i.to_s)
308
+ graph.add_vertex(other)
309
+ graph.add_edge(other, resource)
310
+ end
311
+
312
+ graph.unblock(resource)
313
+
314
+ graph.blockers[resource].should == 2
315
+ end
316
+
317
+ it "should decrement the number of blockers if there are any" do
318
+ graph.blockers[resource] = 40
319
+
320
+ graph.unblock(resource)
321
+
322
+ graph.blockers[resource].should == 39
323
+ end
324
+
325
+ it "should warn if there are no blockers" do
326
+ vertex = stub('vertex')
327
+ vertex.expects(:warning).with "appears to have a negative number of dependencies"
328
+ graph.blockers[vertex] = 0
329
+
330
+ graph.unblock(vertex)
331
+ end
332
+
333
+ it "should return true if the resource is now unblocked" do
334
+ graph.blockers[resource] = 1
335
+
336
+ graph.unblock(resource).should == true
337
+ end
338
+
339
+ it "should return false if the resource is still blocked" do
340
+ graph.blockers[resource] = 2
341
+
342
+ graph.unblock(resource).should == false
343
+ end
344
+ end
345
+
346
+ describe "#finish" do
347
+ let(:graph) { @transaction.relationship_graph }
348
+ let(:path) { tmpdir('eval_generate') }
349
+ let(:resource) { Puppet::Type.type(:file).new(:path => path, :recurse => true) }
350
+
351
+ before :each do
352
+ @transaction.catalog.add_resource(resource)
353
+ end
354
+
355
+ it "should unblock the resource's dependents and queue them if ready" do
356
+ dependent = Puppet::Type.type(:file).new(:path => tmpfile('dependent'), :require => resource)
357
+ more_dependent = Puppet::Type.type(:file).new(:path => tmpfile('more_dependent'), :require => [resource, dependent])
358
+ @transaction.catalog.add_resource(dependent, more_dependent)
359
+
360
+ graph.finish(resource)
361
+
362
+ graph.blockers[dependent].should == 0
363
+ graph.blockers[more_dependent].should == 1
364
+
365
+ key = graph.unguessable_deterministic_key[dependent]
366
+
367
+ graph.ready[key].must == dependent
368
+
369
+ graph.ready.should_not be_has_key(graph.unguessable_deterministic_key[more_dependent])
370
+ end
371
+
372
+ it "should mark the resource as done" do
373
+ graph.finish(resource)
374
+
375
+ graph.done[resource].should == true
376
+ end
377
+ end
378
+
379
+ describe "when traversing" do
380
+ let(:graph) { @transaction.relationship_graph }
381
+ let(:path) { tmpdir('eval_generate') }
382
+ let(:resource) { Puppet::Type.type(:file).new(:path => path, :recurse => true) }
383
+
384
+ before :each do
385
+ @transaction.catalog.add_resource(resource)
386
+ end
387
+
388
+ it "should clear blockers if resources are added" do
389
+ graph.blockers['foo'] = 3
390
+ graph.blockers['bar'] = 4
391
+
392
+ graph.ready[graph.unguessable_deterministic_key[resource]] = resource
393
+
394
+ @transaction.expects(:eval_generate).with(resource).returns true
395
+
396
+ graph.traverse {}
397
+
398
+ graph.blockers.should be_empty
399
+ end
400
+
401
+ it "should yield the resource even if eval_generate is called" do
402
+ graph.ready[graph.unguessable_deterministic_key[resource]] = resource
403
+
404
+ @transaction.expects(:eval_generate).with(resource).returns true
405
+
406
+ yielded = false
407
+ graph.traverse do |res|
408
+ yielded = true if res == resource
409
+ end
410
+
411
+ yielded.should == true
412
+ end
413
+
414
+ it "should prefetch the provider if necessary" do
415
+ @transaction.expects(:prefetch_if_necessary).with(resource)
416
+
417
+ graph.traverse {}
418
+ end
419
+
420
+ it "should not clear blockers if resources aren't added" do
421
+ graph.blockers['foo'] = 3
422
+ graph.blockers['bar'] = 4
423
+
424
+ graph.ready[graph.unguessable_deterministic_key[resource]] = resource
425
+
426
+ @transaction.expects(:eval_generate).with(resource).returns false
427
+
428
+ graph.traverse {}
429
+
430
+ graph.blockers.should == {'foo' => 3, 'bar' => 4, resource => 0}
431
+ end
432
+
433
+ it "should unblock all dependents of the resource" do
434
+ dependent = Puppet::Type.type(:notify).new(:name => "hello", :require => resource)
435
+ dependent2 = Puppet::Type.type(:notify).new(:name => "goodbye", :require => resource)
436
+
437
+ @transaction.catalog.add_resource(dependent, dependent2)
438
+
439
+ graph.blockers[dependent].should == 1
440
+ graph.blockers[dependent2].should == 1
441
+
442
+ graph.ready[graph.unguessable_deterministic_key[resource]] = resource
443
+
444
+ graph.traverse {}
445
+
446
+ graph.blockers[dependent].should == 0
447
+ graph.blockers[dependent2].should == 0
448
+ end
449
+
450
+ it "should enqueue any unblocked dependents" do
451
+ dependent = Puppet::Type.type(:notify).new(:name => "hello", :require => resource)
452
+ dependent2 = Puppet::Type.type(:notify).new(:name => "goodbye", :require => resource)
453
+
454
+ @transaction.catalog.add_resource(dependent, dependent2)
455
+
456
+ graph.blockers[dependent].should == 1
457
+ graph.blockers[dependent2].should == 1
458
+
459
+ graph.ready[graph.unguessable_deterministic_key[resource]] = resource
460
+
461
+ seen = []
462
+
463
+ graph.traverse do |res|
464
+ seen << res
465
+ end
466
+
467
+ seen.should =~ [resource, dependent, dependent2]
468
+ end
469
+
470
+ it "should mark the resource done" do
471
+ graph.ready[graph.unguessable_deterministic_key[resource]] = resource
472
+
473
+ graph.traverse {}
474
+
475
+ graph.done[resource].should == true
476
+ end
477
+
478
+ it "should not evaluate the resource if it's not suitable" do
479
+ resource.stubs(:suitable?).returns false
480
+
481
+ graph.traverse do |resource|
482
+ raise "evaluated a resource"
483
+ end
484
+ end
485
+
486
+ it "should defer an unsuitable resource unless it can't go on" do
487
+ other = Puppet::Type.type(:notify).new(:name => "hello")
488
+ @transaction.catalog.add_resource(other)
489
+
490
+ # Show that we check once, then get the resource back and check again
491
+ resource.expects(:suitable?).twice.returns(false).then.returns(true)
492
+
493
+ graph.traverse {}
494
+ end
495
+
496
+ it "should fail unsuitable resources and go on if it gets blocked" do
497
+ dependent = Puppet::Type.type(:notify).new(:name => "hello", :require => resource)
498
+ @transaction.catalog.add_resource(dependent)
499
+
500
+ resource.stubs(:suitable?).returns false
501
+
502
+ evaluated = []
503
+ graph.traverse do |res|
504
+ evaluated << res
505
+ end
506
+
507
+ # We should have gone on to evaluate the children
508
+ evaluated.should == [dependent]
509
+ @transaction.resource_status(resource).should be_failed
510
+ end
511
+ end
512
+
185
513
  describe "when generating resources" do
186
514
  it "should call 'generate' on all created resources" do
187
515
  first = Puppet::Type.type(:notify).new(:name => "first")
@@ -199,7 +527,7 @@ describe Puppet::Transaction do
199
527
  end
200
528
 
201
529
  it "should finish all resources" do
202
- generator = stub 'generator', :depthfirst? => true, :tags => []
530
+ generator = stub 'generator', :depthfirst? => true, :tags => [], :ref => "Some[resource]"
203
531
  resource = stub 'resource', :tag => nil
204
532
 
205
533
  @catalog = Puppet::Resource::Catalog.new
@@ -232,8 +560,8 @@ describe Puppet::Transaction do
232
560
  end
233
561
 
234
562
  it "should copy all tags to the newly generated resources" do
235
- child = stub 'child'
236
- generator = stub 'resource', :tags => ["one", "two"]
563
+ child = stub 'child', :ref => "Some[child_resource]"
564
+ generator = stub 'resource', :tags => ["one", "two"], :ref => "Some[resource]"
237
565
 
238
566
  @catalog = Puppet::Resource::Catalog.new
239
567
  @transaction = Puppet::Transaction.new(@catalog)
@@ -351,17 +679,72 @@ describe Puppet::Transaction do
351
679
  end
352
680
 
353
681
  describe "when prefetching" do
354
- it "should match resources by name, not title" do
355
- @catalog = Puppet::Resource::Catalog.new
356
- @transaction = Puppet::Transaction.new(@catalog)
682
+ let(:catalog) { Puppet::Resource::Catalog.new }
683
+ let(:transaction) { Puppet::Transaction.new(catalog) }
684
+ let(:resource) { Puppet::Type.type(:sshkey).create :title => "foo", :name => "bar", :type => :dsa, :key => "eh", :provider => :parsed }
685
+ let(:resource2) { Puppet::Type.type(:package).create :title => "blah", :provider => "apt" }
357
686
 
358
- # Have both a title and name
359
- resource = Puppet::Type.type(:sshkey).create :title => "foo", :name => "bar", :type => :dsa, :key => "eh"
360
- @catalog.add_resource resource
687
+ before :each do
688
+ catalog.add_resource resource
689
+ catalog.add_resource resource2
690
+ end
691
+
692
+
693
+ describe "#resources_by_provider" do
694
+ it "should fetch resources by their type and provider" do
695
+ transaction.resources_by_provider(:sshkey, :parsed).should == {
696
+ resource.name => resource,
697
+ }
698
+
699
+ transaction.resources_by_provider(:package, :apt).should == {
700
+ resource2.name => resource2,
701
+ }
702
+ end
703
+
704
+ it "should omit resources whose types don't use providers" do
705
+ # faking the sshkey type not to have a provider
706
+ resource.class.stubs(:attrclass).returns nil
707
+
708
+ transaction.resources_by_provider(:sshkey, :parsed).should == {}
709
+ end
361
710
 
711
+ it "should return empty hash for providers with no resources" do
712
+ transaction.resources_by_provider(:package, :yum).should == {}
713
+ end
714
+ end
715
+
716
+ it "should match resources by name, not title" do
362
717
  resource.provider.class.expects(:prefetch).with("bar" => resource)
363
718
 
364
- @transaction.prefetch
719
+ transaction.prefetch_if_necessary(resource)
720
+ end
721
+
722
+ it "should not prefetch a provider which has already been prefetched" do
723
+ transaction.prefetched_providers[:sshkey][:parsed] = true
724
+
725
+ resource.provider.class.expects(:prefetch).never
726
+
727
+ transaction.prefetch_if_necessary(resource)
728
+ end
729
+
730
+ it "should mark the provider prefetched" do
731
+ resource.provider.class.stubs(:prefetch)
732
+
733
+ transaction.prefetch_if_necessary(resource)
734
+
735
+ transaction.prefetched_providers[:sshkey][:parsed].should be_true
736
+ end
737
+
738
+ it "should prefetch resources without a provider if prefetching the default provider" do
739
+ other = Puppet::Type.type(:sshkey).create :name => "other"
740
+
741
+ other.instance_variable_set(:@provider, nil)
742
+
743
+ catalog.add_resource other
744
+
745
+ resource.provider.class.expects(:prefetch).with('bar' => resource, 'other' => other)
746
+
747
+ transaction.prefetch_if_necessary(resource)
365
748
  end
366
749
  end
367
750
 
@@ -407,7 +790,7 @@ describe Puppet::Transaction do
407
790
  before do
408
791
  @resource = Puppet::Type.type(:notify).new :title => "foobar"
409
792
  @catalog.add_resource @resource
410
- @transaction.stubs(:prepare)
793
+ @transaction.stubs(:add_dynamically_generated_resources)
411
794
  end
412
795
 
413
796
  it 'should stop processing if :stop_processing? is true' do