chef 0.10.10 → 10.12.0.rc.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 (94) hide show
  1. data/README.rdoc +6 -0
  2. data/distro/common/html/chef-client.8.html +4 -3
  3. data/distro/common/html/chef-expander.8.html +3 -3
  4. data/distro/common/html/chef-expanderctl.8.html +3 -3
  5. data/distro/common/html/chef-server-webui.8.html +3 -3
  6. data/distro/common/html/chef-server.8.html +3 -3
  7. data/distro/common/html/chef-solo.8.html +3 -3
  8. data/distro/common/html/chef-solr.8.html +3 -3
  9. data/distro/common/html/knife-bootstrap.1.html +3 -3
  10. data/distro/common/html/knife-client.1.html +3 -3
  11. data/distro/common/html/knife-configure.1.html +3 -3
  12. data/distro/common/html/knife-cookbook-site.1.html +3 -3
  13. data/distro/common/html/knife-cookbook.1.html +3 -3
  14. data/distro/common/html/knife-data-bag.1.html +3 -3
  15. data/distro/common/html/knife-environment.1.html +3 -3
  16. data/distro/common/html/knife-exec.1.html +3 -3
  17. data/distro/common/html/knife-index.1.html +3 -3
  18. data/distro/common/html/knife-node.1.html +3 -3
  19. data/distro/common/html/knife-role.1.html +3 -3
  20. data/distro/common/html/knife-search.1.html +3 -3
  21. data/distro/common/html/knife-ssh.1.html +3 -3
  22. data/distro/common/html/knife-status.1.html +3 -3
  23. data/distro/common/html/knife-tag.1.html +3 -3
  24. data/distro/common/html/knife.1.html +3 -3
  25. data/distro/common/html/shef.1.html +3 -3
  26. data/distro/common/man/man1/knife-bootstrap.1 +1 -1
  27. data/distro/common/man/man1/knife-client.1 +1 -1
  28. data/distro/common/man/man1/knife-configure.1 +1 -1
  29. data/distro/common/man/man1/knife-cookbook-site.1 +1 -1
  30. data/distro/common/man/man1/knife-cookbook.1 +1 -1
  31. data/distro/common/man/man1/knife-data-bag.1 +1 -1
  32. data/distro/common/man/man1/knife-environment.1 +1 -1
  33. data/distro/common/man/man1/knife-exec.1 +1 -1
  34. data/distro/common/man/man1/knife-index.1 +1 -1
  35. data/distro/common/man/man1/knife-node.1 +1 -1
  36. data/distro/common/man/man1/knife-role.1 +1 -1
  37. data/distro/common/man/man1/knife-search.1 +1 -1
  38. data/distro/common/man/man1/knife-ssh.1 +1 -1
  39. data/distro/common/man/man1/knife-status.1 +1 -1
  40. data/distro/common/man/man1/knife-tag.1 +1 -1
  41. data/distro/common/man/man1/knife.1 +1 -1
  42. data/distro/common/man/man1/shef.1 +1 -1
  43. data/distro/common/man/man8/chef-client.8 +5 -1
  44. data/distro/common/man/man8/chef-expander.8 +1 -1
  45. data/distro/common/man/man8/chef-expanderctl.8 +1 -1
  46. data/distro/common/man/man8/chef-server-webui.8 +1 -1
  47. data/distro/common/man/man8/chef-server.8 +1 -1
  48. data/distro/common/man/man8/chef-solo.8 +1 -1
  49. data/distro/common/man/man8/chef-solr.8 +1 -1
  50. data/distro/common/markdown/man8/chef-client.mkd +2 -0
  51. data/lib/chef/application/client.rb +1 -1
  52. data/lib/chef/application/solo.rb +1 -1
  53. data/lib/chef/application/windows_service.rb +1 -1
  54. data/lib/chef/config.rb +1 -1
  55. data/lib/chef/exceptions.rb +3 -0
  56. data/lib/chef/file_access_control/unix.rb +21 -6
  57. data/lib/chef/file_access_control/windows.rb +7 -7
  58. data/lib/chef/knife/ssh.rb +4 -2
  59. data/lib/chef/mixin/enforce_ownership_and_permissions.rb +1 -1
  60. data/lib/chef/provider/link.rb +49 -45
  61. data/lib/chef/provider/mdadm.rb +4 -1
  62. data/lib/chef/provider/package/rubygems.rb +2 -1
  63. data/lib/chef/provider/remote_file.rb +17 -1
  64. data/lib/chef/reserved_names.rb +9 -0
  65. data/lib/chef/resource/link.rb +1 -17
  66. data/lib/chef/resource/mdadm.rb +1 -1
  67. data/lib/chef/resource_platform_map.rb +1 -3
  68. data/lib/chef/rest.rb +48 -17
  69. data/lib/chef/version.rb +1 -1
  70. data/lib/chef/win32/api.rb +16 -1
  71. data/lib/chef/win32/api/error.rb +9 -9
  72. data/lib/chef/win32/api/file.rb +263 -17
  73. data/lib/chef/win32/api/memory.rb +12 -12
  74. data/lib/chef/win32/api/process.rb +5 -5
  75. data/lib/chef/win32/api/psapi.rb +3 -3
  76. data/lib/chef/win32/api/security.rb +41 -41
  77. data/lib/chef/win32/api/system.rb +8 -8
  78. data/lib/chef/win32/api/unicode.rb +6 -6
  79. data/lib/chef/win32/error.rb +4 -4
  80. data/lib/chef/win32/file.rb +65 -15
  81. data/lib/chef/win32/file/info.rb +7 -7
  82. data/lib/chef/win32/handle.rb +3 -3
  83. data/lib/chef/win32/memory.rb +8 -8
  84. data/lib/chef/win32/process.rb +8 -8
  85. data/lib/chef/win32/security.rb +49 -49
  86. data/lib/chef/win32/security/ace.rb +11 -11
  87. data/lib/chef/win32/security/acl.rb +10 -10
  88. data/lib/chef/win32/security/securable_object.rb +13 -13
  89. data/lib/chef/win32/security/security_descriptor.rb +12 -12
  90. data/lib/chef/win32/security/sid.rb +8 -8
  91. data/lib/chef/win32/security/token.rb +8 -8
  92. data/lib/chef/win32/unicode.rb +5 -5
  93. data/lib/chef/win32/version.rb +4 -4
  94. metadata +374 -370
@@ -22,9 +22,9 @@ require 'chef/win32/security'
22
22
  class Chef
23
23
  class FileAccessControl
24
24
  module Windows
25
- include Chef::Win32::API::Security
25
+ include Chef::ReservedNames::Win32::API::Security
26
26
 
27
- Security = Chef::Win32::Security
27
+ Security = Chef::ReservedNames::Win32::Security
28
28
  ACL = Security::ACL
29
29
  ACE = Security::ACE
30
30
  SID = Security::SID
@@ -83,9 +83,9 @@ class Chef
83
83
  def securable_object
84
84
  @securable_object ||= begin
85
85
  if file.kind_of?(String)
86
- so = Chef::Win32::Security::SecurableObject.new(file.dup)
86
+ so = Chef::ReservedNames::Win32::Security::SecurableObject.new(file.dup)
87
87
  end
88
- raise ArgumentError, "'file' must be a valid path or object of type 'Chef::Win32::Security::SecurableObject'" unless so.kind_of? Chef::Win32::Security::SecurableObject
88
+ raise ArgumentError, "'file' must be a valid path or object of type 'Chef::ReservedNames::Win32::Security::SecurableObject'" unless so.kind_of? Chef::ReservedNames::Win32::Security::SecurableObject
89
89
  so
90
90
  end
91
91
  end
@@ -223,20 +223,20 @@ class Chef
223
223
  if owner
224
224
  acls += mode_ace(owner, (mode & 0700) >> 6)
225
225
  elsif mode & 0700 != 0
226
- raise "Mode #{mode.to_s(8)} includes bits for the owner, but owner is not specified"
226
+ Chef::Log.warn("Mode #{sprintf("%03o", mode)} includes bits for the owner, but owner is not specified")
227
227
  end
228
228
 
229
229
  group = target_group
230
230
  if group
231
231
  acls += mode_ace(group, (mode & 070) >> 3)
232
232
  elsif mode & 070 != 0
233
- raise "Mode #{mode.to_s(8)} includes bits for the group, but group is not specified"
233
+ Chef::Log.warn("Mode #{sprintf("%03o", mode)} includes bits for the group, but group is not specified")
234
234
  end
235
235
 
236
236
  acls += mode_ace(SID.Everyone, (mode & 07))
237
237
  end
238
238
 
239
- acls.nil? ? nil : Chef::Win32::Security::ACL.create(acls)
239
+ acls.nil? ? nil : Chef::ReservedNames::Win32::Security::ACL.create(acls)
240
240
  end
241
241
 
242
242
  def target_group
@@ -27,9 +27,11 @@ class Chef
27
27
  require 'net/ssh/multi'
28
28
  require 'readline'
29
29
  require 'chef/search/query'
30
- require 'chef/mixin/command'
30
+ require 'chef/mixin/shell_out'
31
31
  end
32
32
 
33
+ include Chef::Mixin::ShellOut
34
+
33
35
  attr_writer :password
34
36
 
35
37
  banner "knife ssh QUERY COMMAND (options)"
@@ -294,7 +296,7 @@ class Chef
294
296
  cmd = ["tmux new-session -d -s #{tmux_name}",
295
297
  "-n '#{server.host}'", ssh_dest.call(server),
296
298
  new_window_cmds.call].join(" ")
297
- Chef::Mixin::Command.run_command(:command => cmd)
299
+ shell_out!(cmd)
298
300
  exec("tmux attach-session -t #{tmux_name}")
299
301
  rescue Chef::Exceptions::Exec
300
302
  end
@@ -31,7 +31,7 @@ class Chef
31
31
  end
32
32
  access_controls = Chef::FileAccessControl.new(new_resource, path)
33
33
  access_controls.set_all
34
- new_resource.updated_by_last_action(access_controls.modified?)
34
+ new_resource.updated_by_last_action(true) if access_controls.modified?
35
35
  end
36
36
 
37
37
  end
@@ -30,7 +30,16 @@ class Chef
30
30
  def file_class
31
31
  @host_os_file ||= if Chef::Platform.windows?
32
32
  require 'chef/win32/file'
33
- Chef::Win32::File
33
+ begin
34
+ Chef::ReservedNames::Win32::File.verify_links_supported!
35
+ rescue Chef::Exceptions::Win32APIFunctionNotImplemented => e
36
+ message = "Link resource is not supported on this version of Windows"
37
+ message << ": #{node[:kernel][:name]}" if node
38
+ message << " (#{node[:platform_version]})" if node
39
+ Chef::Log.fatal(message)
40
+ raise e
41
+ end
42
+ Chef::ReservedNames::Win32::File
34
43
  else
35
44
  ::File
36
45
  end
@@ -48,44 +57,47 @@ class Chef
48
57
  def load_current_resource
49
58
  @current_resource = Chef::Resource::Link.new(@new_resource.name)
50
59
  @current_resource.target_file(@new_resource.target_file)
51
- @current_resource.link_type(@new_resource.link_type)
52
- if @new_resource.link_type == :symbolic
53
- if ::File.exists?(@current_resource.target_file) && file_class.symlink?(@current_resource.target_file)
54
- @current_resource.to(
55
- ::File.expand_path(file_class.readlink(@current_resource.target_file))
56
- )
57
- cstats = ::File.lstat(@current_resource.target_file)
58
- @current_resource.owner(cstats.uid)
59
- @current_resource.group(cstats.gid)
60
- else
61
- @current_resource.to("")
62
- end
63
- elsif @new_resource.link_type == :hard
64
- if ::File.exists?(@current_resource.target_file) && ::File.exists?(@new_resource.to)
65
- if ::File.stat(@current_resource.target_file).ino == ::File.stat(@new_resource.to).ino
66
- @current_resource.to(@new_resource.to)
60
+ if file_class.symlink?(@current_resource.target_file)
61
+ @current_resource.link_type(:symbolic)
62
+ @current_resource.to(
63
+ canonicalize(file_class.readlink(@current_resource.target_file))
64
+ )
65
+ cstats = ::File.lstat(@current_resource.target_file)
66
+ @current_resource.owner(cstats.uid)
67
+ @current_resource.group(cstats.gid)
68
+ else
69
+ @current_resource.link_type(:hard)
70
+ if ::File.exists?(@current_resource.target_file)
71
+ if ::File.exists?(@new_resource.to) &&
72
+ file_class.stat(@current_resource.target_file).ino ==
73
+ file_class.stat(@new_resource.to).ino
74
+ @current_resource.to(canonicalize(@new_resource.to))
67
75
  else
68
76
  @current_resource.to("")
69
77
  end
70
- else
71
- @current_resource.to("")
72
78
  end
73
79
  end
74
80
  @current_resource
75
81
  end
76
82
 
83
+ def canonicalize(path)
84
+ Chef::Platform.windows? ? path.gsub('/', '\\') : path
85
+ end
86
+
77
87
  def action_create
78
- if @current_resource.to != ::File.expand_path(@new_resource.to, @new_resource.target_file)
88
+ if @current_resource.to != canonicalize(@new_resource.to) ||
89
+ @current_resource.link_type != @new_resource.link_type
79
90
  if @new_resource.link_type == :symbolic
80
- unless (file_class.symlink?(@new_resource.target_file) && file_class.readlink(@new_resource.target_file) == @new_resource.to)
81
- if file_class.symlink?(@new_resource.target_file) || ::File.exist?(@new_resource.target_file)
82
- ::File.unlink(@new_resource.target_file)
83
- end
84
- file_class.symlink(@new_resource.to,@new_resource.target_file)
85
- Chef::Log.debug("#{@new_resource} created #{@new_resource.link_type} link from #{@new_resource.to} -> #{@new_resource.target_file}")
86
- Chef::Log.info("#{@new_resource} created")
91
+ if @current_resource.to # nil if target_file does not exist
92
+ ::File.unlink(@new_resource.target_file)
87
93
  end
94
+ file_class.symlink(canonicalize(@new_resource.to),@new_resource.target_file)
95
+ Chef::Log.debug("#{@new_resource} created #{@new_resource.link_type} link from #{@new_resource.to} -> #{@new_resource.target_file}")
96
+ Chef::Log.info("#{@new_resource} created")
88
97
  elsif @new_resource.link_type == :hard
98
+ if @current_resource.to # nil if target_file does not exist
99
+ ::File.unlink(@new_resource.target_file)
100
+ end
89
101
  file_class.link(@new_resource.to, @new_resource.target_file)
90
102
  Chef::Log.debug("#{@new_resource} created #{@new_resource.link_type} link from #{@new_resource.to} -> #{@new_resource.target_file}")
91
103
  Chef::Log.info("#{@new_resource} created")
@@ -93,29 +105,21 @@ class Chef
93
105
  @new_resource.updated_by_last_action(true)
94
106
  end
95
107
  if @new_resource.link_type == :symbolic
96
- enforce_ownership_and_permissions
108
+ enforce_ownership_and_permissions @new_resource.target_file
97
109
  end
98
110
  end
99
111
 
100
112
  def action_delete
101
- if @new_resource.link_type == :symbolic
102
- if file_class.symlink?(@new_resource.target_file)
103
- ::File.delete(@new_resource.target_file)
104
- Chef::Log.info("#{@new_resource} deleted")
105
- @new_resource.updated_by_last_action(true)
106
- elsif ::File.exists?(@new_resource.target_file)
107
- raise Chef::Exceptions::Link, "Cannot delete #{@new_resource} at #{@new_resource.target_file}! Not a symbolic link."
108
- end
109
- elsif @new_resource.link_type == :hard
110
- if ::File.exists?(@new_resource.target_file)
111
- if ::File.exists?(@new_resource.to) && (file_class.stat(@current_resource.target_file).ino == file_class.stat(@new_resource.to).ino)
112
- ::File.delete(@new_resource.target_file)
113
- Chef::Log.info("#{@new_resource} deleted")
114
- @new_resource.updated_by_last_action(true)
115
- else
116
- raise Chef::Exceptions::Link, "Cannot delete #{@new_resource} at #{@new_resource.target_file}! Not a hard link."
117
- end
113
+ if @current_resource.to # Exists
114
+ if @current_resource.link_type == @new_resource.link_type
115
+ unless @current_resource.link_type == :hard && @current_resource.to == ''
116
+ ::File.delete(@new_resource.target_file)
117
+ Chef::Log.info("#{@new_resource} deleted")
118
+ @new_resource.updated_by_last_action(true)
119
+ return
120
+ end
118
121
  end
122
+ raise Chef::Exceptions::Link, "Cannot delete #{@new_resource} at #{@new_resource.target_file}! Not a #{@new_resource.link_type.to_s} link."
119
123
  end
120
124
  end
121
125
  end
@@ -51,7 +51,10 @@ class Chef
51
51
 
52
52
  def action_create
53
53
  unless @current_resource.exists
54
- command = "yes | mdadm --create #{@new_resource.raid_device} --chunk=#{@new_resource.chunk} --level #{@new_resource.level} --metadata=#{@new_resource.metadata} --bitmap=#{@new_resource.bitmap} --raid-devices #{@new_resource.devices.length} #{@new_resource.devices.join(" ")}"
54
+ command = "yes | mdadm --create #{@new_resource.raid_device} --chunk=#{@new_resource.chunk} --level #{@new_resource.level}"
55
+ command << " --metadata=#{@new_resource.metadata}"
56
+ command << " --bitmap=#{@new_resource.bitmap}" if @new_resource.bitmap
57
+ command << " --raid-devices #{@new_resource.devices.length} #{@new_resource.devices.join(" ")}"
55
58
  Chef::Log.debug("#{@new_resource} mdadm command: #{command}")
56
59
  #pid, stdin, stdout, stderr = popen4(command)
57
60
  shell_out!(command)
@@ -344,6 +344,7 @@ class Chef
344
344
  # Opscode Omnibus - The ruby that ships inside omnibus is only used for Chef
345
345
  # Default to installing somewhere more functional
346
346
  gem_location = find_gem_by_path
347
+ @new_resource.gem_binary gem_location
347
348
  @gem_env = AlternateGemEnvironment.new(gem_location)
348
349
  Chef::Log.debug("#{@new_resource} using gem '#{gem_location}'")
349
350
  else
@@ -353,7 +354,7 @@ class Chef
353
354
  end
354
355
 
355
356
  def is_omnibus?
356
- if RbConfig::CONFIG['bindir'] == "/opt/chef/embedded/bin"
357
+ if RbConfig::CONFIG['bindir'] =~ %r!/opt/(opscode|chef)/embedded/bin!
357
358
  Chef::Log.debug("#{@new_resource} detected omnibus installation in #{RbConfig::CONFIG['bindir']}")
358
359
  # Omnibus installs to a static path because of linking on unix, find it.
359
360
  true
@@ -39,7 +39,7 @@ class Chef
39
39
  if current_resource_matches_target_checksum?
40
40
  Chef::Log.debug("#{@new_resource} checksum matches target checksum (#{@new_resource.checksum}) - not updating")
41
41
  else
42
- Chef::REST.new(@new_resource.source, nil, nil).fetch(@new_resource.source) do |raw_file|
42
+ Chef::REST.new(@new_resource.source, nil, nil, http_client_opts).fetch(@new_resource.source) do |raw_file|
43
43
  if matches_current_checksum?(raw_file)
44
44
  Chef::Log.debug "#{@new_resource} target and source checksums are the same - not updating"
45
45
  else
@@ -99,6 +99,22 @@ class Chef
99
99
  end
100
100
  end
101
101
 
102
+ def http_client_opts
103
+ opts={}
104
+ # CHEF-3140
105
+ # 1. If it's already compressed, trying to compress it more will
106
+ # probably be counter-productive.
107
+ # 2. Some servers are misconfigured so that you GET $URL/file.tgz but
108
+ # they respond with content type of tar and content encoding of gzip,
109
+ # which tricks Chef::REST into decompressing the response body. In this
110
+ # case you'd end up with a tar archive (no gzip) named, e.g., foo.tgz,
111
+ # which is not what you wanted.
112
+ if @new_resource.path =~ /gz$/ or @new_resource.source =~ /gz$/
113
+ opts[:disable_gzip] = true
114
+ end
115
+ opts
116
+ end
117
+
102
118
  private
103
119
 
104
120
  def absolute_uri?(source)
@@ -0,0 +1,9 @@
1
+ class Chef
2
+
3
+ # This module exists to hide conflicting constant names from the DSL.
4
+ # Hopefully we'll have a better/prettier/more sustainable solution in the
5
+ # future, but for now this will fix a regression introduced in Chef 0.10.10
6
+ # (conflict with the Win32 namespace)
7
+ module ReservedNames
8
+ end
9
+ end
@@ -39,7 +39,7 @@ class Chef
39
39
 
40
40
  def to(arg=nil)
41
41
  set_or_return(
42
- :source_file,
42
+ :to,
43
43
  arg,
44
44
  :kind_of => String
45
45
  )
@@ -62,22 +62,6 @@ class Chef
62
62
  )
63
63
  end
64
64
 
65
- def group(arg=nil)
66
- set_or_return(
67
- :group,
68
- arg,
69
- :regex => Chef::Config[:group_valid_regex]
70
- )
71
- end
72
-
73
- def owner(arg=nil)
74
- set_or_return(
75
- :owner,
76
- arg,
77
- :regex => Chef::Config[:user_valid_regex]
78
- )
79
- end
80
-
81
65
  end
82
66
  end
83
67
  end
@@ -31,7 +31,7 @@ class Chef
31
31
  @exists = false
32
32
  @level = 1
33
33
  @metadata = "0.90"
34
- @bitmap = "none"
34
+ @bitmap = nil
35
35
  @raid_device = name
36
36
 
37
37
  @action = :create
@@ -43,7 +43,6 @@ class Chef
43
43
 
44
44
  if map.has_key?(platform_sym)
45
45
  if map[platform_sym].has_key?(version)
46
- Chef::Log.debug("Platform #{platform_sym} version #{version} found")
47
46
  if map[platform_sym].has_key?(:default)
48
47
  resource_map.merge!(map[platform_sym][:default])
49
48
  end
@@ -51,8 +50,6 @@ class Chef
51
50
  elsif map[platform_sym].has_key?(:default)
52
51
  resource_map.merge!(map[platform_sym][:default])
53
52
  end
54
- else
55
- Chef::Log.debug("Platform #{platform} not found, using all defaults. (Unsupported platform?)")
56
53
  end
57
54
  resource_map
58
55
  end
@@ -136,6 +133,7 @@ class Chef
136
133
  def platform_resource(short_name, platform, version)
137
134
  pmap = filter(platform, version)
138
135
  rtkey = short_name.kind_of?(Chef::Resource) ? short_name.resource_name.to_sym : short_name
136
+
139
137
  pmap.has_key?(rtkey) ? pmap[rtkey] : nil
140
138
  end
141
139
 
@@ -62,6 +62,8 @@ class Chef
62
62
  @sign_on_redirect, @sign_request = true, true
63
63
  @redirects_followed = 0
64
64
  @redirect_limit = 10
65
+ @disable_gzip = false
66
+ handle_options(options)
65
67
  end
66
68
 
67
69
  def signing_key_filename
@@ -267,15 +269,19 @@ class Chef
267
269
  end
268
270
 
269
271
  def decompress_body(response)
270
- case response[CONTENT_ENCODING]
271
- when GZIP
272
- Chef::Log.debug "decompressing gzip response"
273
- Zlib::Inflate.new(Zlib::MAX_WBITS + 16).inflate(response.body)
274
- when DEFLATE
275
- Chef::Log.debug "decompressing deflate response"
276
- Zlib::Inflate.inflate(response.body)
277
- else
272
+ if gzip_disabled?
278
273
  response.body
274
+ else
275
+ case response[CONTENT_ENCODING]
276
+ when GZIP
277
+ Chef::Log.debug "decompressing gzip response"
278
+ Zlib::Inflate.new(Zlib::MAX_WBITS + 16).inflate(response.body)
279
+ when DEFLATE
280
+ Chef::Log.debug "decompressing deflate response"
281
+ Zlib::Inflate.inflate(response.body)
282
+ else
283
+ response.body
284
+ end
279
285
  end
280
286
  end
281
287
 
@@ -403,7 +409,7 @@ class Chef
403
409
  headers['Accept'] = "application/json" unless raw
404
410
  headers["Content-Type"] = 'application/json' if json_body
405
411
  headers['Content-Length'] = json_body.bytesize.to_s if json_body
406
- headers[RESTRequest::ACCEPT_ENCODING] = RESTRequest::ENCODING_GZIP_DEFLATE
412
+ headers[RESTRequest::ACCEPT_ENCODING] = RESTRequest::ENCODING_GZIP_DEFLATE unless gzip_disabled?
407
413
  headers.merge!(authentication_headers(method, url, json_body)) if sign_requests?
408
414
  headers.merge!(Chef::Config[:custom_http_headers]) if Chef::Config[:custom_http_headers]
409
415
  headers
@@ -419,15 +425,19 @@ class Chef
419
425
  # Kudos to _why!
420
426
  size, total = 0, response.header['Content-Length'].to_i
421
427
 
422
- inflater = case response[CONTENT_ENCODING]
423
- when GZIP
424
- Chef::Log.debug "decompressing gzip stream"
425
- Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
426
- when DEFLATE
427
- Chef::Log.debug "decompressing inflate stream"
428
- Zlib::Inflate.new
429
- else
428
+ inflater = if gzip_disabled?
430
429
  NoopInflater.new
430
+ else
431
+ case response[CONTENT_ENCODING]
432
+ when GZIP
433
+ Chef::Log.debug "decompressing gzip stream"
434
+ Zlib::Inflate.new(Zlib::MAX_WBITS + 16)
435
+ when DEFLATE
436
+ Chef::Log.debug "decompressing inflate stream"
437
+ Zlib::Inflate.new
438
+ else
439
+ NoopInflater.new
440
+ end
431
441
  end
432
442
 
433
443
  response.read_body do |chunk|
@@ -441,5 +451,26 @@ class Chef
441
451
  raise
442
452
  end
443
453
 
454
+ # gzip is disabled using the disable_gzip => true option in the
455
+ # constructor. When gzip is disabled, no 'Accept-Encoding' header will be
456
+ # set, and the response will not be decompressed, no matter what the
457
+ # Content-Encoding header of the response is. The intended use case for
458
+ # this is to work around situations where you request +file.tar.gz+, but
459
+ # the server responds with a content type of tar and a content encoding of
460
+ # gzip, tricking the client into decompressing the response so you end up
461
+ # with a tar archive (no gzip) named file.tar.gz
462
+ def gzip_disabled?
463
+ @disable_gzip
464
+ end
465
+
466
+ def handle_options(opts)
467
+ opts.each do |name, value|
468
+ case name.to_s
469
+ when 'disable_gzip'
470
+ @disable_gzip = value
471
+ end
472
+ end
473
+ end
474
+
444
475
  end
445
476
  end