puppet 2.7.1 → 2.7.3

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 (171) hide show
  1. data/CHANGELOG +225 -1
  2. data/CONTRIBUTING.md +299 -0
  3. data/README.md +0 -1
  4. data/conf/redhat/puppet.spec +132 -25
  5. data/conf/solaris/pkginfo +1 -1
  6. data/conf/suse/puppet.spec +5 -2
  7. data/ext/envpuppet +56 -3
  8. data/ext/vim/README +2 -1
  9. data/ext/vim/ftplugin/puppet.vim +94 -0
  10. data/ext/vim/indent/puppet.vim +76 -0
  11. data/lib/puppet.rb +2 -3
  12. data/lib/puppet/application/agent.rb +7 -7
  13. data/lib/puppet/application/apply.rb +20 -8
  14. data/lib/puppet/application/ca.rb +5 -0
  15. data/lib/puppet/application/cert.rb +2 -1
  16. data/lib/puppet/application/certificate.rb +0 -5
  17. data/lib/puppet/application/device.rb +4 -4
  18. data/lib/puppet/application/doc.rb +23 -12
  19. data/lib/puppet/application/face_base.rb +2 -1
  20. data/lib/puppet/application/inspect.rb +5 -2
  21. data/lib/puppet/configurer.rb +60 -56
  22. data/lib/puppet/configurer/fact_handler.rb +6 -1
  23. data/lib/puppet/defaults.rb +20 -1
  24. data/lib/puppet/face/ca.rb +233 -0
  25. data/lib/puppet/face/certificate.rb +15 -11
  26. data/lib/puppet/face/certificate_request.rb +9 -11
  27. data/lib/puppet/face/certificate_revocation_list.rb +5 -7
  28. data/lib/puppet/face/node/clean.rb +154 -0
  29. data/lib/puppet/face/status.rb +1 -0
  30. data/lib/puppet/file_serving/configuration/parser.rb +6 -13
  31. data/lib/puppet/indirector/exec.rb +3 -3
  32. data/lib/puppet/indirector/face.rb +17 -7
  33. data/lib/puppet/indirector/report/processor.rb +29 -16
  34. data/lib/puppet/indirector/rest.rb +42 -7
  35. data/lib/puppet/indirector/yaml.rb +5 -0
  36. data/lib/puppet/interface.rb +7 -2
  37. data/lib/puppet/interface/action.rb +57 -23
  38. data/lib/puppet/interface/action_manager.rb +10 -5
  39. data/lib/puppet/interface/face_collection.rb +43 -52
  40. data/lib/puppet/interface/option.rb +19 -0
  41. data/lib/puppet/interface/option_builder.rb +13 -0
  42. data/lib/puppet/interface/option_manager.rb +2 -1
  43. data/lib/puppet/metatype/manager.rb +7 -20
  44. data/lib/puppet/module.rb +4 -1
  45. data/lib/puppet/network/authconfig.rb +3 -1
  46. data/lib/puppet/network/authstore.rb +14 -5
  47. data/lib/puppet/network/handler/fileserver.rb +3 -0
  48. data/lib/puppet/network/http/webrick.rb +1 -1
  49. data/lib/puppet/network/rest_authconfig.rb +6 -1
  50. data/lib/puppet/network/rest_authorization.rb +1 -1
  51. data/lib/puppet/parser/compiler.rb +8 -11
  52. data/lib/puppet/parser/functions.rb +1 -6
  53. data/lib/puppet/parser/functions/create_resources.rb +6 -5
  54. data/lib/puppet/parser/functions/regsubst.rb +26 -0
  55. data/lib/puppet/parser/functions/shellquote.rb +26 -0
  56. data/lib/puppet/parser/functions/sprintf.rb +26 -0
  57. data/lib/puppet/parser/grammar.ra +34 -60
  58. data/lib/puppet/parser/lexer.rb +5 -5
  59. data/lib/puppet/parser/parser.rb +913 -1196
  60. data/lib/puppet/parser/resource.rb +18 -1
  61. data/lib/puppet/parser/scope.rb +2 -2
  62. data/lib/puppet/provider/augeas/augeas.rb +42 -17
  63. data/lib/puppet/provider/mount/parsed.rb +19 -1
  64. data/lib/puppet/provider/naginator.rb +9 -1
  65. data/lib/puppet/provider/nameservice/directoryservice.rb +11 -8
  66. data/lib/puppet/provider/network_device.rb +1 -1
  67. data/lib/puppet/provider/package/aptitude.rb +1 -0
  68. data/lib/puppet/provider/package/pacman.rb +94 -0
  69. data/lib/puppet/provider/ssh_authorized_key/parsed.rb +0 -6
  70. data/lib/puppet/rails/host.rb +7 -0
  71. data/lib/puppet/reports/store.rb +15 -0
  72. data/lib/puppet/resource/catalog.rb +15 -6
  73. data/lib/puppet/ssl/certificate.rb +6 -0
  74. data/lib/puppet/ssl/inventory.rb +2 -0
  75. data/lib/puppet/transaction.rb +9 -17
  76. data/lib/puppet/transaction/report.rb +3 -3
  77. data/lib/puppet/type.rb +13 -24
  78. data/lib/puppet/type/file.rb +8 -2
  79. data/lib/puppet/type/file/source.rb +2 -2
  80. data/lib/puppet/type/service.rb +20 -24
  81. data/lib/puppet/type/ssh_authorized_key.rb +12 -0
  82. data/lib/puppet/type/user.rb +8 -0
  83. data/lib/puppet/util.rb +0 -1
  84. data/lib/puppet/util/network_device.rb +3 -3
  85. data/lib/puppet/util/settings.rb +1 -1
  86. data/lib/puppet/util/settings/file_setting.rb +1 -0
  87. data/lib/semver.rb +65 -0
  88. data/spec/integration/defaults_spec.rb +23 -1
  89. data/spec/integration/network/rest_authconfig_spec.rb +145 -0
  90. data/spec/integration/node/facts_spec.rb +1 -1
  91. data/spec/integration/parser/functions_spec.rb +1 -1
  92. data/spec/integration/parser/parser_spec.rb +31 -0
  93. data/spec/integration/provider/ssh_authorized_key_spec.rb +207 -0
  94. data/spec/integration/type_spec.rb +11 -0
  95. data/spec/lib/puppet/face/1.0.0/huzzah.rb +8 -0
  96. data/spec/lib/puppet/face/huzzah.rb +1 -0
  97. data/spec/lib/puppet/face/huzzah/obsolete.rb +6 -0
  98. data/spec/shared_behaviours/things_that_declare_options.rb +115 -3
  99. data/spec/unit/application/agent_spec.rb +2 -2
  100. data/spec/unit/application/apply_spec.rb +74 -56
  101. data/spec/unit/application/cert_spec.rb +10 -0
  102. data/spec/unit/application/device_spec.rb +2 -3
  103. data/spec/unit/application/face_base_spec.rb +1 -0
  104. data/spec/unit/application/facts_spec.rb +1 -0
  105. data/spec/unit/application/inspect_spec.rb +5 -0
  106. data/spec/unit/configurer/fact_handler_spec.rb +45 -37
  107. data/spec/unit/configurer_spec.rb +405 -327
  108. data/spec/unit/face/ca_spec.rb +355 -0
  109. data/spec/unit/face/certificate_spec.rb +16 -4
  110. data/spec/unit/face/node_spec.rb +261 -1
  111. data/spec/unit/file_serving/configuration/parser_spec.rb +8 -0
  112. data/spec/unit/indirector/certificate/rest_spec.rb +1 -0
  113. data/spec/unit/indirector/certificate_status/file_spec.rb +4 -0
  114. data/spec/unit/indirector/exec_spec.rb +4 -4
  115. data/spec/unit/indirector/face_spec.rb +3 -1
  116. data/spec/unit/indirector/facts/couch_spec.rb +2 -2
  117. data/spec/unit/indirector/facts/network_device_spec.rb +2 -6
  118. data/spec/unit/indirector/node/exec_spec.rb +1 -1
  119. data/spec/unit/indirector/report/processor_spec.rb +31 -8
  120. data/spec/unit/indirector/rest_spec.rb +53 -5
  121. data/spec/unit/indirector/yaml_spec.rb +18 -0
  122. data/spec/unit/interface/action_spec.rb +112 -8
  123. data/spec/unit/interface/face_collection_spec.rb +46 -36
  124. data/spec/unit/interface/option_spec.rb +44 -0
  125. data/spec/unit/interface_spec.rb +11 -6
  126. data/spec/unit/module_spec.rb +38 -9
  127. data/spec/unit/network/authconfig_spec.rb +23 -0
  128. data/spec/unit/network/authstore_spec.rb +36 -4
  129. data/spec/unit/network/handler/fileserver_spec.rb +32 -0
  130. data/spec/unit/network/rest_authconfig_spec.rb +1 -1
  131. data/spec/unit/node_spec.rb +1 -0
  132. data/spec/unit/parser/compiler_spec.rb +8 -46
  133. data/spec/unit/parser/lexer_spec.rb +27 -17
  134. data/spec/unit/parser/resource_spec.rb +61 -3
  135. data/spec/unit/parser/scope_spec.rb +5 -1
  136. data/spec/unit/provider/augeas/augeas_spec.rb +106 -1
  137. data/spec/unit/provider/cisco_spec.rb +3 -4
  138. data/spec/unit/provider/interface/cisco_spec.rb +1 -2
  139. data/spec/unit/provider/mount/parsed_spec.rb +41 -0
  140. data/spec/unit/provider/nameservice/directoryservice_spec.rb +60 -0
  141. data/spec/unit/provider/network_device_spec.rb +1 -2
  142. data/spec/unit/provider/package/pacman_spec.rb +237 -0
  143. data/spec/unit/provider/package/pkgutil_spec.rb +2 -3
  144. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +21 -32
  145. data/spec/unit/provider/vlan/cisco_spec.rb +1 -2
  146. data/spec/unit/rails/host_spec.rb +8 -0
  147. data/spec/unit/resource/catalog_spec.rb +55 -8
  148. data/spec/unit/semver_spec.rb +187 -0
  149. data/spec/unit/ssl/certificate_spec.rb +25 -0
  150. data/spec/unit/transaction/report_spec.rb +3 -3
  151. data/spec/unit/transaction_spec.rb +8 -2
  152. data/spec/unit/type/file_spec.rb +57 -0
  153. data/spec/unit/type/interface_spec.rb +1 -2
  154. data/spec/unit/type/schedule_spec.rb +73 -42
  155. data/spec/unit/type/ssh_authorized_key_spec.rb +180 -70
  156. data/spec/unit/type/user_spec.rb +8 -0
  157. data/spec/unit/type/vlan_spec.rb +1 -2
  158. data/spec/unit/type_spec.rb +66 -0
  159. data/spec/unit/util/network_device/cisco/device_spec.rb +1 -2
  160. data/spec/unit/util/network_device/cisco/facts_spec.rb +2 -3
  161. data/spec/unit/util/network_device/cisco/interface_spec.rb +1 -2
  162. data/spec/unit/util/network_device/config_spec.rb +3 -4
  163. data/spec/unit/util/network_device/ipcalc_spec.rb +1 -2
  164. data/spec/unit/util/network_device/transport/base_spec.rb +1 -2
  165. data/spec/unit/util/network_device/transport/ssh_spec.rb +1 -2
  166. data/spec/unit/util/network_device/transport/telnet_spec.rb +1 -2
  167. data/spec/unit/util/network_device_spec.rb +2 -2
  168. data/spec/unit/util/settings/file_setting_spec.rb +4 -0
  169. data/spec/unit/util/settings_spec.rb +11 -0
  170. data/test/lib/puppettest/railstesting.rb +0 -34
  171. metadata +19 -4
@@ -0,0 +1,154 @@
1
+ Puppet::Face.define(:node, '0.0.1') do
2
+ action(:clean) do
3
+ option "--[no-]unexport" do
4
+ summary "Unexport exported resources"
5
+ end
6
+
7
+ summary "Clean up everything a puppetmaster knows about a node"
8
+ arguments "<host1> [<host2> ...]"
9
+ description <<-EOT
10
+ This includes
11
+
12
+ * Signed certificates ($vardir/ssl/ca/signed/node.domain.pem)
13
+ * Cached facts ($vardir/yaml/facts/node.domain.yaml)
14
+ * Cached node stuff ($vardir/yaml/node/node.domain.yaml)
15
+ * Reports ($vardir/reports/node.domain)
16
+ * Stored configs: it can either remove all data from an host in your
17
+ storedconfig database, or with --unexport turn every exported resource
18
+ supporting ensure to absent so that any other host checking out their
19
+ config can remove those exported configurations.
20
+
21
+ This will unexport exported resources of a
22
+ host, so that consumers of these resources can remove the exported
23
+ resources and we will safely remove the node from our
24
+ infrastructure.
25
+ EOT
26
+
27
+ when_invoked do |*args|
28
+ nodes = args[0..-2]
29
+ options = args.last
30
+ raise "At least one node should be passed" if nodes.empty? || nodes == options
31
+
32
+ # TODO: this is a hack and should be removed if faces provide the proper
33
+ # infrastructure to set the run mode.
34
+ require 'puppet/util/run_mode'
35
+ $puppet_application_mode = Puppet::Util::RunMode[:master]
36
+
37
+ if Puppet::SSL::CertificateAuthority.ca?
38
+ Puppet::SSL::Host.ca_location = :local
39
+ else
40
+ Puppet::SSL::Host.ca_location = :none
41
+ end
42
+
43
+ Puppet::Node::Facts.indirection.terminus_class = :yaml
44
+ Puppet::Node::Facts.indirection.cache_class = :yaml
45
+ Puppet::Node.indirection.terminus_class = :yaml
46
+ Puppet::Node.indirection.cache_class = :yaml
47
+
48
+ nodes.each { |node| cleanup(node.downcase, options[:unexport]) }
49
+ end
50
+ end
51
+
52
+ def cleanup(node, unexport)
53
+ clean_cert(node)
54
+ clean_cached_facts(node)
55
+ clean_cached_node(node)
56
+ clean_reports(node)
57
+
58
+ # This is roughly functional, but seems to introduce order-dependent test
59
+ # failures; this can be re-added when those issues are resolved.
60
+ # clean_storeconfigs(node, unexport)
61
+ end
62
+
63
+ # clean signed cert for +host+
64
+ def clean_cert(node)
65
+ if Puppet::SSL::CertificateAuthority.ca?
66
+ Puppet::Face[:ca, :current].revoke(node)
67
+ Puppet::Face[:ca, :current].destroy(node)
68
+ Puppet.info "#{node} certificates removed from ca"
69
+ else
70
+ Puppet.info "Not managing #{node} certs as this host is not a CA"
71
+ end
72
+ end
73
+
74
+ # clean facts for +host+
75
+ def clean_cached_facts(node)
76
+ Puppet::Node::Facts.indirection.destroy(node)
77
+ Puppet.info "#{node}'s facts removed"
78
+ end
79
+
80
+ # clean cached node +host+
81
+ def clean_cached_node(node)
82
+ Puppet::Node.indirection.destroy(node)
83
+ Puppet.info "#{node}'s cached node removed"
84
+ end
85
+
86
+ # clean node reports for +host+
87
+ def clean_reports(node)
88
+ Puppet::Transaction::Report.indirection.destroy(node)
89
+ Puppet.info "#{node}'s reports removed"
90
+ end
91
+
92
+ # clean storeconfig for +node+
93
+ def clean_storeconfigs(node, do_unexport=false)
94
+ return unless Puppet[:storeconfigs] && Puppet.features.rails?
95
+ require 'puppet/rails'
96
+ Puppet::Rails.connect
97
+ unless rails_node = Puppet::Rails::Host.find_by_name(node)
98
+ Puppet.notice "No entries found for #{node} in storedconfigs."
99
+ return
100
+ end
101
+
102
+ if do_unexport
103
+ unexport(rails_node)
104
+ Puppet.notice "Force #{node}'s exported resources to absent"
105
+ Puppet.warning "Please wait until all other hosts have checked out their configuration before finishing the cleanup with:"
106
+ Puppet.warning "$ puppet node clean #{node}"
107
+ else
108
+ rails_node.destroy
109
+ Puppet.notice "#{node} storeconfigs removed"
110
+ end
111
+ end
112
+
113
+ def unexport(node)
114
+ # fetch all exported resource
115
+ query = {:include => {:param_values => :param_name}}
116
+ query[:conditions] = [ "exported=? AND host_id=?", true, node.id ]
117
+ Puppet::Rails::Resource.find(:all, query).each do |resource|
118
+ if type_is_ensurable(resource)
119
+ line = 0
120
+ param_name = Puppet::Rails::ParamName.find_or_create_by_name("ensure")
121
+
122
+ if ensure_param = resource.param_values.find(
123
+ :first,
124
+ :conditions => [ 'param_name_id = ?', param_name.id ]
125
+ )
126
+ line = ensure_param.line.to_i
127
+ Puppet::Rails::ParamValue.delete(ensure_param.id);
128
+ end
129
+
130
+ # force ensure parameter to "absent"
131
+ resource.param_values.create(
132
+ :value => "absent",
133
+ :line => line,
134
+ :param_name => param_name
135
+ )
136
+ Puppet.info("#{resource.name} has been marked as \"absent\"")
137
+ end
138
+ end
139
+ end
140
+
141
+ def environment
142
+ @environment ||= Puppet::Node::Environment.new
143
+ end
144
+
145
+ def type_is_ensurable(resource)
146
+ if (type = Puppet::Type.type(resource.restype)) && type.validattr?(:ensure)
147
+ return true
148
+ else
149
+ type = environment.known_resource_types.find_definition('', resource.restype)
150
+ return true if type && type.arguments.keys.include?('ensure')
151
+ end
152
+ return false
153
+ end
154
+ end
@@ -12,6 +12,7 @@ Puppet::Indirector::Face.define(:status, '0.0.1') do
12
12
  get_action(:search).summary "Invalid for this subcommand."
13
13
 
14
14
  find = get_action(:find)
15
+ find.default = true
15
16
  find.summary "Check status of puppet master server."
16
17
  find.arguments "<dummy_text>"
17
18
  find.returns <<-'EOT'
@@ -24,9 +24,10 @@ class Puppet::FileServing::Configuration::Parser < Puppet::Util::LoadedFile
24
24
  when /^\s*$/; next # skip blank lines
25
25
  when /\[([-\w]+)\]/
26
26
  mount = newmount($1)
27
- when /^\s*(\w+)\s+(.+)$/
27
+ when /^\s*(\w+)\s+(.+?)(\s*#.*)?$/
28
28
  var = $1
29
29
  value = $2
30
+ value.strip!
30
31
  raise(ArgumentError, "Fileserver configuration file does not use '=' as a separator") if value =~ /^=/
31
32
  case var
32
33
  when "path"
@@ -58,12 +59,8 @@ class Puppet::FileServing::Configuration::Parser < Puppet::Util::LoadedFile
58
59
  begin
59
60
  mount.info "allowing #{val} access"
60
61
  mount.allow(val)
61
- rescue AuthStoreError => detail
62
-
63
- raise ArgumentError.new(
64
- detail.to_s,
65
-
66
- @count, file)
62
+ rescue Puppet::AuthStoreError => detail
63
+ raise ArgumentError.new(detail.to_s, @count, file)
67
64
  end
68
65
  }
69
66
  end
@@ -75,12 +72,8 @@ class Puppet::FileServing::Configuration::Parser < Puppet::Util::LoadedFile
75
72
  begin
76
73
  mount.info "denying #{val} access"
77
74
  mount.deny(val)
78
- rescue AuthStoreError => detail
79
-
80
- raise ArgumentError.new(
81
- detail.to_s,
82
-
83
- @count, file)
75
+ rescue Puppet::AuthStoreError => detail
76
+ raise ArgumentError.new(detail.to_s, @count, file)
84
77
  end
85
78
  }
86
79
  end
@@ -16,8 +16,8 @@ class Puppet::Indirector::Exec < Puppet::Indirector::Terminus
16
16
  private
17
17
 
18
18
  # Proxy the execution, so it's easier to test.
19
- def execute(command)
20
- Puppet::Util.execute(command)
19
+ def execute(command, arguments)
20
+ Puppet::Util.execute(command,arguments)
21
21
  end
22
22
 
23
23
  # Call the external command and see if it returns our output.
@@ -33,7 +33,7 @@ class Puppet::Indirector::Exec < Puppet::Indirector::Terminus
33
33
  # Add our name to it.
34
34
  external_command << name
35
35
  begin
36
- output = execute(external_command)
36
+ output = execute(external_command, :combine => false)
37
37
  rescue Puppet::ExecutionFailure => detail
38
38
  raise Puppet::Error, "Failed to find #{name} via exec: #{detail}"
39
39
  end
@@ -48,16 +48,26 @@ class Puppet::Indirector::Face < Puppet::Face
48
48
  return result
49
49
  end
50
50
 
51
+ option "--extra HASH" do
52
+ summary "Extra arguments to pass to the indirection request"
53
+ description <<-end
54
+ A terminus can take additional arguments to refine the operation, which
55
+ are passed as an arbitrary hash to the back-end. Anything passed as
56
+ the extra value is just send direct to the back-end.
57
+ end
58
+ default_to do Hash.new end
59
+ end
60
+
51
61
  action :destroy do
52
62
  summary "Delete an object."
53
63
  arguments "<key>"
54
- when_invoked { |key, options| call_indirection_method(:destroy, key, options) }
64
+ when_invoked {|key, options| call_indirection_method :destroy, key, options[:extra] }
55
65
  end
56
66
 
57
67
  action :find do
58
68
  summary "Retrieve an object by name."
59
69
  arguments "<key>"
60
- when_invoked { |key, options| call_indirection_method(:find, key, options) }
70
+ when_invoked {|key, options| call_indirection_method :find, key, options[:extra] }
61
71
  end
62
72
 
63
73
  action :save do
@@ -68,13 +78,13 @@ class Puppet::Indirector::Face < Puppet::Face
68
78
  currently accept data from STDIN, save actions cannot currently be invoked
69
79
  from the command line.
70
80
  EOT
71
- when_invoked { |key, options| call_indirection_method(:save, key, options) }
81
+ when_invoked {|key, options| call_indirection_method :save, key, options[:extra] }
72
82
  end
73
83
 
74
84
  action :search do
75
85
  summary "Search for an object or retrieve multiple objects."
76
86
  arguments "<query>"
77
- when_invoked { |key, options| call_indirection_method(:search, key, options) }
87
+ when_invoked {|key, options| call_indirection_method :search, key, options[:extra] }
78
88
  end
79
89
 
80
90
  # Print the configuration for the current terminus class
@@ -86,11 +96,11 @@ class Puppet::Indirector::Face < Puppet::Face
86
96
  run mode with the '--mode' option.
87
97
  EOT
88
98
 
89
- when_invoked do |*args|
99
+ when_invoked do |options|
90
100
  if t = indirection.terminus_class
91
- puts "Run mode '#{Puppet.run_mode.name}': #{t}"
101
+ "Run mode '#{Puppet.run_mode.name}': #{t}"
92
102
  else
93
- $stderr.puts "No default terminus class for run mode '#{Puppet.run_mode.name}'"
103
+ "No default terminus class for run mode '#{Puppet.run_mode.name}'"
94
104
  end
95
105
  end
96
106
  end
@@ -14,28 +14,30 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
14
14
  process(request.instance)
15
15
  end
16
16
 
17
+ def destroy(request)
18
+ processors do |mod|
19
+ mod.destroy(request.key) if mod.respond_to?(:destroy)
20
+ end
21
+ end
22
+
17
23
  private
18
24
 
19
25
  # Process the report with each of the configured report types.
20
26
  # LAK:NOTE This isn't necessarily the best design, but it's backward
21
27
  # compatible and that's good enough for now.
22
28
  def process(report)
23
- return if Puppet[:reports] == "none"
24
-
25
- reports.each do |name|
26
- if mod = Puppet::Reports.report(name)
27
- # We have to use a dup because we're including a module in the
28
- # report.
29
- newrep = report.dup
30
- begin
31
- newrep.extend(mod)
32
- newrep.process
33
- rescue => detail
34
- puts detail.backtrace if Puppet[:trace]
35
- Puppet.err "Report #{name} failed: #{detail}"
36
- end
37
- else
38
- Puppet.warning "No report named '#{name}'"
29
+ Puppet.debug "Recieved report to process from #{report.host}"
30
+ processors do |mod|
31
+ Puppet.debug "Processing report from #{report.host} with processor #{mod}"
32
+ # We have to use a dup because we're including a module in the
33
+ # report.
34
+ newrep = report.dup
35
+ begin
36
+ newrep.extend(mod)
37
+ newrep.process
38
+ rescue => detail
39
+ puts detail.backtrace if Puppet[:trace]
40
+ Puppet.err "Report #{name} failed: #{detail}"
39
41
  end
40
42
  end
41
43
  end
@@ -45,4 +47,15 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
45
47
  # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
46
48
  x = Puppet[:reports].gsub(/(^\s+)|(\s+$)/, '').split(/\s*,\s*/)
47
49
  end
50
+
51
+ def processors(&blk)
52
+ return if Puppet[:reports] == "none"
53
+ reports.each do |name|
54
+ if mod = Puppet::Reports.report(name)
55
+ yield(mod)
56
+ else
57
+ Puppet.warning "No report named '#{name}'"
58
+ end
59
+ end
60
+ end
48
61
  end
@@ -71,16 +71,51 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
71
71
  Puppet::Network::HttpPool.http_instance(request.server || self.class.server, request.port || self.class.port)
72
72
  end
73
73
 
74
+ [:get, :post, :head, :delete, :put].each do |method|
75
+ define_method "http_#{method}" do |request, *args|
76
+ http_request(method, request, *args)
77
+ end
78
+ end
79
+
80
+ def http_request(method, request, *args)
81
+ http_connection = network(request)
82
+ peer_certs = []
83
+
84
+ # We add the callback to collect the certificates for use in constructing
85
+ # the error message if the verification failed. This is necessary since we
86
+ # don't have direct access to the cert that we expected the connection to
87
+ # use otherwise.
88
+ #
89
+ http_connection.verify_callback = proc do |preverify_ok, ssl_context|
90
+ peer_certs << Puppet::SSL::Certificate.from_s(ssl_context.current_cert.to_pem)
91
+ preverify_ok
92
+ end
93
+
94
+ http_connection.send(method, *args)
95
+ rescue OpenSSL::SSL::SSLError => error
96
+ if error.message.include? "certificate verify failed"
97
+ raise Puppet::Error, "#{error.message}. This is often because the time is out of sync on the server or client"
98
+ elsif error.message.include? "hostname was not match"
99
+ raise unless cert = peer_certs.find { |c| c.name !~ /^puppet ca/i }
100
+
101
+ valid_certnames = [cert.name, *cert.alternate_names].uniq
102
+ msg = valid_certnames.length > 1 ? "one of #{valid_certnames.join(', ')}" : valid_certnames.first
103
+
104
+ raise Puppet::Error, "Server hostname '#{http_connection.address}' did not match server certificate; expected #{msg}"
105
+ else
106
+ raise
107
+ end
108
+ end
109
+
74
110
  def find(request)
75
111
  uri, body = request_to_uri_and_body(request)
76
112
  uri_with_query_string = "#{uri}?#{body}"
77
- http_connection = network(request)
78
113
  # WEBrick in Ruby 1.9.1 only supports up to 1024 character lines in an HTTP request
79
114
  # http://redmine.ruby-lang.org/issues/show/3991
80
115
  response = if "GET #{uri_with_query_string} HTTP/1.1\r\n".length > 1024
81
- http_connection.post(uri, body, headers)
116
+ http_post(request, uri, body, headers)
82
117
  else
83
- http_connection.get(uri_with_query_string, headers)
118
+ http_get(request, uri_with_query_string, headers)
84
119
  end
85
120
  result = deserialize response
86
121
  result.name = request.key if result.respond_to?(:name=)
@@ -88,7 +123,7 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
88
123
  end
89
124
 
90
125
  def head(request)
91
- response = network(request).head(indirection2uri(request), headers)
126
+ response = http_head(request, indirection2uri(request), headers)
92
127
  case response.code
93
128
  when "404"
94
129
  return false
@@ -101,7 +136,7 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
101
136
  end
102
137
 
103
138
  def search(request)
104
- unless result = deserialize(network(request).get(indirection2uri(request), headers), true)
139
+ unless result = deserialize(http_get(request, indirection2uri(request), headers), true)
105
140
  return []
106
141
  end
107
142
  result
@@ -109,12 +144,12 @@ class Puppet::Indirector::REST < Puppet::Indirector::Terminus
109
144
 
110
145
  def destroy(request)
111
146
  raise ArgumentError, "DELETE does not accept options" unless request.options.empty?
112
- deserialize network(request).delete(indirection2uri(request), headers)
147
+ deserialize http_delete(request, indirection2uri(request), headers)
113
148
  end
114
149
 
115
150
  def save(request)
116
151
  raise ArgumentError, "PUT does not accept options" unless request.options.empty?
117
- deserialize network(request).put(indirection2uri(request), request.instance.render, headers.merge({ "Content-Type" => request.instance.mime }))
152
+ deserialize http_put(request, indirection2uri(request), request.instance.render, headers.merge({ "Content-Type" => request.instance.mime }))
118
153
  end
119
154
 
120
155
  private
@@ -47,6 +47,11 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
47
47
  File.join(base, self.class.indirection_name.to_s, name.to_s + ext)
48
48
  end
49
49
 
50
+ def destroy(request)
51
+ file_path = path(request.key)
52
+ File.unlink(file_path) if File.exists?(file_path)
53
+ end
54
+
50
55
  def search(request)
51
56
  Dir.glob(path(request.key,'')).collect do |file|
52
57
  YAML.load_file(file)
@@ -2,6 +2,7 @@ require 'puppet'
2
2
  require 'puppet/util/autoload'
3
3
  require 'puppet/interface/documentation'
4
4
  require 'prettyprint'
5
+ require 'semver'
5
6
 
6
7
  class Puppet::Interface
7
8
  include FullDocs
@@ -63,6 +64,10 @@ class Puppet::Interface
63
64
  end
64
65
  face
65
66
  end
67
+
68
+ def find_action(name, action, version = :current)
69
+ Puppet::Interface::FaceCollection.get_action_for_face(name, action, version)
70
+ end
66
71
  end
67
72
 
68
73
  def set_default_format(format)
@@ -84,12 +89,12 @@ class Puppet::Interface
84
89
  attr_reader :name, :version
85
90
 
86
91
  def initialize(name, version, &block)
87
- unless Puppet::Interface::FaceCollection.validate_version(version)
92
+ unless SemVer.valid?(version)
88
93
  raise ArgumentError, "Cannot create face #{name.inspect} with invalid version number '#{version}'!"
89
94
  end
90
95
 
91
96
  @name = Puppet::Interface::FaceCollection.underscorize(name)
92
- @version = version
97
+ @version = SemVer.new(version)
93
98
 
94
99
  # The few bits of documentation we actually demand. The default license
95
100
  # is a favour to our end users; if you happen to get that in a core face