runa-chef 0.8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +136 -0
  3. data/bin/chef-client +26 -0
  4. data/bin/chef-solo +26 -0
  5. data/bin/knife +27 -0
  6. data/bin/shef +45 -0
  7. data/distro/README +2 -0
  8. data/distro/common/man/man1/chef-indexer.1 +42 -0
  9. data/distro/common/man/man1/chef-server.1 +108 -0
  10. data/distro/common/man/man8/chef-client.8 +61 -0
  11. data/distro/common/man/man8/chef-solo.8 +58 -0
  12. data/distro/common/man/man8/knife.8 +359 -0
  13. data/distro/debian/etc/init.d/chef-client +175 -0
  14. data/distro/debian/etc/init.d/chef-indexer +175 -0
  15. data/distro/debian/etc/init.d/chef-server +120 -0
  16. data/distro/redhat/etc/init.d/chef-client +78 -0
  17. data/distro/redhat/etc/init.d/chef-indexer +76 -0
  18. data/distro/redhat/etc/init.d/chef-server +78 -0
  19. data/distro/redhat/etc/sysconfig/chef-client +10 -0
  20. data/distro/redhat/etc/sysconfig/chef-indexer +8 -0
  21. data/distro/redhat/etc/sysconfig/chef-server +10 -0
  22. data/distro/suse/etc/init.d/chef-client +121 -0
  23. data/lib/chef.rb +49 -0
  24. data/lib/chef/api_client.rb +269 -0
  25. data/lib/chef/application.rb +98 -0
  26. data/lib/chef/application/agent.rb +18 -0
  27. data/lib/chef/application/client.rb +214 -0
  28. data/lib/chef/application/knife.rb +138 -0
  29. data/lib/chef/application/server.rb +19 -0
  30. data/lib/chef/application/solo.rb +214 -0
  31. data/lib/chef/cache.rb +61 -0
  32. data/lib/chef/cache/checksum.rb +70 -0
  33. data/lib/chef/certificate.rb +154 -0
  34. data/lib/chef/client.rb +323 -0
  35. data/lib/chef/compile.rb +158 -0
  36. data/lib/chef/config.rb +195 -0
  37. data/lib/chef/cookbook.rb +198 -0
  38. data/lib/chef/cookbook/metadata.rb +487 -0
  39. data/lib/chef/cookbook/metadata/version.rb +87 -0
  40. data/lib/chef/cookbook_loader.rb +180 -0
  41. data/lib/chef/couchdb.rb +273 -0
  42. data/lib/chef/daemon.rb +170 -0
  43. data/lib/chef/data_bag.rb +216 -0
  44. data/lib/chef/data_bag_item.rb +227 -0
  45. data/lib/chef/exceptions.rb +39 -0
  46. data/lib/chef/file_cache.rb +205 -0
  47. data/lib/chef/knife.rb +300 -0
  48. data/lib/chef/knife/client_bulk_delete.rb +41 -0
  49. data/lib/chef/knife/client_create.rb +55 -0
  50. data/lib/chef/knife/client_delete.rb +37 -0
  51. data/lib/chef/knife/client_edit.rb +37 -0
  52. data/lib/chef/knife/client_list.rb +40 -0
  53. data/lib/chef/knife/client_reregister.rb +48 -0
  54. data/lib/chef/knife/client_show.rb +42 -0
  55. data/lib/chef/knife/configure.rb +84 -0
  56. data/lib/chef/knife/cookbook_bulk_delete.rb +47 -0
  57. data/lib/chef/knife/cookbook_delete.rb +41 -0
  58. data/lib/chef/knife/cookbook_download.rb +57 -0
  59. data/lib/chef/knife/cookbook_list.rb +41 -0
  60. data/lib/chef/knife/cookbook_metadata.rb +87 -0
  61. data/lib/chef/knife/cookbook_show.rb +75 -0
  62. data/lib/chef/knife/cookbook_upload.rb +173 -0
  63. data/lib/chef/knife/data_bag_create.rb +43 -0
  64. data/lib/chef/knife/data_bag_delete.rb +43 -0
  65. data/lib/chef/knife/data_bag_edit.rb +49 -0
  66. data/lib/chef/knife/data_bag_list.rb +42 -0
  67. data/lib/chef/knife/data_bag_show.rb +40 -0
  68. data/lib/chef/knife/ec2_instance_data.rb +46 -0
  69. data/lib/chef/knife/node_bulk_delete.rb +44 -0
  70. data/lib/chef/knife/node_create.rb +39 -0
  71. data/lib/chef/knife/node_delete.rb +36 -0
  72. data/lib/chef/knife/node_edit.rb +36 -0
  73. data/lib/chef/knife/node_from_file.rb +42 -0
  74. data/lib/chef/knife/node_list.rb +41 -0
  75. data/lib/chef/knife/node_run_list_add.rb +64 -0
  76. data/lib/chef/knife/node_run_list_remove.rb +45 -0
  77. data/lib/chef/knife/node_show.rb +46 -0
  78. data/lib/chef/knife/role_bulk_delete.rb +45 -0
  79. data/lib/chef/knife/role_create.rb +44 -0
  80. data/lib/chef/knife/role_delete.rb +36 -0
  81. data/lib/chef/knife/role_edit.rb +37 -0
  82. data/lib/chef/knife/role_from_file.rb +46 -0
  83. data/lib/chef/knife/role_list.rb +40 -0
  84. data/lib/chef/knife/role_show.rb +43 -0
  85. data/lib/chef/knife/search.rb +94 -0
  86. data/lib/chef/log.rb +39 -0
  87. data/lib/chef/mixin/check_helper.rb +31 -0
  88. data/lib/chef/mixin/checksum.rb +32 -0
  89. data/lib/chef/mixin/command.rb +390 -0
  90. data/lib/chef/mixin/convert_to_class_name.rb +57 -0
  91. data/lib/chef/mixin/create_path.rb +56 -0
  92. data/lib/chef/mixin/deep_merge.rb +33 -0
  93. data/lib/chef/mixin/find_preferred_file.rb +92 -0
  94. data/lib/chef/mixin/from_file.rb +50 -0
  95. data/lib/chef/mixin/generate_url.rb +58 -0
  96. data/lib/chef/mixin/language.rb +107 -0
  97. data/lib/chef/mixin/language_include_attribute.rb +56 -0
  98. data/lib/chef/mixin/language_include_recipe.rb +53 -0
  99. data/lib/chef/mixin/params_validate.rb +197 -0
  100. data/lib/chef/mixin/recipe_definition_dsl_core.rb +79 -0
  101. data/lib/chef/mixin/template.rb +94 -0
  102. data/lib/chef/nanite.rb +100 -0
  103. data/lib/chef/node.rb +463 -0
  104. data/lib/chef/node/attribute.rb +412 -0
  105. data/lib/chef/openid_registration.rb +181 -0
  106. data/lib/chef/platform.rb +268 -0
  107. data/lib/chef/provider.rb +101 -0
  108. data/lib/chef/provider/breakpoint.rb +36 -0
  109. data/lib/chef/provider/cron.rb +184 -0
  110. data/lib/chef/provider/deploy.rb +314 -0
  111. data/lib/chef/provider/deploy/revision.rb +70 -0
  112. data/lib/chef/provider/deploy/timestamped.rb +33 -0
  113. data/lib/chef/provider/directory.rb +72 -0
  114. data/lib/chef/provider/erl_call.rb +72 -0
  115. data/lib/chef/provider/execute.rb +58 -0
  116. data/lib/chef/provider/file.rb +195 -0
  117. data/lib/chef/provider/git.rb +203 -0
  118. data/lib/chef/provider/group.rb +120 -0
  119. data/lib/chef/provider/group/dscl.rb +128 -0
  120. data/lib/chef/provider/group/gpasswd.rb +50 -0
  121. data/lib/chef/provider/group/groupadd.rb +78 -0
  122. data/lib/chef/provider/group/pw.rb +88 -0
  123. data/lib/chef/provider/group/usermod.rb +57 -0
  124. data/lib/chef/provider/http_request.rb +106 -0
  125. data/lib/chef/provider/ifconfig.rb +131 -0
  126. data/lib/chef/provider/link.rb +157 -0
  127. data/lib/chef/provider/mdadm.rb +88 -0
  128. data/lib/chef/provider/mount.rb +117 -0
  129. data/lib/chef/provider/mount/mount.rb +208 -0
  130. data/lib/chef/provider/package.rb +160 -0
  131. data/lib/chef/provider/package/apt.rb +110 -0
  132. data/lib/chef/provider/package/dpkg.rb +109 -0
  133. data/lib/chef/provider/package/easy_install.rb +106 -0
  134. data/lib/chef/provider/package/freebsd.rb +153 -0
  135. data/lib/chef/provider/package/macports.rb +105 -0
  136. data/lib/chef/provider/package/portage.rb +124 -0
  137. data/lib/chef/provider/package/rpm.rb +99 -0
  138. data/lib/chef/provider/package/rubygems.rb +136 -0
  139. data/lib/chef/provider/package/yum-dump.py +125 -0
  140. data/lib/chef/provider/package/yum.rb +175 -0
  141. data/lib/chef/provider/package/zypper.rb +132 -0
  142. data/lib/chef/provider/remote_directory.rb +126 -0
  143. data/lib/chef/provider/remote_file.rb +141 -0
  144. data/lib/chef/provider/route.rb +118 -0
  145. data/lib/chef/provider/ruby_block.rb +33 -0
  146. data/lib/chef/provider/script.rb +42 -0
  147. data/lib/chef/provider/service.rb +135 -0
  148. data/lib/chef/provider/service/debian.rb +64 -0
  149. data/lib/chef/provider/service/freebsd.rb +156 -0
  150. data/lib/chef/provider/service/gentoo.rb +54 -0
  151. data/lib/chef/provider/service/init.rb +71 -0
  152. data/lib/chef/provider/service/redhat.rb +62 -0
  153. data/lib/chef/provider/service/simple.rb +114 -0
  154. data/lib/chef/provider/subversion.rb +156 -0
  155. data/lib/chef/provider/template.rb +175 -0
  156. data/lib/chef/provider/user.rb +170 -0
  157. data/lib/chef/provider/user/dscl.rb +280 -0
  158. data/lib/chef/provider/user/pw.rb +113 -0
  159. data/lib/chef/provider/user/useradd.rb +108 -0
  160. data/lib/chef/recipe.rb +105 -0
  161. data/lib/chef/resource.rb +380 -0
  162. data/lib/chef/resource/apt_package.rb +34 -0
  163. data/lib/chef/resource/bash.rb +33 -0
  164. data/lib/chef/resource/breakpoint.rb +35 -0
  165. data/lib/chef/resource/cron.rb +179 -0
  166. data/lib/chef/resource/csh.rb +33 -0
  167. data/lib/chef/resource/deploy.rb +359 -0
  168. data/lib/chef/resource/deploy_revision.rb +35 -0
  169. data/lib/chef/resource/directory.rb +76 -0
  170. data/lib/chef/resource/dpkg_package.rb +34 -0
  171. data/lib/chef/resource/easy_install_package.rb +41 -0
  172. data/lib/chef/resource/erl_call.rb +83 -0
  173. data/lib/chef/resource/execute.rb +127 -0
  174. data/lib/chef/resource/file.rb +84 -0
  175. data/lib/chef/resource/gem_package.rb +41 -0
  176. data/lib/chef/resource/git.rb +36 -0
  177. data/lib/chef/resource/group.rb +70 -0
  178. data/lib/chef/resource/http_request.rb +52 -0
  179. data/lib/chef/resource/ifconfig.rb +134 -0
  180. data/lib/chef/resource/link.rb +78 -0
  181. data/lib/chef/resource/macports_package.rb +29 -0
  182. data/lib/chef/resource/mdadm.rb +82 -0
  183. data/lib/chef/resource/mount.rb +135 -0
  184. data/lib/chef/resource/package.rb +80 -0
  185. data/lib/chef/resource/perl.rb +33 -0
  186. data/lib/chef/resource/portage_package.rb +33 -0
  187. data/lib/chef/resource/python.rb +33 -0
  188. data/lib/chef/resource/remote_directory.rb +91 -0
  189. data/lib/chef/resource/remote_file.rb +60 -0
  190. data/lib/chef/resource/route.rb +135 -0
  191. data/lib/chef/resource/ruby.rb +33 -0
  192. data/lib/chef/resource/ruby_block.rb +39 -0
  193. data/lib/chef/resource/scm.rb +137 -0
  194. data/lib/chef/resource/script.rb +51 -0
  195. data/lib/chef/resource/service.rb +134 -0
  196. data/lib/chef/resource/subversion.rb +34 -0
  197. data/lib/chef/resource/template.rb +60 -0
  198. data/lib/chef/resource/timestamped_deploy.rb +31 -0
  199. data/lib/chef/resource/user.rb +101 -0
  200. data/lib/chef/resource_collection.rb +212 -0
  201. data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
  202. data/lib/chef/resource_definition.rb +67 -0
  203. data/lib/chef/rest.rb +298 -0
  204. data/lib/chef/role.rb +301 -0
  205. data/lib/chef/run_list.rb +164 -0
  206. data/lib/chef/runner.rb +130 -0
  207. data/lib/chef/search/query.rb +71 -0
  208. data/lib/chef/shef.rb +220 -0
  209. data/lib/chef/shef/ext.rb +297 -0
  210. data/lib/chef/shef/shef_session.rb +175 -0
  211. data/lib/chef/streaming_cookbook_uploader.rb +185 -0
  212. data/lib/chef/tasks/chef_repo.rake +245 -0
  213. data/lib/chef/util/file_edit.rb +125 -0
  214. data/lib/chef/util/fileedit.rb +121 -0
  215. data/lib/chef/webui_user.rb +231 -0
  216. metadata +398 -0
@@ -0,0 +1,124 @@
1
+ # Author:: Daniel DeLeo (<dan@kallistec.com>)
2
+ # Copyright:: Copyright (c) 2009 Daniel DeLeo
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ class Chef
19
+ class ResourceCollection
20
+ class StepableIterator
21
+
22
+ def self.for_collection(new_collection)
23
+ instance = new(new_collection)
24
+ instance
25
+ end
26
+
27
+ attr_accessor :collection
28
+ attr_reader :position
29
+
30
+ def initialize(collection=[])
31
+ @position = 0
32
+ @paused = false
33
+ @collection = collection
34
+ end
35
+
36
+ def size
37
+ collection.size
38
+ end
39
+
40
+ def each(&block)
41
+ reset_iteration(block)
42
+ @iterator_type = :element
43
+ iterate
44
+ end
45
+
46
+ def each_index(&block)
47
+ reset_iteration(block)
48
+ @iterator_type = :index
49
+ iterate
50
+ end
51
+
52
+ def each_with_index(&block)
53
+ reset_iteration(block)
54
+ @iterator_type = :element_with_index
55
+ iterate
56
+ end
57
+
58
+ def paused?
59
+ @paused
60
+ end
61
+
62
+ def pause
63
+ @paused = true
64
+ end
65
+
66
+ def resume
67
+ @paused = false
68
+ iterate
69
+ end
70
+
71
+ def rewind
72
+ @position = 0
73
+ end
74
+
75
+ def skip_back(skips=1)
76
+ @position -= skips
77
+ end
78
+
79
+ def skip_forward(skips=1)
80
+ @position += skips
81
+ end
82
+
83
+ def step
84
+ return nil if @position == size
85
+ call_iterator_block
86
+ @position += 1
87
+ end
88
+
89
+ def iterate_on(iteration_type, &block)
90
+ @iterator_type = iteration_type
91
+ @iterator_block = block
92
+ end
93
+
94
+ private
95
+
96
+ def reset_iteration(iterator_block)
97
+ @iterator_block = iterator_block
98
+ @position = 0
99
+ @paused = false
100
+ end
101
+
102
+ def iterate
103
+ while @position < size && !paused?
104
+ step
105
+ end
106
+ collection
107
+ end
108
+
109
+ def call_iterator_block
110
+ case @iterator_type
111
+ when :element
112
+ @iterator_block.call(collection[@position])
113
+ when :index
114
+ @iterator_block.call(@position)
115
+ when :element_with_index
116
+ @iterator_block.call(collection[@position], @position)
117
+ else
118
+ raise "42error: someone forgot to set @iterator_type, wtf?"
119
+ end
120
+ end
121
+
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,67 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/mixin/from_file'
20
+ require 'chef/mixin/params_validate'
21
+
22
+ class Chef
23
+ class ResourceDefinition
24
+
25
+ include Chef::Mixin::FromFile
26
+ include Chef::Mixin::ParamsValidate
27
+
28
+ attr_accessor :name, :params, :recipe, :node
29
+
30
+ def initialize(node=nil)
31
+ @name = nil
32
+ @params = Hash.new
33
+ @recipe = nil
34
+ @node = node
35
+ end
36
+
37
+ def define(resource_name, prototype_params=nil, &block)
38
+ unless resource_name.kind_of?(Symbol)
39
+ raise ArgumentError, "You must use a symbol when defining a new resource!"
40
+ end
41
+ @name = resource_name
42
+ if prototype_params
43
+ unless prototype_params.kind_of?(Hash)
44
+ raise ArgumentError, "You must pass a hash as the prototype parameters for a definition."
45
+ end
46
+ @params = prototype_params
47
+ end
48
+ if Kernel.block_given?
49
+ @recipe = block
50
+ else
51
+ raise ArgumentError, "You must pass a block to a definition."
52
+ end
53
+ true
54
+ end
55
+
56
+ # When we do the resource definition, we're really just setting new values for
57
+ # the paramaters we prototyped at the top. This method missing is as simple as
58
+ # it gets.
59
+ def method_missing(symbol, *args)
60
+ @params[symbol] = args.length == 1 ? args[0] : args
61
+ end
62
+
63
+ def to_s
64
+ "#{name.to_s}"
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,298 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Thom May (<thom@clearairturbulence.org>)
4
+ # Author:: Nuo Yan (<nuo@opscode.com>)
5
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+
21
+ require 'chef/mixin/params_validate'
22
+ require 'chef/openid_registration'
23
+ require 'net/https'
24
+ require 'uri'
25
+ require 'json'
26
+ require 'tempfile'
27
+ require 'singleton'
28
+ require 'mixlib/authentication/signedheaderauth'
29
+ require 'chef/api_client'
30
+
31
+ include Mixlib::Authentication::SignedHeaderAuth
32
+
33
+ class Chef
34
+ class REST
35
+
36
+ class CookieJar < Hash
37
+ include Singleton
38
+ end
39
+
40
+ attr_accessor :url, :cookies, :client_name, :signing_key, :signing_key_filename, :sign_on_redirect, :sign_request
41
+
42
+ def initialize(url, client_name=Chef::Config[:node_name], signing_key_filename=Chef::Config[:client_key])
43
+ @url = url
44
+ @cookies = CookieJar.instance
45
+ @client_name = client_name
46
+ if signing_key_filename
47
+ @signing_key_filename = signing_key_filename
48
+ @signing_key = load_signing_key(signing_key_filename)
49
+ @sign_request = true
50
+ else
51
+ @signing_key = nil
52
+ @sign_request = false
53
+ end
54
+ @sign_on_redirect = true
55
+ end
56
+
57
+ def load_signing_key(key)
58
+ if File.exists?(key) && File.readable?(key)
59
+ IO.read(key)
60
+ else
61
+ raise Chef::Exceptions::PrivateKeyMissing, "I cannot find #{key}, which you told me to use to sign requests!"
62
+ end
63
+ end
64
+
65
+ # Register the client
66
+ def register(name=Chef::Config[:node_name], destination=Chef::Config[:client_key])
67
+
68
+ if File.exists?(destination)
69
+ raise Chef::Exceptions::CannotWritePrivateKey, "I cannot write your private key to #{destination} - check permissions?" unless File.writable?(destination)
70
+ end
71
+
72
+ nc = Chef::ApiClient.new
73
+ nc.name(name)
74
+ response = nc.save(true, true)
75
+
76
+ Chef::Log.debug("Registration response: #{response.inspect}")
77
+
78
+ raise Chef::Exceptions::CannotWritePrivateKey, "The response from the server did not include a private key!" unless response.has_key?("private_key")
79
+
80
+ begin
81
+ # Write out the private key
82
+ file = File.open(destination, "w")
83
+ file.print(response["private_key"])
84
+ file.close
85
+ rescue
86
+ raise Chef::Exceptions::CannotWritePrivateKey, "I cannot write your private key to #{destination}"
87
+ end
88
+
89
+ true
90
+ end
91
+
92
+ # Send an HTTP GET request to the path
93
+ #
94
+ # === Parameters
95
+ # path:: The path to GET
96
+ # raw:: Whether you want the raw body returned, or JSON inflated. Defaults
97
+ # to JSON inflated.
98
+ def get_rest(path, raw=false, headers={})
99
+ run_request(:GET, create_url(path), headers, false, 10, raw)
100
+ end
101
+
102
+ # Send an HTTP DELETE request to the path
103
+ def delete_rest(path, headers={})
104
+ run_request(:DELETE, create_url(path), headers)
105
+ end
106
+
107
+ # Send an HTTP POST request to the path
108
+ def post_rest(path, json, headers={})
109
+ run_request(:POST, create_url(path), headers, json)
110
+ end
111
+
112
+ # Send an HTTP PUT request to the path
113
+ def put_rest(path, json, headers={})
114
+ run_request(:PUT, create_url(path), headers, json)
115
+ end
116
+
117
+ def create_url(path)
118
+ if path =~ /^(http|https):\/\//
119
+ URI.parse(path)
120
+ else
121
+ URI.parse("#{@url}/#{path}")
122
+ end
123
+ end
124
+
125
+ def sign_request(http_method, private_key, user_id, body = "", host="localhost")
126
+ #body = "" if body == false
127
+ timestamp = Time.now.utc.iso8601
128
+ sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object(
129
+ :http_method=>http_method,
130
+ :body=>body,
131
+ :user_id=>user_id,
132
+ :timestamp=>timestamp)
133
+ signed = sign_obj.sign(private_key).merge({:host => host})
134
+ signed.inject({}){|memo, kv| memo["#{kv[0].to_s.upcase}"] = kv[1];memo}
135
+ end
136
+
137
+ # Actually run an HTTP request. First argument is the HTTP method,
138
+ # which should be one of :GET, :PUT, :POST or :DELETE. Next is the
139
+ # URL, then an object to include in the body (which will be converted with
140
+ # .to_json) and finally, the limit of HTTP Redirects to follow (10).
141
+ #
142
+ # Typically, you won't use this method -- instead, you'll use one of
143
+ # the helper methods (get_rest, post_rest, etc.)
144
+ #
145
+ # Will return the body of the response on success.
146
+ def run_request(method, url, headers={}, data=false, limit=10, raw=false)
147
+
148
+ http_retry_delay = Chef::Config[:http_retry_delay]
149
+ http_retry_count = Chef::Config[:http_retry_count]
150
+
151
+ raise ArgumentError, 'HTTP redirect too deep' if limit == 0
152
+
153
+ http = Net::HTTP.new(url.host, url.port)
154
+ if url.scheme == "https"
155
+ http.use_ssl = true
156
+ if Chef::Config[:ssl_verify_mode] == :verify_none
157
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
158
+ elsif Chef::Config[:ssl_verify_mode] == :verify_peer
159
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
160
+ end
161
+ if Chef::Config[:ssl_ca_path] and File.exists?(Chef::Config[:ssl_ca_path])
162
+ http.ca_path = Chef::Config[:ssl_ca_path]
163
+ elsif Chef::Config[:ssl_ca_file] and File.exists?(Chef::Config[:ssl_ca_file])
164
+ http.ca_file = Chef::Config[:ssl_ca_file]
165
+ end
166
+ if Chef::Config[:ssl_client_cert] && File.exists?(Chef::Config[:ssl_client_cert])
167
+ http.cert = OpenSSL::X509::Certificate.new(File.read(Chef::Config[:ssl_client_cert]))
168
+ http.key = OpenSSL::PKey::RSA.new(File.read(Chef::Config[:ssl_client_key]))
169
+ end
170
+ end
171
+
172
+ http.read_timeout = Chef::Config[:rest_timeout]
173
+
174
+ unless raw
175
+ headers = headers.merge({
176
+ 'Accept' => "application/json",
177
+ })
178
+ end
179
+
180
+ if @cookies.has_key?("#{url.host}:#{url.port}")
181
+ headers['Cookie'] = @cookies["#{url.host}:#{url.port}"]
182
+ end
183
+
184
+ json_body = data ? data.to_json : nil
185
+
186
+ if @sign_request
187
+ Chef::Log.debug("Signing the request as #{@client_name}")
188
+ if json_body
189
+ headers.merge!(sign_request(method, OpenSSL::PKey::RSA.new(@signing_key), @client_name, json_body, "#{url.host}:#{url.port}"))
190
+ else
191
+ headers.merge!(sign_request(method, OpenSSL::PKey::RSA.new(@signing_key), @client_name, "", "#{url.host}:#{url.port}"))
192
+ end
193
+ end
194
+
195
+ req = nil
196
+ case method
197
+ when :GET
198
+ req_path = "#{url.path}"
199
+ req_path << "?#{url.query}" if url.query
200
+ req = Net::HTTP::Get.new(req_path, headers)
201
+ when :POST
202
+ headers["Content-Type"] = 'application/json' if data
203
+ req_path = "#{url.path}"
204
+ req_path << "?#{url.query}" if url.query
205
+ req = Net::HTTP::Post.new(req_path, headers)
206
+ req.body = json_body if json_body
207
+ when :PUT
208
+ headers["Content-Type"] = 'application/json' if data
209
+ req_path = "#{url.path}"
210
+ req_path << "?#{url.query}" if url.query
211
+ req = Net::HTTP::Put.new(req_path, headers)
212
+ req.body = json_body if json_body
213
+ when :DELETE
214
+ req_path = "#{url.path}"
215
+ req_path << "?#{url.query}" if url.query
216
+ req = Net::HTTP::Delete.new(req_path, headers)
217
+ else
218
+ raise ArgumentError, "You must provide :GET, :PUT, :POST or :DELETE as the method"
219
+ end
220
+
221
+ Chef::Log.debug("Sending HTTP Request via #{req.method} to #{url.host}:#{url.port}#{req.path}")
222
+
223
+ # Optionally handle HTTP Basic Authentication
224
+ req.basic_auth(url.user, url.password) if url.user
225
+
226
+ res = nil
227
+ tf = nil
228
+ http_retries = 1
229
+
230
+ begin
231
+ res = http.request(req) do |response|
232
+ if raw
233
+ tf = Tempfile.new("chef-rest")
234
+ # Stolen from http://www.ruby-forum.com/topic/166423
235
+ # Kudos to _why!
236
+ size, total = 0, response.header['Content-Length'].to_i
237
+ response.read_body do |chunk|
238
+ tf.write(chunk)
239
+ size += chunk.size
240
+ if size == 0
241
+ Chef::Log.debug("#{req.path} done (0 length file)")
242
+ elsif total == 0
243
+ Chef::Log.debug("#{req.path} (zero content length)")
244
+ else
245
+ Chef::Log.debug("#{req.path}" + " %d%% done (%d of %d)" % [(size * 100) / total, size, total])
246
+ end
247
+ end
248
+ tf.close
249
+ tf
250
+ else
251
+ response.read_body
252
+ end
253
+ response
254
+ end
255
+
256
+ rescue Errno::ECONNREFUSED => e
257
+ Chef::Log.error("Connection refused connecting to #{url.host}:#{url.port} for #{req.path} #{http_retries}/#{http_retry_count}")
258
+ sleep(http_retry_delay)
259
+ retry if (http_retries += 1) < http_retry_count
260
+ raise Errno::ECONNREFUSED, "Connection refused connecting to #{url.host}:#{url.port} for #{req.path}, giving up"
261
+ rescue Timeout::Error
262
+ Chef::Log.error("Timeout connecting to #{url.host}:#{url.port} for #{req.path}, retry #{http_retries}/#{http_retry_count}")
263
+ sleep(http_retry_delay)
264
+ retry if (http_retries += 1) < http_retry_count
265
+ raise Timeout::Error, "Timeout connecting to #{url.host}:#{url.port} for #{req.path}, giving up"
266
+ end
267
+
268
+ if res.kind_of?(Net::HTTPSuccess)
269
+ if res['set-cookie']
270
+ @cookies["#{url.host}:#{url.port}"] = res['set-cookie']
271
+ end
272
+ if res['content-type'] =~ /json/
273
+ response_body = res.body.chomp
274
+ JSON.parse(response_body)
275
+ else
276
+ if raw
277
+ tf
278
+ else
279
+ res.body
280
+ end
281
+ end
282
+ elsif res.kind_of?(Net::HTTPFound) or res.kind_of?(Net::HTTPMovedPermanently)
283
+ if res['set-cookie']
284
+ @cookies["#{url.host}:#{url.port}"] = res['set-cookie']
285
+ end
286
+ @sign_request = false if @sign_on_redirect == false
287
+ run_request(:GET, create_url(res['location']), {}, false, limit - 1, raw)
288
+ else
289
+ if res['content-type'] =~ /json/
290
+ exception = JSON.parse(res.body)
291
+ Chef::Log.warn("HTTP Request Returned #{res.code} #{res.message}: #{exception["error"].respond_to?(:join) ? exception["error"].join(", ") : exception["error"]}")
292
+ end
293
+ res.error!
294
+ end
295
+ end
296
+
297
+ end
298
+ end