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
@@ -10,19 +10,19 @@ config = Puppet::Util::Reference.newreference(:configuration, :depth => 1, :doc
10
10
  }.each do |name, object|
11
11
  # Make each name an anchor
12
12
  header = name.to_s
13
- str += h(header, 3)
13
+ str << markdown_header(header, 3)
14
14
 
15
15
  # Print the doc string itself
16
16
  begin
17
- str += object.desc.gsub(/\n/, " ")
17
+ str << object.desc.gsub(/\n/, " ")
18
18
  rescue => detail
19
19
  puts detail.backtrace
20
20
  puts detail
21
21
  end
22
- str += "\n\n"
22
+ str << "\n\n"
23
23
 
24
24
  # Now print the data about the item.
25
- str += ""
25
+ str << ""
26
26
  val = object.default
27
27
  if name.to_s == "vardir"
28
28
  val = "/var/lib/puppet"
@@ -31,11 +31,11 @@ config = Puppet::Util::Reference.newreference(:configuration, :depth => 1, :doc
31
31
  end
32
32
 
33
33
  # Leave out the section information; it was apparently confusing people.
34
- #str += "- **Section**: #{object.section}\n"
34
+ #str << "- **Section**: #{object.section}\n"
35
35
  unless val == ""
36
- str += "- *Default*: #{val}\n"
36
+ str << "- *Default*: #{val}\n"
37
37
  end
38
- str += "\n"
38
+ str << "\n"
39
39
  end
40
40
 
41
41
  return str
@@ -8,16 +8,15 @@ reference = Puppet::Util::Reference.newreference :indirection, :doc => "Indirect
8
8
  Puppet::Indirector::Indirection.instances.sort { |a,b| a.to_s <=> b.to_s }.each do |indirection|
9
9
  ind = Puppet::Indirector::Indirection.instance(indirection)
10
10
  name = indirection.to_s.capitalize
11
- text += "## " + indirection.to_s + "\n\n"
11
+ text << "## " + indirection.to_s + "\n\n"
12
12
 
13
- text += ind.doc + "\n\n"
13
+ text << ind.doc + "\n\n"
14
14
 
15
15
  Puppet::Indirector::Terminus.terminus_classes(ind.name).sort { |a,b| a.to_s <=> b.to_s }.each do |terminus|
16
- text += "### " + terminus.to_s + "\n\n"
17
-
16
+ terminus_name = terminus.to_s
18
17
  term_class = Puppet::Indirector::Terminus.terminus_class(ind.name, terminus)
19
-
20
- text += Puppet::Util::Docs.scrub(term_class.doc) + "\n\n"
18
+ terminus_doc = Puppet::Util::Docs.scrub(term_class.doc)
19
+ text << markdown_definitionlist(terminus_name, terminus_doc)
21
20
  end
22
21
  end
23
22
 
@@ -29,7 +29,9 @@ in your manifest, including defined components.
29
29
  params.sort { |a,b|
30
30
  a.to_s <=> b.to_s
31
31
  }.each { |param|
32
- str += paramwrap(param.to_s, scrub(Puppet::Type.metaparamdoc(param)), :level => 3)
32
+ str << markdown_header(param.to_s, 3)
33
+ str << scrub(Puppet::Type.metaparamdoc(param))
34
+ str << "\n\n"
33
35
  }
34
36
  rescue => detail
35
37
  puts detail.backtrace
@@ -9,14 +9,14 @@ network = Puppet::Util::Reference.newreference :network, :depth => 2, :doc => "A
9
9
 
10
10
  interface = handler.interface
11
11
 
12
- ret += h(name, 2)
13
-
14
- ret += scrub(handler.doc)
15
- ret += "\n\n"
16
- ret += option(:prefix, interface.prefix)
17
- ret += option(:side, handler.side.to_s.capitalize)
18
- ret += option(:methods, interface.methods.collect { |ary| ary[0] }.join(", ") )
19
- ret += "\n\n"
12
+ ret << markdown_header(name, 2)
13
+
14
+ ret << scrub(handler.doc)
15
+ ret << "\n\n"
16
+ ret << option(:prefix, interface.prefix)
17
+ ret << option(:side, handler.side.to_s.capitalize)
18
+ ret << option(:methods, interface.methods.collect { |ary| ary[0] }.join(", ") )
19
+ ret << "\n\n"
20
20
  end
21
21
 
22
22
  ret
@@ -17,16 +17,16 @@ providers = Puppet::Util::Reference.newreference :providers, :title => "Provider
17
17
  ["Ruby Version", "Puppet Version", "Operating System", "Operating System Release"].each do |label|
18
18
  name = label.gsub(/\s+/, '')
19
19
  value = Facter.value(name)
20
- ret += option(label, value)
20
+ ret << option(label, value)
21
21
  end
22
- ret += "\n"
22
+ ret << "\n"
23
23
 
24
24
  count = 1
25
25
 
26
26
  # Produce output for each type.
27
27
  types.each do |type|
28
28
  features = type.features
29
- ret += "\n" # add a trailing newline
29
+ ret << "\n" # add a trailing newline
30
30
 
31
31
  # Now build up a table of provider suitability.
32
32
  headers = %w{Provider Suitable?} + features.collect { |f| f.to_s }.sort
@@ -35,11 +35,7 @@ providers = Puppet::Util::Reference.newreference :providers, :title => "Provider
35
35
 
36
36
  functional = false
37
37
  notes = []
38
- begin
39
- default = type.defaultprovider.name
40
- rescue Puppet::DevError
41
- default = "none"
42
- end
38
+ default = type.defaultprovider ? type.defaultprovider.name : 'none'
43
39
  type.providers.sort { |a,b| a.to_s <=> b.to_s }.each do |pname|
44
40
  data = []
45
41
  table_data[pname] = data
@@ -61,21 +57,21 @@ providers = Puppet::Util::Reference.newreference :providers, :title => "Provider
61
57
  missing.each do |test, values|
62
58
  case test
63
59
  when :exists
64
- details += " - Missing files #{values.join(", ")}\n"
60
+ details << " - Missing files #{values.join(", ")}\n"
65
61
  when :variable
66
62
  values.each do |name, facts|
67
63
  if Puppet.settings.valid?(name)
68
- details += " - Setting #{name} (currently #{Puppet.settings.value(name).inspect}) not in list #{facts.join(", ")}\n"
64
+ details << " - Setting #{name} (currently #{Puppet.settings.value(name).inspect}) not in list #{facts.join(", ")}\n"
69
65
  else
70
- details += " - Fact #{name} (currently #{Facter.value(name).inspect}) not in list #{facts.join(", ")}\n"
66
+ details << " - Fact #{name} (currently #{Facter.value(name).inspect}) not in list #{facts.join(", ")}\n"
71
67
  end
72
68
  end
73
69
  when :true
74
- details += " - Got #{values} true tests that should have been false\n"
70
+ details << " - Got #{values} true tests that should have been false\n"
75
71
  when :false
76
- details += " - Got #{values} false tests that should have been true\n"
72
+ details << " - Got #{values} false tests that should have been true\n"
77
73
  when :feature
78
- details += " - Missing features #{values.collect { |f| f.to_s }.join(",")}\n"
74
+ details << " - Missing features #{values.collect { |f| f.to_s }.join(",")}\n"
79
75
  end
80
76
  end
81
77
  notes << details
@@ -93,20 +89,20 @@ providers = Puppet::Util::Reference.newreference :providers, :title => "Provider
93
89
  end
94
90
  end
95
91
 
96
- ret += h(type.name.to_s + "_", 2)
92
+ ret << markdown_header(type.name.to_s + "_", 2)
97
93
 
98
- ret += "[#{type.name}](#{"http://docs.puppetlabs.com/references/stable/type.html##{type.name}"})\n\n"
99
- ret += option("Default provider", default)
100
- ret += doctable(headers, table_data)
94
+ ret << "[#{type.name}](#{"http://docs.puppetlabs.com/references/stable/type.html##{type.name}"})\n\n"
95
+ ret << option("Default provider", default)
96
+ ret << doctable(headers, table_data)
101
97
 
102
98
  notes.each do |note|
103
- ret += note + "\n"
99
+ ret << note + "\n"
104
100
  end
105
101
 
106
- ret += "\n"
102
+ ret << "\n"
107
103
  end
108
104
 
109
- ret += "\n"
105
+ ret << "\n"
110
106
 
111
107
  ret
112
108
  end
@@ -23,7 +23,7 @@ type = Puppet::Util::Reference.newreference :type, :doc => "All Puppet resource
23
23
  file { "/etc/passwd":
24
24
  owner => root,
25
25
  group => root,
26
- mode => 644
26
+ mode => 644
27
27
  }
28
28
 
29
29
  `/etc/passwd` is considered the title of the file object (used for things like
@@ -54,19 +54,19 @@ type = Puppet::Util::Reference.newreference :type, :doc => "All Puppet resource
54
54
  a.to_s <=> b.to_s
55
55
  }.each { |name,type|
56
56
 
57
- str += "
57
+ str << "
58
58
 
59
59
  ----------------
60
60
 
61
61
  "
62
62
 
63
- str += h(name, 3)
64
- str += scrub(type.doc) + "\n\n"
63
+ str << markdown_header(name, 3)
64
+ str << scrub(type.doc) + "\n\n"
65
65
 
66
66
  # Handle the feature docs.
67
67
  if featuredocs = type.featuredocs
68
- str += h("Features", 4)
69
- str += featuredocs
68
+ str << markdown_header("Features", 4)
69
+ str << featuredocs
70
70
  end
71
71
 
72
72
  docs = {}
@@ -92,7 +92,7 @@ type = Puppet::Util::Reference.newreference :type, :doc => "All Puppet resource
92
92
  docs[sname] = tmp
93
93
  }
94
94
 
95
- str += h("Parameters", 4) + "\n"
95
+ str << markdown_header("Parameters", 4) + "\n"
96
96
  type.parameters.sort { |a,b|
97
97
  a.to_s <=> b.to_s
98
98
  }.each { |name,param|
@@ -104,9 +104,12 @@ type = Puppet::Util::Reference.newreference :type, :doc => "All Puppet resource
104
104
  docs.sort { |a, b|
105
105
  a[0].to_s <=> b[0].to_s
106
106
  }.each { |name, doc|
107
- str += paramwrap(name, doc, :namevar => additional_key_attributes.include?(name))
107
+ if additional_key_attributes.include?(name)
108
+ doc = "(**Namevar:** If omitted, this parameter's value defaults to the resource's title.)\n\n" + doc
109
+ end
110
+ str << markdown_definitionlist(name, doc)
108
111
  }
109
- str += "\n"
112
+ str << "\n"
110
113
  }
111
114
 
112
115
  str
@@ -1,6 +1,7 @@
1
1
  require 'puppet'
2
2
  require 'puppet/util/tagging'
3
3
  require 'puppet/util/pson'
4
+ require 'puppet/parameter'
4
5
 
5
6
  # The simplest resource class. Eventually it will function as the
6
7
  # base class for all resource-like behaviour.
@@ -264,11 +265,7 @@ class Puppet::Resource
264
265
 
265
266
  attributes = attr.collect { |k|
266
267
  v = parameters[k]
267
- if v.is_a? Array
268
- " %-#{attr_max}s => %s,\n" % [ k, "[\'#{v.join("', '")}\']" ]
269
- else
270
- " %-#{attr_max}s => %s,\n" % [ k, "\'#{v}\'" ]
271
- end
268
+ " %-#{attr_max}s => %s,\n" % [k, Puppet::Parameter.format_value_for_display(v)]
272
269
  }.join
273
270
 
274
271
  "%s { '%s':\n%s}" % [self.type.to_s.downcase, self.title, attributes]
@@ -361,7 +361,7 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
361
361
  #
362
362
  # These two hashes comprise the aforementioned attention to the possible
363
363
  # case of containers that contain / depend on other containers; they map
364
- # containers to their sentinals but pass other verticies through. Thus we
364
+ # containers to their sentinels but pass other verticies through. Thus we
365
365
  # can "do the right thing" for references to other verticies that may or
366
366
  # may not be containers.
367
367
  #
@@ -146,4 +146,74 @@ class Puppet::SSL::CertificateRequest < Puppet::SSL::Base
146
146
  sort.
147
147
  uniq
148
148
  end
149
+
150
+ # Return the set of extensions requested on this CSR, in a form designed to
151
+ # be useful to Ruby: a hash. Which, not coincidentally, you can pass
152
+ # successfully to the OpenSSL constructor later, if you want.
153
+ def request_extensions
154
+ raise Puppet::Error, "CSR needs content to extract fields" unless @content
155
+
156
+ # Prefer the standard extReq, but accept the Microsoft specific version as
157
+ # a fallback, if the standard version isn't found.
158
+ ext = @content.attributes.find {|x| x.oid == "extReq" } or
159
+ @content.attributes.find {|x| x.oid == "msExtReq" }
160
+ return [] unless ext
161
+
162
+ # Assert the structure and extract the names into an array of arrays.
163
+ unless ext.value.is_a? OpenSSL::ASN1::Set
164
+ raise Puppet::Error, "In #{ext.oid}, expected Set but found #{ext.value.class}"
165
+ end
166
+
167
+ unless ext.value.value.is_a? Array
168
+ raise Puppet::Error, "In #{ext.oid}, expected Set[Array] but found #{ext.value.value.class}"
169
+ end
170
+
171
+ unless ext.value.value.length == 1
172
+ raise Puppet::Error, "In #{ext.oid}, expected Set[Array[...]], but found #{ext.value.value.length} items in the array"
173
+ end
174
+
175
+ san = ext.value.value.first
176
+ unless san.is_a? OpenSSL::ASN1::Sequence
177
+ raise Puppet::Error, "In #{ext.oid}, expected Set[Array[Sequence[...]]], but found #{san.class}"
178
+ end
179
+ san = san.value
180
+
181
+ # OK, now san should be the array of items, validate that...
182
+ index = -1
183
+ san.map do |name|
184
+ index += 1
185
+
186
+ unless name.is_a? OpenSSL::ASN1::Sequence
187
+ raise Puppet::Error, "In #{ext.oid}, expected request extension record #{index} to be a Sequence, but found #{name.class}"
188
+ end
189
+ name = name.value
190
+
191
+ # OK, turn that into an extension, to unpack the content. Lovely that
192
+ # we have to swap the order of arguments to the underlying method, or
193
+ # perhaps that the ASN.1 representation chose to pack them in a
194
+ # strange order where the optional component comes *earlier* than the
195
+ # fixed component in the sequence.
196
+ case name.length
197
+ when 2
198
+ ev = OpenSSL::X509::Extension.new(name[0].value, name[1].value)
199
+ { "oid" => ev.oid, "value" => ev.value }
200
+
201
+ when 3
202
+ ev = OpenSSL::X509::Extension.new(name[0].value, name[2].value, name[1].value)
203
+ { "oid" => ev.oid, "value" => ev.value, "critical" => ev.critical? }
204
+
205
+ else
206
+ raise Puppet::Error, "In #{ext.oid}, expected extension record #{index} to have two or three items, but found #{name.length}"
207
+ end
208
+ end.flatten
209
+ end
210
+
211
+ def subject_alt_names
212
+ @subject_alt_names ||= request_extensions.
213
+ select {|x| x["oid"] = "subjectAltName" }.
214
+ map {|x| x["value"].split(/\s*,\s*/) }.
215
+ flatten.
216
+ sort.
217
+ uniq
218
+ end
149
219
  end
@@ -160,6 +160,10 @@ class Puppet::SSL::Host
160
160
  name == Puppet[:certname].downcase
161
161
  end
162
162
 
163
+ def this_csr_is_for_the_current_host
164
+ name == Puppet[:certname].downcase
165
+ end
166
+
163
167
  # Our certificate request requires the key but that's all.
164
168
  def generate_certificate_request(options = {})
165
169
  generate_key unless key
@@ -169,6 +173,8 @@ class Puppet::SSL::Host
169
173
  # ...add our configured dns_alt_names
170
174
  if Puppet[:dns_alt_names] and Puppet[:dns_alt_names] != ''
171
175
  options[:dns_alt_names] ||= Puppet[:dns_alt_names]
176
+ elsif Puppet::SSL::CertificateAuthority.ca? and fqdn = Facter.value(:fqdn) and domain = Facter.value(:domain)
177
+ options[:dns_alt_names] = "puppet, #{fqdn}, puppet.#{domain}"
172
178
  end
173
179
  end
174
180
 
@@ -92,7 +92,7 @@ class Puppet::Transaction
92
92
  # collects all of the changes, executes them, and responds to any
93
93
  # necessary events.
94
94
  def evaluate
95
- prepare
95
+ add_dynamically_generated_resources
96
96
 
97
97
  Puppet.info "Applying configuration version '#{catalog.version}'" if catalog.version
98
98
 
@@ -145,15 +145,18 @@ class Puppet::Transaction
145
145
  end
146
146
 
147
147
  def eval_generate(resource)
148
+ return false unless resource.respond_to?(:eval_generate)
148
149
  raise Puppet::DevError,"Depthfirst resources are not supported by eval_generate" if resource.depthfirst?
149
150
  begin
150
- made = resource.eval_generate.uniq.reverse
151
+ made = resource.eval_generate.uniq
152
+ return false if made.empty?
153
+ made = Hash[made.map(&:name).zip(made)]
151
154
  rescue => detail
152
155
  puts detail.backtrace if Puppet[:trace]
153
156
  resource.err "Failed to generate additional resources using 'eval_generate: #{detail}"
154
- return
157
+ return false
155
158
  end
156
- made.each do |res|
159
+ made.values.each do |res|
157
160
  begin
158
161
  res.tag(*resource.tags)
159
162
  @catalog.add_resource(res)
@@ -162,17 +165,34 @@ class Puppet::Transaction
162
165
  res.info "Duplicate generated resource; skipping"
163
166
  end
164
167
  end
165
- sentinal = Puppet::Type::Whit.new(:name => "completed_#{resource.title}", :catalog => resource.catalog)
168
+ sentinel = Puppet::Type.type(:whit).new(:name => "completed_#{resource.title}", :catalog => resource.catalog)
169
+
170
+ # The completed whit is now the thing that represents the resource is done
166
171
  relationship_graph.adjacent(resource,:direction => :out,:type => :edges).each { |e|
167
- add_conditional_directed_dependency(sentinal, e.target, e.label)
172
+ # But children run as part of the resource, not after it
173
+ next if made[e.target.name]
174
+
175
+ add_conditional_directed_dependency(sentinel, e.target, e.label)
168
176
  relationship_graph.remove_edge! e
169
177
  }
178
+
170
179
  default_label = Puppet::Resource::Catalog::Default_label
171
- made.each do |res|
172
- add_conditional_directed_dependency(made.find { |r| r != res && r.name == res.name[0,r.name.length]} || resource, res)
173
- add_conditional_directed_dependency(res, sentinal, default_label)
180
+ made.values.each do |res|
181
+ # Depend on the nearest ancestor we generated, falling back to the
182
+ # resource if we have none
183
+ parent_name = res.ancestors.find { |a| made[a] and made[a] != res }
184
+ parent = made[parent_name] || resource
185
+
186
+ add_conditional_directed_dependency(parent, res)
187
+
188
+ # This resource isn't 'completed' until each child has run
189
+ add_conditional_directed_dependency(res, sentinel, default_label)
174
190
  end
175
- add_conditional_directed_dependency(resource, sentinal, default_label)
191
+
192
+ # This edge allows the resource's events to propagate, though it isn't
193
+ # strictly necessary for ordering purposes
194
+ add_conditional_directed_dependency(resource, sentinel, default_label)
195
+ true
176
196
  end
177
197
 
178
198
  # A general method for recursively generating new resources from a
@@ -200,9 +220,7 @@ class Puppet::Transaction
200
220
  end
201
221
  end
202
222
 
203
- # Collect any dynamically generated resources. This method is called
204
- # before the transaction starts.
205
- def xgenerate
223
+ def add_dynamically_generated_resources
206
224
  @catalog.vertices.each { |resource| generate_additional_resources(resource) }
207
225
  end
208
226
 
@@ -221,41 +239,56 @@ class Puppet::Transaction
221
239
  @event_manager = Puppet::Transaction::EventManager.new(self)
222
240
 
223
241
  @resource_harness = Puppet::Transaction::ResourceHarness.new(self)
242
+
243
+ @prefetched_providers = Hash.new { |h,k| h[k] = {} }
224
244
  end
225
245
 
226
- # Prefetch any providers that support it. We don't support prefetching
227
- # types, just providers.
228
- def prefetch
229
- prefetchers = {}
230
- @catalog.vertices.each do |resource|
231
- if provider = resource.provider and provider.class.respond_to?(:prefetch)
232
- prefetchers[provider.class] ||= {}
233
- prefetchers[provider.class][resource.name] = resource
234
- end
235
- end
246
+ def resources_by_provider(type_name, provider_name)
247
+ unless @resources_by_provider
248
+ @resources_by_provider = Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } }
236
249
 
237
- # Now call prefetch, passing in the resources so that the provider instances can be replaced.
238
- prefetchers.each do |provider, resources|
239
- Puppet.debug "Prefetching #{provider.name} resources for #{provider.resource_type.name}"
240
- begin
241
- provider.prefetch(resources)
242
- rescue => detail
243
- puts detail.backtrace if Puppet[:trace]
244
- Puppet.err "Could not prefetch #{provider.resource_type.name} provider '#{provider.name}': #{detail}"
250
+ @catalog.vertices.each do |resource|
251
+ if resource.class.attrclass(:provider)
252
+ prov = resource.provider && resource.provider.class.name
253
+ @resources_by_provider[resource.type][prov][resource.name] = resource
254
+ end
245
255
  end
246
256
  end
257
+
258
+ @resources_by_provider[type_name][provider_name] || {}
247
259
  end
248
260
 
249
- # Prepare to evaluate the resources in a transaction.
250
- def prepare
251
- # Now add any dynamically generated resources
252
- xgenerate
261
+ def prefetch_if_necessary(resource)
262
+ provider_class = resource.provider.class
263
+ return unless provider_class.respond_to?(:prefetch) and !prefetched_providers[resource.type][provider_class.name]
253
264
 
254
- # Then prefetch. It's important that we generate and then prefetch,
255
- # so that any generated resources also get prefetched.
256
- prefetch
265
+ resources = resources_by_provider(resource.type, provider_class.name)
266
+
267
+ if provider_class == resource.class.defaultprovider
268
+ providerless_resources = resources_by_provider(resource.type, nil)
269
+ providerless_resources.values.each {|res| res.provider = provider_class.name}
270
+ resources.merge! providerless_resources
271
+ end
272
+
273
+ prefetch(provider_class, resources)
257
274
  end
258
275
 
276
+ attr_reader :prefetched_providers
277
+
278
+ # Prefetch any providers that support it, yo. We don't support prefetching
279
+ # types, just providers.
280
+ def prefetch(provider_class, resources)
281
+ type_name = provider_class.resource_type.name
282
+ return if @prefetched_providers[type_name][provider_class.name]
283
+ Puppet.debug "Prefetching #{provider_class.name} resources for #{type_name}"
284
+ begin
285
+ provider_class.prefetch(resources)
286
+ rescue => detail
287
+ puts detail.backtrace if Puppet[:trace]
288
+ Puppet.err "Could not prefetch #{type_name} provider '#{provider_class.name}': #{detail}"
289
+ end
290
+ @prefetched_providers[type_name][provider_class.name] = true
291
+ end
259
292
 
260
293
  # We want to monitor changes in the relationship graph of our
261
294
  # catalog but this is complicated by the fact that the catalog
@@ -273,46 +306,116 @@ class Puppet::Transaction
273
306
  # except via the Transaction#relationship_graph
274
307
 
275
308
  class Relationship_graph_wrapper
276
- attr_reader :real_graph,:transaction,:ready,:generated,:done,:unguessable_deterministic_key
309
+ require 'puppet/rb_tree_map'
310
+ attr_reader :real_graph,:transaction,:ready,:generated,:done,:blockers,:unguessable_deterministic_key
277
311
  def initialize(real_graph,transaction)
278
312
  @real_graph = real_graph
279
313
  @transaction = transaction
280
- @ready = {}
314
+ @ready = Puppet::RbTreeMap.new
281
315
  @generated = {}
282
316
  @done = {}
283
- @unguessable_deterministic_key = Hash.new { |h,k| h[k] = Digest::SHA1.hexdigest("NaCl, MgSO4 (salts) and then #{k.title}") }
284
- vertices.each { |v| check_if_now_ready(v) }
317
+ @blockers = {}
318
+ @unguessable_deterministic_key = Hash.new { |h,k| h[k] = Digest::SHA1.hexdigest("NaCl, MgSO4 (salts) and then #{k.ref}") }
319
+ @providerless_types = []
320
+ vertices.each do |v|
321
+ blockers[v] = direct_dependencies_of(v).length
322
+ enqueue(v) if blockers[v] == 0
323
+ end
285
324
  end
286
325
  def method_missing(*args,&block)
287
326
  real_graph.send(*args,&block)
288
327
  end
289
328
  def add_vertex(v)
290
329
  real_graph.add_vertex(v)
291
- check_if_now_ready(v) # ?????????????????????????????????????????
292
330
  end
293
331
  def add_edge(f,t,label=nil)
294
- ready.delete(t)
332
+ key = unguessable_deterministic_key[t]
333
+
334
+ ready.delete(key)
335
+
295
336
  real_graph.add_edge(f,t,label)
296
337
  end
297
- def check_if_now_ready(r)
298
- ready[r] = true if direct_dependencies_of(r).all? { |r2| done[r2] }
338
+ # Decrement the blocker count for the resource by 1. If the number of
339
+ # blockers is unknown, count them and THEN decrement by 1.
340
+ def unblock(resource)
341
+ blockers[resource] ||= direct_dependencies_of(resource).select { |r2| !done[r2] }.length
342
+ if blockers[resource] > 0
343
+ blockers[resource] -= 1
344
+ else
345
+ resource.warning "appears to have a negative number of dependencies"
346
+ end
347
+ blockers[resource] <= 0
348
+ end
349
+ def enqueue(*resources)
350
+ resources.each do |resource|
351
+ key = unguessable_deterministic_key[resource]
352
+ ready[key] = resource
353
+ end
354
+ end
355
+ def finish(resource)
356
+ direct_dependents_of(resource).each do |v|
357
+ enqueue(v) if unblock(v)
358
+ end
359
+ done[resource] = true
299
360
  end
300
361
  def next_resource
301
- ready.keys.sort_by { |r0| unguessable_deterministic_key[r0] }.first
362
+ ready.delete_min
302
363
  end
303
364
  def traverse(&block)
304
365
  real_graph.report_cycles_in_graph
305
- while (r = next_resource) && !transaction.stop_processing?
306
- if !generated[r] && r.respond_to?(:eval_generate)
307
- transaction.eval_generate(r)
308
- generated[r] = true
366
+
367
+ deferred_resources = []
368
+
369
+ while (resource = next_resource) && !transaction.stop_processing?
370
+ if resource.suitable?
371
+ made_progress = true
372
+
373
+ transaction.prefetch_if_necessary(resource)
374
+
375
+ # If we generated resources, we don't know what they are now
376
+ # blocking, so we opt to recompute it, rather than try to track every
377
+ # change that would affect the number.
378
+ blockers.clear if transaction.eval_generate(resource)
379
+
380
+ yield resource
381
+
382
+ finish(resource)
309
383
  else
310
- ready.delete(r)
311
- yield r
312
- done[r] = true
313
- direct_dependents_of(r).each { |v| check_if_now_ready(v) }
384
+ deferred_resources << resource
385
+ end
386
+
387
+ if ready.empty? and deferred_resources.any?
388
+ if made_progress
389
+ enqueue(*deferred_resources)
390
+ else
391
+ fail_unsuitable_resources(deferred_resources)
392
+ end
393
+
394
+ made_progress = false
395
+ deferred_resources = []
314
396
  end
315
397
  end
398
+
399
+ # Just once per type. No need to punish the user.
400
+ @providerless_types.uniq.each do |type|
401
+ Puppet.err "Could not find a suitable provider for #{type}"
402
+ end
403
+ end
404
+
405
+ def fail_unsuitable_resources(resources)
406
+ resources.each do |resource|
407
+ # We don't automatically assign unsuitable providers, so if there
408
+ # is one, it must have been selected by the user.
409
+ if resource.provider
410
+ resource.err "Provider #{resource.provider.class.name} is not functional on this host"
411
+ else
412
+ @providerless_types << resource.type
413
+ end
414
+
415
+ transaction.resource_status(resource).failed = true
416
+
417
+ finish(resource)
418
+ end
316
419
  end
317
420
  end
318
421