chef 0.9.8 → 0.9.10.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/distro/common/man/man8/knife.8 +89 -79
- data/distro/common/markdown/knife.mkd +7 -0
- data/distro/debian/etc/default/chef-server +3 -0
- data/distro/debian/etc/default/chef-server-webui +3 -0
- data/distro/debian/etc/default/chef-solr +3 -0
- data/distro/debian/etc/default/chef-solr-indexer +3 -0
- data/distro/debian/etc/init.d/chef-server +3 -1
- data/distro/debian/etc/init.d/chef-server-webui +3 -1
- data/distro/redhat/etc/init.d/chef-client +1 -1
- data/lib/chef/application.rb +2 -0
- data/lib/chef/application/client.rb +5 -3
- data/lib/chef/application/knife.rb +16 -5
- data/lib/chef/application/solo.rb +0 -1
- data/lib/chef/checksum.rb +65 -1
- data/lib/chef/checksum_cache.rb +173 -0
- data/lib/chef/client.rb +84 -121
- data/lib/chef/cookbook/remote_file_vendor.rb +10 -3
- data/lib/chef/cookbook/syntax_check.rb +2 -2
- data/lib/chef/cookbook_loader.rb +2 -0
- data/lib/chef/cookbook_site_streaming_uploader.rb +29 -0
- data/lib/chef/cookbook_uploader.rb +8 -7
- data/lib/chef/cookbook_version.rb +155 -114
- data/lib/chef/exceptions.rb +5 -0
- data/lib/chef/handler.rb +43 -0
- data/lib/chef/index_queue/consumer.rb +1 -1
- data/lib/chef/index_queue/indexable.rb +1 -1
- data/lib/chef/knife.rb +18 -5
- data/lib/chef/knife/bootstrap.rb +2 -2
- data/lib/chef/knife/bootstrap/archlinux-gems.erb +44 -0
- data/lib/chef/knife/bootstrap/client-install.vbs +80 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
- data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -7
- data/lib/chef/knife/bootstrap/windows-gems.erb +34 -0
- data/lib/chef/knife/configure_client.rb +4 -2
- data/lib/chef/knife/cookbook_metadata.rb +1 -1
- data/lib/chef/knife/cookbook_site_share.rb +2 -1
- data/lib/chef/knife/cookbook_site_vendor.rb +6 -0
- data/lib/chef/knife/cookbook_test.rb +1 -1
- data/lib/chef/knife/ec2_server_create.rb +51 -26
- data/lib/chef/knife/exec.rb +52 -0
- data/lib/chef/knife/ssh.rb +27 -15
- data/lib/chef/knife/status.rb +27 -10
- data/lib/chef/knife/windows_bootstrap.rb +154 -0
- data/lib/chef/mixin/checksum.rb +2 -2
- data/lib/chef/mixin/xml_escape.rb +75 -49
- data/lib/chef/node.rb +54 -58
- data/lib/chef/node/attribute.rb +61 -53
- data/lib/chef/platform.rb +19 -2
- data/lib/chef/provider/breakpoint.rb +1 -1
- data/lib/chef/provider/cookbook_file.rb +3 -3
- data/lib/chef/provider/cron.rb +3 -3
- data/lib/chef/provider/cron/solaris.rb +195 -0
- data/lib/chef/provider/deploy.rb +3 -3
- data/lib/chef/provider/directory.rb +2 -2
- data/lib/chef/provider/env.rb +5 -5
- data/lib/chef/provider/execute.rb +1 -1
- data/lib/chef/provider/file.rb +10 -9
- data/lib/chef/provider/git.rb +12 -4
- data/lib/chef/provider/group.rb +5 -5
- data/lib/chef/provider/http_request.rb +25 -9
- data/lib/chef/provider/ifconfig.rb +2 -2
- data/lib/chef/provider/link.rb +11 -6
- data/lib/chef/provider/log.rb +1 -0
- data/lib/chef/provider/mdadm.rb +3 -3
- data/lib/chef/provider/mount.rb +5 -5
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/ohai.rb +41 -0
- data/lib/chef/provider/package.rb +5 -5
- data/lib/chef/provider/package/yum-dump.py +5 -2
- data/lib/chef/provider/remote_directory.rb +11 -5
- data/lib/chef/provider/remote_file.rb +2 -2
- data/lib/chef/provider/route.rb +154 -133
- data/lib/chef/provider/ruby_block.rb +1 -1
- data/lib/chef/provider/service.rb +6 -6
- data/lib/chef/provider/subversion.rb +12 -9
- data/lib/chef/provider/template.rb +2 -2
- data/lib/chef/provider/user.rb +7 -7
- data/lib/chef/provider/user/useradd.rb +15 -1
- data/lib/chef/providers.rb +2 -0
- data/lib/chef/resource.rb +164 -58
- data/lib/chef/resource/http_request.rb +9 -0
- data/lib/chef/resource/ohai.rb +40 -0
- data/lib/chef/resource/remote_directory.rb +10 -1
- data/lib/chef/resource/rpm_package.rb +34 -0
- data/lib/chef/resource_collection.rb +3 -2
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/rest.rb +13 -7
- data/lib/chef/rest/auth_credentials.rb +1 -1
- data/lib/chef/rest/rest_request.rb +3 -1
- data/lib/chef/runner.rb +31 -55
- data/lib/chef/shef/shef_session.rb +1 -1
- data/lib/chef/util/windows/net_use.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/webui_user.rb +0 -1
- metadata +38 -19
- data/lib/chef/cache.rb +0 -61
- data/lib/chef/cache/checksum.rb +0 -91
data/lib/chef/client.rb
CHANGED
@@ -40,6 +40,73 @@ class Chef
|
|
40
40
|
# The main object in a Chef run. Preps a Chef::Node and Chef::RunContext,
|
41
41
|
# syncs cookbooks if necessary, and triggers convergence.
|
42
42
|
class Client
|
43
|
+
|
44
|
+
# Clears all notifications for client run status events.
|
45
|
+
# Primarily for testing purposes.
|
46
|
+
def self.clear_notifications
|
47
|
+
@run_start_notifications = nil
|
48
|
+
@run_completed_successfully_notifications = nil
|
49
|
+
@run_failed_notifications = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# The list of notifications to be run when the client run starts.
|
53
|
+
def self.run_start_notifications
|
54
|
+
@run_start_notifications ||= []
|
55
|
+
end
|
56
|
+
|
57
|
+
# The list of notifications to be run when the client run completes
|
58
|
+
# successfully.
|
59
|
+
def self.run_completed_successfully_notifications
|
60
|
+
@run_completed_successfully_notifications ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
# The list of notifications to be run when the client run fails.
|
64
|
+
def self.run_failed_notifications
|
65
|
+
@run_failed_notifications ||= []
|
66
|
+
end
|
67
|
+
|
68
|
+
# Add a notification for the 'client run started' event. The notification
|
69
|
+
# is provided as a block. The current Chef::RunStatus object will be passed
|
70
|
+
# to the notification_block when the event is triggered.
|
71
|
+
def self.when_run_starts(¬ification_block)
|
72
|
+
run_start_notifications << notification_block
|
73
|
+
end
|
74
|
+
|
75
|
+
# Add a notification for the 'client run success' event. The notification
|
76
|
+
# is provided as a block. The current Chef::RunStatus object will be passed
|
77
|
+
# to the notification_block when the event is triggered.
|
78
|
+
def self.when_run_completes_successfully(¬ification_block)
|
79
|
+
run_completed_successfully_notifications << notification_block
|
80
|
+
end
|
81
|
+
|
82
|
+
# Add a notification for the 'client run failed' event. The notification
|
83
|
+
# is provided as a block. The current Chef::RunStatus is passed to the
|
84
|
+
# notification_block when the event is triggered.
|
85
|
+
def self.when_run_fails(¬ification_block)
|
86
|
+
run_failed_notifications << notification_block
|
87
|
+
end
|
88
|
+
|
89
|
+
# Callback to fire notifications that the Chef run is starting
|
90
|
+
def run_started
|
91
|
+
self.class.run_start_notifications.each do |notification|
|
92
|
+
notification.call(run_status)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Callback to fire notifications that the run completed successfully
|
97
|
+
def run_completed_successfully
|
98
|
+
self.class.run_completed_successfully_notifications.each do |notification|
|
99
|
+
notification.call(run_status)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Callback to fire notifications that the Chef run failed
|
104
|
+
def run_failed
|
105
|
+
self.class.run_failed_notifications.each do |notification|
|
106
|
+
notification.call(run_status)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
43
110
|
attr_accessor :node
|
44
111
|
attr_accessor :ohai
|
45
112
|
attr_accessor :rest
|
@@ -49,10 +116,13 @@ class Chef
|
|
49
116
|
# TODO: timh/cw: 5-19-2010: json_attribs should be moved to RunContext?
|
50
117
|
attr_reader :json_attribs
|
51
118
|
|
119
|
+
attr_reader :run_status
|
120
|
+
|
52
121
|
# Creates a new Chef::Client.
|
53
122
|
def initialize(json_attribs=nil)
|
54
123
|
@json_attribs = json_attribs
|
55
124
|
@node = nil
|
125
|
+
@run_status = nil
|
56
126
|
@runner = nil
|
57
127
|
@ohai = Ohai::System.new
|
58
128
|
end
|
@@ -75,9 +145,10 @@ class Chef
|
|
75
145
|
build_node
|
76
146
|
|
77
147
|
begin
|
78
|
-
|
148
|
+
|
79
149
|
run_status.start_clock
|
80
150
|
Chef::Log.info("Starting Chef Run (Version #{Chef::VERSION})")
|
151
|
+
run_started
|
81
152
|
|
82
153
|
if Chef::Config[:solo]
|
83
154
|
Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) }
|
@@ -86,18 +157,12 @@ class Chef
|
|
86
157
|
assert_cookbook_path_not_empty(run_context)
|
87
158
|
converge(run_context)
|
88
159
|
else
|
89
|
-
# Keep track of the filenames that we use in both eager cookbook
|
90
|
-
# downloading (during sync_cookbooks) and lazy (during the run
|
91
|
-
# itself, through FileVendor). After the run is over, clean up the
|
92
|
-
# cache.
|
93
|
-
valid_cache_entries = Hash.new
|
94
|
-
|
95
160
|
# Sync_cookbooks eagerly loads all files except files and templates.
|
96
161
|
# It returns the cookbook_hash -- the return result from
|
97
162
|
# /nodes/#{nodename}/cookbooks -- which we will use for our
|
98
163
|
# run_context.
|
99
|
-
Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, rest
|
100
|
-
cookbook_hash = sync_cookbooks
|
164
|
+
Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, rest) }
|
165
|
+
cookbook_hash = sync_cookbooks
|
101
166
|
run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(cookbook_hash))
|
102
167
|
run_status.run_context = run_context
|
103
168
|
|
@@ -106,41 +171,23 @@ class Chef
|
|
106
171
|
converge(run_context)
|
107
172
|
Chef::Log.debug("Saving the current state of node #{node_name}")
|
108
173
|
@node.save
|
109
|
-
|
110
|
-
cleanup_file_cache(valid_cache_entries)
|
111
174
|
end
|
112
175
|
|
113
176
|
run_status.stop_clock
|
114
177
|
Chef::Log.info("Chef Run complete in #{run_status.elapsed_time} seconds")
|
115
|
-
|
178
|
+
run_completed_successfully
|
116
179
|
true
|
117
180
|
rescue Exception => e
|
118
181
|
run_status.stop_clock
|
119
182
|
run_status.exception = e
|
120
|
-
|
121
|
-
Chef::Log.
|
183
|
+
run_failed
|
184
|
+
Chef::Log.debug("Re-raising exception: #{e.class} - #{e.message}\n#{e.backtrace.join("\n ")}")
|
122
185
|
raise
|
123
186
|
ensure
|
124
187
|
run_status = nil
|
125
188
|
end
|
126
189
|
end
|
127
190
|
|
128
|
-
def run_report_handlers(run_status)
|
129
|
-
Chef::Log.info("Running report handlers")
|
130
|
-
Array(Chef::Config[:report_handlers]).each do |handler|
|
131
|
-
handler.run_report_safely(run_status)
|
132
|
-
end
|
133
|
-
Chef::Log.info("Report handlers complete")
|
134
|
-
end
|
135
|
-
|
136
|
-
def run_exception_handlers(run_status)
|
137
|
-
Chef::Log.error("Running exception handlers")
|
138
|
-
Array(Chef::Config[:exception_handlers]).each do |handler|
|
139
|
-
handler.run_report_safely(run_status)
|
140
|
-
end
|
141
|
-
Chef::Log.error("Exception handlers complete")
|
142
|
-
end
|
143
|
-
|
144
191
|
def run_ohai
|
145
192
|
ohai.all_plugins
|
146
193
|
end
|
@@ -171,10 +218,13 @@ class Chef
|
|
171
218
|
@node = Chef::Node.find_or_create(node_name)
|
172
219
|
end
|
173
220
|
|
174
|
-
|
221
|
+
|
222
|
+
@node.consume_external_attrs(ohai.data, @json_attribs)
|
175
223
|
@node.save unless Chef::Config[:solo]
|
176
224
|
@node.reset_defaults_and_overrides
|
177
225
|
|
226
|
+
@run_status = Chef::RunStatus.new(@node)
|
227
|
+
|
178
228
|
@node
|
179
229
|
end
|
180
230
|
|
@@ -196,25 +246,10 @@ class Chef
|
|
196
246
|
#
|
197
247
|
# === Returns
|
198
248
|
# true:: Always returns true
|
199
|
-
def sync_cookbooks
|
249
|
+
def sync_cookbooks
|
200
250
|
Chef::Log.debug("Synchronizing cookbooks")
|
201
251
|
cookbook_hash = rest.get_rest("nodes/#{node_name}/cookbooks")
|
202
|
-
Chef::
|
203
|
-
|
204
|
-
# Remove all cookbooks no longer relevant to this node
|
205
|
-
Chef::FileCache.find(File.join(%w{cookbooks ** *})).each do |cache_file|
|
206
|
-
cache_file =~ /^cookbooks\/([^\/]+)\//
|
207
|
-
unless cookbook_hash.has_key?($1)
|
208
|
-
Chef::Log.info("Removing #{cache_file} from the cache; its cookbook is no longer needed on this client.")
|
209
|
-
Chef::FileCache.delete(cache_file)
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
# Synchronize each of the node's cookbooks, and add to the
|
214
|
-
# valid_cache_entries hash.
|
215
|
-
cookbook_hash.values.each do |cookbook|
|
216
|
-
sync_cookbook_file_cache(cookbook, valid_cache_entries)
|
217
|
-
end
|
252
|
+
Chef::CookbookVersion.sync_cookbooks(cookbook_hash)
|
218
253
|
|
219
254
|
# register the file cache path in the cookbook path so that CookbookLoader actually picks up the synced cookbooks
|
220
255
|
Chef::Config[:cookbook_path] = File.join(Chef::Config[:file_cache_path], "cookbooks")
|
@@ -222,78 +257,6 @@ class Chef
|
|
222
257
|
cookbook_hash
|
223
258
|
end
|
224
259
|
|
225
|
-
# Update the file caches for a given cache segment. Takes a segment name
|
226
|
-
# and a hash that matches one of the cookbooks/_attribute_files style
|
227
|
-
# remote file listings.
|
228
|
-
#
|
229
|
-
# === Parameters
|
230
|
-
# cookbook<Chef::Cookbook>:: The cookbook to update
|
231
|
-
# valid_cache_entries<Hash>:: Out-param; Added to this hash are the files that
|
232
|
-
# were referred to by this cookbook
|
233
|
-
def sync_cookbook_file_cache(cookbook, valid_cache_entries)
|
234
|
-
Chef::Log.debug("Synchronizing cookbook #{cookbook.name}")
|
235
|
-
|
236
|
-
# files and templates are lazily loaded, and will be done later.
|
237
|
-
eager_segments = Chef::CookbookVersion::COOKBOOK_SEGMENTS.dup
|
238
|
-
eager_segments.delete(:files)
|
239
|
-
eager_segments.delete(:templates)
|
240
|
-
|
241
|
-
eager_segments.each do |segment|
|
242
|
-
segment_filenames = Array.new
|
243
|
-
cookbook.manifest[segment].each do |manifest_record|
|
244
|
-
# segment = cookbook segment
|
245
|
-
# remote_list = list of file hashes
|
246
|
-
#
|
247
|
-
# We need the list of known good attribute files, so we can delete any that are
|
248
|
-
# just laying about.
|
249
|
-
|
250
|
-
cache_filename = File.join("cookbooks", cookbook.name, manifest_record['path'])
|
251
|
-
valid_cache_entries[cache_filename] = true
|
252
|
-
|
253
|
-
current_checksum = nil
|
254
|
-
if Chef::FileCache.has_key?(cache_filename)
|
255
|
-
current_checksum = Chef::CookbookVersion.checksum_cookbook_file(Chef::FileCache.load(cache_filename, false))
|
256
|
-
end
|
257
|
-
|
258
|
-
# If the checksums are different between on-disk (current) and on-server
|
259
|
-
# (remote, per manifest), do the update. This will also execute if there
|
260
|
-
# is no current checksum.
|
261
|
-
if current_checksum != manifest_record['checksum']
|
262
|
-
raw_file = rest.get_rest(manifest_record[:url], true)
|
263
|
-
|
264
|
-
Chef::Log.info("Storing updated #{cache_filename} in the cache.")
|
265
|
-
Chef::FileCache.move_to(raw_file.path, cache_filename)
|
266
|
-
else
|
267
|
-
Chef::Log.debug("Not storing #{cache_filename}, as the cache is up to date.")
|
268
|
-
end
|
269
|
-
|
270
|
-
# make the segment filenames a full path.
|
271
|
-
full_path_cache_filename = Chef::FileCache.load(cache_filename, false)
|
272
|
-
segment_filenames << full_path_cache_filename
|
273
|
-
end
|
274
|
-
|
275
|
-
# replace segment filenames with a full-path one.
|
276
|
-
if segment.to_sym == :recipes
|
277
|
-
cookbook.recipe_filenames = segment_filenames
|
278
|
-
elsif segment.to_sym == :attributes
|
279
|
-
cookbook.attribute_filenames = segment_filenames
|
280
|
-
else
|
281
|
-
cookbook.segment_filenames(segment).replace(segment_filenames)
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def cleanup_file_cache(valid_cache_entries)
|
287
|
-
# Delete each file in the cache that we didn't encounter in the
|
288
|
-
# manifest.
|
289
|
-
Chef::FileCache.find(File.join(%w{cookbooks ** *})).each do |cache_filename|
|
290
|
-
unless valid_cache_entries[cache_filename]
|
291
|
-
Chef::Log.info("Removing #{cache_filename} from the cache; it is no longer on the server.")
|
292
|
-
Chef::FileCache.delete(cache_filename)
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
260
|
# Converges the node.
|
298
261
|
#
|
299
262
|
# === Returns
|
@@ -325,7 +288,7 @@ class Chef
|
|
325
288
|
if directory_not_empty?(cookbook_path)
|
326
289
|
break
|
327
290
|
else
|
328
|
-
msg = "No cookbook found in #{Chef::Config[:cookbook_path].inspect}, make sure
|
291
|
+
msg = "No cookbook found in #{Chef::Config[:cookbook_path].inspect}, make sure cookbook_path is set correctly."
|
329
292
|
Chef::Log.fatal(msg)
|
330
293
|
raise Chef::Exceptions::CookbookNotFound, msg if is_last_element?(index, Chef::Config[:cookbook_path])
|
331
294
|
end
|
@@ -25,11 +25,10 @@ class Chef
|
|
25
25
|
# if not available, loading them from the remote server.
|
26
26
|
class RemoteFileVendor < FileVendor
|
27
27
|
|
28
|
-
def initialize(manifest, rest
|
28
|
+
def initialize(manifest, rest)
|
29
29
|
@manifest = manifest
|
30
30
|
@cookbook_name = @manifest[:cookbook_name]
|
31
31
|
@rest = rest
|
32
|
-
@valid_cache_entries = valid_cache_entries
|
33
32
|
end
|
34
33
|
|
35
34
|
# Implements abstract base's requirement. It looks in the
|
@@ -50,7 +49,7 @@ class Chef
|
|
50
49
|
|
51
50
|
# update valid_cache_entries so the upstream cache cleaner knows what
|
52
51
|
# we've used.
|
53
|
-
|
52
|
+
validate_cached_copy(cache_filename)
|
54
53
|
|
55
54
|
current_checksum = nil
|
56
55
|
if Chef::FileCache.has_key?(cache_filename)
|
@@ -74,6 +73,14 @@ class Chef
|
|
74
73
|
# return the filename, not the contents (second argument= false)
|
75
74
|
full_path_cache_filename
|
76
75
|
end
|
76
|
+
|
77
|
+
def validate_cached_copy(cache_filename)
|
78
|
+
valid_cache_entries[cache_filename] = true
|
79
|
+
end
|
80
|
+
|
81
|
+
def valid_cache_entries
|
82
|
+
Chef::CookbookVersion.valid_cache_entries
|
83
|
+
end
|
77
84
|
|
78
85
|
end
|
79
86
|
end
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require 'chef/
|
19
|
+
require 'chef/checksum_cache'
|
20
20
|
require 'chef/mixin/shell_out'
|
21
21
|
|
22
22
|
class Chef
|
@@ -47,7 +47,7 @@ class Chef
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def cache
|
50
|
-
Chef::
|
50
|
+
Chef::ChecksumCache.instance
|
51
51
|
end
|
52
52
|
|
53
53
|
def ruby_files
|
data/lib/chef/cookbook_loader.rb
CHANGED
@@ -101,6 +101,7 @@ class Chef
|
|
101
101
|
cookbook,
|
102
102
|
cookbook_settings[cookbook_name][:root_filenames]
|
103
103
|
)
|
104
|
+
cookbook_settings[cookbook_name][:root_dir] = cookbook
|
104
105
|
if File.exists?(File.join(cookbook, "metadata.json"))
|
105
106
|
cookbook_settings[cookbook_name][:metadata_filenames] << File.join(cookbook, "metadata.json")
|
106
107
|
end
|
@@ -119,6 +120,7 @@ class Chef
|
|
119
120
|
|
120
121
|
cookbook_settings.each_key do |cookbook|
|
121
122
|
@cookbooks_by_name[cookbook] = Chef::CookbookVersion.new(cookbook)
|
123
|
+
@cookbooks_by_name[cookbook].root_dir = cookbook_settings[cookbook][:root_dir]
|
122
124
|
@cookbooks_by_name[cookbook].attribute_filenames = cookbook_settings[cookbook][:attribute_filenames].values
|
123
125
|
@cookbooks_by_name[cookbook].definition_filenames = cookbook_settings[cookbook][:definition_filenames].values
|
124
126
|
@cookbooks_by_name[cookbook].recipe_filenames = cookbook_settings[cookbook][:recipe_filenames].values
|
@@ -34,6 +34,35 @@ class Chef
|
|
34
34
|
|
35
35
|
class << self
|
36
36
|
|
37
|
+
def create_build_dir(cookbook)
|
38
|
+
tmp_cookbook_path = Tempfile.new("chef-#{cookbook.name}-build")
|
39
|
+
tmp_cookbook_path.close
|
40
|
+
tmp_cookbook_dir = tmp_cookbook_path.path
|
41
|
+
File.unlink(tmp_cookbook_dir)
|
42
|
+
FileUtils.mkdir_p(tmp_cookbook_dir)
|
43
|
+
Chef::Log.debug("Staging at #{tmp_cookbook_dir}")
|
44
|
+
checksums_to_on_disk_paths = cookbook.checksums
|
45
|
+
Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segment|
|
46
|
+
cookbook.manifest[segment].each do |manifest_record|
|
47
|
+
path_in_cookbook = manifest_record[:path]
|
48
|
+
on_disk_path = checksums_to_on_disk_paths[manifest_record[:checksum]]
|
49
|
+
dest = File.join(tmp_cookbook_dir, cookbook.name.to_s, path_in_cookbook)
|
50
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
51
|
+
Chef::Log.debug("Staging #{on_disk_path} to #{dest}")
|
52
|
+
FileUtils.cp(on_disk_path, dest)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# First, generate metadata
|
57
|
+
Chef::Log.debug("Generating metadata")
|
58
|
+
kcm = Chef::Knife::CookbookMetadata.new
|
59
|
+
kcm.config[:cookbook_path] = [ tmp_cookbook_dir ]
|
60
|
+
kcm.name_args = [ cookbook.name.to_s ]
|
61
|
+
kcm.run
|
62
|
+
|
63
|
+
tmp_cookbook_dir
|
64
|
+
end
|
65
|
+
|
37
66
|
def post(to_url, user_id, secret_key_filename, params = {}, headers = {})
|
38
67
|
make_request(:post, to_url, user_id, secret_key_filename, params, headers)
|
39
68
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rest_client'
|
2
2
|
require 'chef/cookbook_loader'
|
3
|
-
require 'chef/
|
3
|
+
require 'chef/checksum_cache'
|
4
4
|
require 'chef/sandbox'
|
5
5
|
require 'chef/cookbook_version'
|
6
6
|
require 'chef/cookbook/syntax_check'
|
@@ -23,7 +23,7 @@ class Chef
|
|
23
23
|
# generate checksums of cookbook files and create a sandbox
|
24
24
|
checksum_files = cookbook.checksums
|
25
25
|
checksums = checksum_files.inject({}){|memo,elt| memo[elt.first]=nil ; memo}
|
26
|
-
new_sandbox = rest.post_rest("
|
26
|
+
new_sandbox = rest.post_rest("sandboxes", { :checksums => checksums })
|
27
27
|
|
28
28
|
Chef::Log.info("Uploading files")
|
29
29
|
# upload the new checksums and commit the sandbox
|
@@ -48,8 +48,8 @@ class Chef
|
|
48
48
|
headers = { 'content-type' => 'application/x-binary', 'content-md5' => checksum64, :accept => 'application/json' }
|
49
49
|
headers.merge!(sign_obj.sign(OpenSSL::PKey::RSA.new(rest.signing_key)))
|
50
50
|
begin
|
51
|
-
RestClient::
|
52
|
-
rescue RestClient::
|
51
|
+
RestClient::Resource.new(info['url'], :headers=>headers, :timeout=>1800, :open_timeout=>1800).put(file_contents)
|
52
|
+
rescue RestClient::Exception => e
|
53
53
|
Chef::Log.error("Upload failed: #{e.message}\n#{e.response.body}")
|
54
54
|
raise
|
55
55
|
end
|
@@ -72,19 +72,20 @@ class Chef
|
|
72
72
|
raise
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
76
75
|
# files are uploaded, so save the manifest
|
77
76
|
cookbook.save
|
78
|
-
|
79
77
|
Chef::Log.info("Upload complete!")
|
80
78
|
end
|
81
79
|
|
82
80
|
def build_metadata(cookbook)
|
83
81
|
Chef::Log.debug("Generating metadata")
|
82
|
+
# FIXME: This knife command should be factored out into a
|
83
|
+
# library for use here
|
84
84
|
kcm = Chef::Knife::CookbookMetadata.new
|
85
85
|
kcm.config[:cookbook_path] = Chef::Config[:cookbook_path]
|
86
86
|
kcm.name_args = [ cookbook.name.to_s ]
|
87
87
|
kcm.run
|
88
|
+
cookbook.reload_metadata!
|
88
89
|
end
|
89
90
|
|
90
91
|
def validate_cookbook(cookbook)
|
@@ -99,4 +100,4 @@ class Chef
|
|
99
100
|
|
100
101
|
end
|
101
102
|
end
|
102
|
-
end
|
103
|
+
end
|