summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom May <thom@chef.io>2016-03-03 10:11:29 +0000
committerThom May <thom@chef.io>2016-03-03 10:11:29 +0000
commit788ec4597c9f1517c26d85703bdc79ea01e5ff53 (patch)
tree23364a04f0906df0697565ba84f9163b48a61298
parenta4d98365c1d68d7a24fba62783538951d2bbd2e0 (diff)
parent9c7bc8730af9ddba70d5095301517ae9e07e5024 (diff)
downloadchef-788ec4597c9f1517c26d85703bdc79ea01e5ff53.tar.gz
Merge branch 'remote-file-download-progress' of https://github.com/brandocorp/chef into tm/remote_file_download_progress
-rw-r--r--lib/chef/event_dispatch/base.rb6
-rw-r--r--lib/chef/formatters/doc.rb16
-rw-r--r--lib/chef/http.rb36
-rw-r--r--lib/chef/provider/remote_file/http.rb16
-rw-r--r--lib/chef/resource/remote_file.rb18
5 files changed, 90 insertions, 2 deletions
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index a6a18718c2..65cb519dc7 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -297,6 +297,12 @@ class Chef
# - resource_completed
#
+ # Called when a progress notification should be sent to the user to
+ # indicate the overall progress of a long running operation, such as
+ # a large file download.
+ def resource_action_progress(resource, current, total, interval)
+ end
+
# Called before action is executed on a resource.
def resource_action_start(resource, action, notification_type = nil, notifier = nil)
end
diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb
index 5462241049..31732066a8 100644
--- a/lib/chef/formatters/doc.rb
+++ b/lib/chef/formatters/doc.rb
@@ -23,6 +23,7 @@ class Chef
@start_time = Time.now
@end_time = @start_time
@skipped_resources = 0
+ @progress = {}
end
def elapsed_time
@@ -258,6 +259,21 @@ class Chef
indent
end
+ def resource_action_progress(resource, current, total, interval)
+ @progress[resource] ||= 0
+
+ percent_complete = (current.to_f / total.to_f * 100).to_i
+
+ if percent_complete > @progress[resource]
+
+ @progress[resource] = percent_complete
+
+ if percent_complete % interval == 0
+ start_line " - Progress: #{percent_complete}/100 %", :green
+ end
+ end
+ end
+
# Called when a resource fails, but will retry.
def resource_failed_retriable(resource, action, retry_count, exception)
end
diff --git a/lib/chef/http.rb b/lib/chef/http.rb
index a3673ce281..c90f799cd9 100644
--- a/lib/chef/http.rb
+++ b/lib/chef/http.rb
@@ -74,6 +74,9 @@ class Chef
attr_reader :redirect_limit
attr_reader :options
+ attr_reader :show_progress
+ attr_reader :progress_interval
+
attr_reader :middlewares
# Create a HTTP client object. The supplied +url+ is used as the base for
@@ -153,6 +156,34 @@ class Chef
raise
end
+
+ def streaming_request_with_progress(path, headers={}, &progress_block)
+ url = create_url(path)
+ response, rest_request, return_value = nil, nil, nil
+ tempfile = nil
+
+ method = :GET
+ method, url, headers, data = apply_request_middleware(method, url, headers, data)
+
+ response, rest_request, return_value = send_http_request(method, url, headers, data) do |http_response|
+ if http_response.kind_of?(Net::HTTPSuccess)
+ tempfile = stream_to_tempfile(url, http_response, &progress_block)
+ end
+ apply_stream_complete_middleware(http_response, rest_request, return_value)
+ end
+ return nil if response.kind_of?(Net::HTTPRedirection)
+ unless response.kind_of?(Net::HTTPSuccess)
+ response.error!
+ end
+ tempfile
+ rescue Exception => e
+ log_failed_request(response, return_value) unless response.nil?
+ if e.respond_to?(:chef_rest_request=)
+ e.chef_rest_request = rest_request
+ end
+ raise
+ end
+
# Makes a streaming download request, streaming the response body to a
# tempfile. If a block is given, the tempfile is passed to the block and
# the tempfile will automatically be unlinked after the block is executed.
@@ -389,7 +420,8 @@ class Chef
headers
end
- def stream_to_tempfile(url, response)
+ def stream_to_tempfile(url, response, &progress_block)
+ content_length = response['Content-Length']
tf = Tempfile.open("chef-rest")
if Chef::Platform.windows?
tf.binmode # required for binary files on Windows platforms
@@ -402,6 +434,7 @@ class Chef
response.read_body do |chunk|
tf.write(stream_handler.handle_chunk(chunk))
+ yield tf.size, content_length if block_given?
end
tf.close
tf
@@ -425,3 +458,4 @@ class Chef
end
end
+
diff --git a/lib/chef/provider/remote_file/http.rb b/lib/chef/provider/remote_file/http.rb
index 6fa574e777..3b97d116aa 100644
--- a/lib/chef/provider/remote_file/http.rb
+++ b/lib/chef/provider/remote_file/http.rb
@@ -39,6 +39,10 @@ class Chef
@current_resource = current_resource
end
+ def events
+ new_resource.events
+ end
+
def headers
conditional_get_headers.merge(new_resource.headers)
end
@@ -57,7 +61,13 @@ class Chef
def fetch
http = Chef::HTTP::Simple.new(uri, http_client_opts)
- tempfile = http.streaming_request(uri, headers)
+ if want_progress?
+ tempfile = http.streaming_request_with_progress(uri, headers) do |size, total|
+ events.resource_action_progress(new_resource, size, total, new_resource.progress_interval)
+ end
+ else
+ tempfile = http.streaming_request(uri, headers)
+ end
if tempfile
update_cache_control_data(tempfile, http.last_response)
tempfile.close
@@ -78,6 +88,10 @@ class Chef
@cache_control_data ||= CacheControlData.load_and_validate(uri, current_resource.checksum)
end
+ def want_progress?
+ new_resource.show_progress
+ end
+
def want_mtime_cache_control?
new_resource.use_last_modified
end
diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb
index b42cf4ba5f..b615297c24 100644
--- a/lib/chef/resource/remote_file.rb
+++ b/lib/chef/resource/remote_file.rb
@@ -122,6 +122,24 @@ class Chef
)
end
+ def show_progress(args=nil)
+ set_or_return(
+ :show_progress,
+ args,
+ :default => false,
+ :kind_of => [ TrueClass, FalseClass ]
+ )
+ end
+
+ def progress_interval(args=nil)
+ set_or_return(
+ :progress_interval,
+ args,
+ :default => 10,
+ :equal_to => [1, 5, 10, 20, 25]
+ )
+ end
+
private
include Chef::Mixin::Uris