chef 12.14.89-universal-mingw32 → 12.15.19-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +76 -51
  3. data/Gemfile +1 -1
  4. data/README.md +9 -7
  5. data/Rakefile +1 -1
  6. data/VERSION +1 -1
  7. data/acceptance/Gemfile +3 -0
  8. data/acceptance/Gemfile.lock +19 -18
  9. data/acceptance/fips/.kitchen.yml +1 -1
  10. data/lib/chef/application/exit_code.rb +9 -0
  11. data/lib/chef/cookbook/file_system_file_vendor.rb +7 -8
  12. data/lib/chef/cookbook/metadata.rb +8 -0
  13. data/lib/chef/exceptions.rb +5 -0
  14. data/lib/chef/knife.rb +14 -15
  15. data/lib/chef/knife/ssh.rb +1 -0
  16. data/lib/chef/node/attribute.rb +1 -3
  17. data/lib/chef/node/attribute_collections.rb +20 -0
  18. data/lib/chef/provider/apt_repository.rb +1 -1
  19. data/lib/chef/provider/apt_update.rb +1 -1
  20. data/lib/chef/provider/group/groupadd.rb +2 -1
  21. data/lib/chef/provider/package/cab.rb +150 -0
  22. data/lib/chef/provider/package/rubygems.rb +0 -1
  23. data/lib/chef/provider/registry_key.rb +26 -2
  24. data/lib/chef/provider/remote_file/content.rb +1 -1
  25. data/lib/chef/provider/user.rb +10 -0
  26. data/lib/chef/provider/user/dscl.rb +2 -2
  27. data/lib/chef/provider/user/linux.rb +4 -14
  28. data/lib/chef/provider/user/pw.rb +2 -2
  29. data/lib/chef/provider/user/solaris.rb +15 -0
  30. data/lib/chef/provider/user/useradd.rb +1 -5
  31. data/lib/chef/providers.rb +1 -0
  32. data/lib/chef/resource/cab_package.rb +44 -0
  33. data/lib/chef/resource/registry_key.rb +3 -3
  34. data/lib/chef/resource/yum_repository.rb +1 -1
  35. data/lib/chef/resources.rb +1 -0
  36. data/lib/chef/server_api.rb +1 -1
  37. data/lib/chef/util/dsc/local_configuration_manager.rb +1 -1
  38. data/lib/chef/version.rb +1 -1
  39. data/spec/data/templates/chef-seattle20160930-4388-1crv7ef.txt +1 -0
  40. data/spec/data/templates/chef-seattle20160930-4388-jjfoae.txt +1 -0
  41. data/spec/data/templates/chef-seattle20160930-4388-umeq2c.txt +1 -0
  42. data/spec/functional/knife/cookbook_delete_spec.rb +48 -59
  43. data/spec/functional/resource/ifconfig_spec.rb +6 -0
  44. data/spec/functional/resource/registry_spec.rb +110 -4
  45. data/spec/unit/application/exit_code_spec.rb +10 -0
  46. data/spec/unit/cookbook/file_vendor_spec.rb +15 -0
  47. data/spec/unit/cookbook/metadata_spec.rb +19 -0
  48. data/spec/unit/exceptions_spec.rb +2 -0
  49. data/spec/unit/node/attribute_spec.rb +23 -1
  50. data/spec/unit/node/vivid_mash_spec.rb +27 -0
  51. data/spec/unit/provider/group/groupadd_spec.rb +118 -99
  52. data/spec/unit/provider/package/cab_spec.rb +218 -0
  53. data/spec/unit/provider/package/rubygems_spec.rb +2 -4
  54. data/spec/unit/provider/registry_key_spec.rb +94 -0
  55. data/spec/unit/provider/remote_file/content_spec.rb +1 -0
  56. data/spec/unit/provider/user/solaris_spec.rb +52 -40
  57. data/spec/unit/resource/apt_update_spec.rb +25 -17
  58. data/spec/unit/resource/cab_package_spec.rb +38 -0
  59. data/spec/unit/resource/registry_key_spec.rb +26 -10
  60. data/spec/unit/server_api_spec.rb +50 -0
  61. data/spec/unit/util/dsc/local_configuration_manager_spec.rb +10 -4
  62. metadata +13 -5
@@ -722,6 +722,14 @@ class Chef
722
722
  end
723
723
  end
724
724
 
725
+ def method_missing(method, *args, &block)
726
+ if block_given?
727
+ super
728
+ else
729
+ Chef::Log.debug "ignoring method #{method} on cookbook with name #{name}, possible typo or future metadata?"
730
+ end
731
+ end
732
+
725
733
  private
726
734
 
727
735
  # Helper to match a gem style version (ohai_version/chef_version) against a set of
@@ -79,6 +79,7 @@ class Chef
79
79
  class Reboot < Exception; end
80
80
  class RebootPending < Exception; end
81
81
  class RebootFailed < Mixlib::ShellOut::ShellCommandFailed; end
82
+ class ClientUpgraded < Exception; end
82
83
  class PrivateKeyMissing < RuntimeError; end
83
84
  class CannotWritePrivateKey < RuntimeError; end
84
85
  class RoleNotFound < RuntimeError; end
@@ -245,6 +246,10 @@ class Chef
245
246
  class Win32RegBadValueSize < ArgumentError; end
246
247
  class Win32RegTypesMismatch < ArgumentError; end
247
248
 
249
+ # incorrect input for registry_key create action throws following error
250
+ class RegKeyValuesTypeMissing < ArgumentError; end
251
+ class RegKeyValuesDataMissing < ArgumentError; end
252
+
248
253
  class InvalidEnvironmentPath < ArgumentError; end
249
254
  class EnvironmentNotFound < RuntimeError; end
250
255
 
@@ -236,6 +236,20 @@ class Chef
236
236
  OFFICIAL_PLUGINS = %w{ec2 rackspace windows openstack terremark bluebox}
237
237
 
238
238
  class << self
239
+ def list_commands(preferred_category = nil)
240
+ category_desc = preferred_category ? preferred_category + " " : ""
241
+ msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n"
242
+ subcommand_loader.list_commands(preferred_category).sort.each do |category, commands|
243
+ next if category =~ /deprecated/i
244
+ msg "** #{category.upcase} COMMANDS **"
245
+ commands.sort.each do |command|
246
+ subcommand_loader.load_command(command)
247
+ msg subcommands[command].banner if subcommands[command]
248
+ end
249
+ msg
250
+ end
251
+ end
252
+
239
253
  private
240
254
 
241
255
  # @api private
@@ -269,21 +283,6 @@ class Chef
269
283
  exit 10
270
284
  end
271
285
 
272
- # @api private
273
- def list_commands(preferred_category = nil)
274
- category_desc = preferred_category ? preferred_category + " " : ""
275
- msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n"
276
- subcommand_loader.list_commands(preferred_category).sort.each do |category, commands|
277
- next if category =~ /deprecated/i
278
- msg "** #{category.upcase} COMMANDS **"
279
- commands.sort.each do |command|
280
- subcommand_loader.load_command(command)
281
- msg subcommands[command].banner if subcommands[command]
282
- end
283
- msg
284
- end
285
- end
286
-
287
286
  # @api private
288
287
  def reset_config_path!
289
288
  @@chef_config_dir = nil
@@ -541,6 +541,7 @@ class Chef
541
541
 
542
542
  configure_user
543
543
  configure_password
544
+ @password = config[:ssh_password] if config[:ssh_password]
544
545
  configure_ssh_identity_file
545
546
  configure_gateway
546
547
  configure_session
@@ -452,9 +452,7 @@ class Chef
452
452
  #
453
453
 
454
454
  def merged_attributes(*path)
455
- # immutablize(
456
- merge_all(path)
457
- # )
455
+ immutablize(merge_all(path))
458
456
  end
459
457
 
460
458
  def combined_override(*path)
@@ -73,6 +73,7 @@ class Chef
73
73
  def initialize(root, data)
74
74
  @root = root
75
75
  super(data)
76
+ map! { |e| convert_value(e) }
76
77
  end
77
78
 
78
79
  # For elements like Fixnums, true, nil...
@@ -86,6 +87,23 @@ class Chef
86
87
  Array.new(map { |e| safe_dup(e) })
87
88
  end
88
89
 
90
+ private
91
+
92
+ def convert_value(value)
93
+ case value
94
+ when VividMash
95
+ value
96
+ when AttrArray
97
+ value
98
+ when Hash
99
+ VividMash.new(root, value)
100
+ when Array
101
+ AttrArray.new(root, value)
102
+ else
103
+ value
104
+ end
105
+ end
106
+
89
107
  end
90
108
 
91
109
  # == VividMash
@@ -184,6 +202,8 @@ class Chef
184
202
  case value
185
203
  when VividMash
186
204
  value
205
+ when AttrArray
206
+ value
187
207
  when Hash
188
208
  VividMash.new(root, value)
189
209
  when Array
@@ -153,7 +153,7 @@ class Chef
153
153
  end
154
154
 
155
155
  def install_key_from_uri
156
- key_name = new_resource.key.split(%r{\/}).last
156
+ key_name = new_resource.key.gsub(/[^0-9A-Za-z\-]/, "_")
157
157
  cached_keyfile = ::File.join(Chef::Config[:file_cache_path], key_name)
158
158
  type = if new_resource.key.start_with?("http")
159
159
  :remote_file
@@ -73,7 +73,7 @@ class Chef
73
73
  end
74
74
 
75
75
  declare_resource(:file, "#{APT_CONF_DIR}/15update-stamp") do
76
- content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};"
76
+ content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};\n"
77
77
  action :create_if_missing
78
78
  end
79
79
 
@@ -126,7 +126,8 @@ class Chef
126
126
 
127
127
  def groupadd_options
128
128
  opts = ""
129
- opts << " -r" if @new_resource.system
129
+ # Solaris doesn't support system groups.
130
+ opts << " -r" if @new_resource.system && !node.platform?("solaris2")
130
131
  opts << " -o" if @new_resource.non_unique
131
132
  opts
132
133
  end
@@ -0,0 +1,150 @@
1
+ #
2
+ # Author:: Vasundhara Jagdale (<vasundhara.jagdale@msystechnologies.com>)
3
+ # Copyright:: Copyright 2015-2016, Chef Software, 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/provider/package"
20
+ require "chef/resource/cab_package"
21
+ require "chef/mixin/shell_out"
22
+
23
+ class Chef
24
+ class Provider
25
+ class Package
26
+ class Cab < Chef::Provider::Package
27
+ include Chef::Mixin::ShellOut
28
+
29
+ provides :cab_package, os: "windows"
30
+
31
+ def load_current_resource
32
+ @current_resource = Chef::Resource::CabPackage.new(new_resource.name)
33
+ current_resource.source(new_resource.source)
34
+ new_resource.version(package_version)
35
+ current_resource.version(installed_version)
36
+ current_resource
37
+ end
38
+
39
+ def install_package(name, version)
40
+ dism_command("/Add-Package /PackagePath:\"#{@new_resource.source}\"")
41
+ end
42
+
43
+ def remove_package(name, version)
44
+ dism_command("/Remove-Package /PackagePath:\"#{@new_resource.source}\"")
45
+ end
46
+
47
+ def dism_command(command)
48
+ shellout = Mixlib::ShellOut.new("dism.exe /Online #{command} /NoRestart", { :timeout => @new_resource.timeout })
49
+ with_os_architecture(nil) do
50
+ shellout.run_command
51
+ end
52
+ end
53
+
54
+ def installed_version
55
+ stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{@new_resource.source}\"").stdout
56
+ package_info = parse_dism_get_package_info(stdout)
57
+ # e.g. Package_for_KB2975719~31bf3856ad364e35~amd64~~6.3.1.8
58
+ package = split_package_identity(package_info["package_information"]["package_identity"])
59
+ # Search for just the package name to catch a different version being installed
60
+ Chef::Log.debug("#{@new_resource} searching for installed package #{package['name']}")
61
+ found_packages = installed_packages.select { |p| p["package_identity"] =~ /^#{package['name']}~/ }
62
+ if found_packages.length == 0
63
+ nil
64
+ elsif found_packages.length == 1
65
+ stdout = dism_command("/Get-PackageInfo /PackageName:\"#{found_packages.first["package_identity"]}\"").stdout
66
+ find_version(stdout)
67
+ else
68
+ # Presuming this won't happen, otherwise we need to handle it
69
+ raise Chef::Exceptions::Package, "Found multiple packages installed matching name #{package['name']}, found: #{found_packages.length} matches"
70
+ end
71
+ end
72
+
73
+ def package_version
74
+ Chef::Log.debug("#{@new_resource} getting product version for package at #{@new_resource.source}")
75
+ stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{@new_resource.source}\"").stdout
76
+ find_version(stdout)
77
+ end
78
+
79
+ def find_version(stdout)
80
+ package_info = parse_dism_get_package_info(stdout)
81
+ package = split_package_identity(package_info["package_information"]["package_identity"])
82
+ package["version"]
83
+ end
84
+
85
+ # returns a hash of package state information given the output of dism /get-packages
86
+ # expected keys: package_identity
87
+ def parse_dism_get_packages(text)
88
+ packages = Array.new
89
+ text.each_line do |line|
90
+ key, value = line.split(":") if line.start_with?("Package Identity")
91
+ unless key.nil? || value.nil?
92
+ package = Hash.new
93
+ package[key.downcase.strip.tr(" ", "_")] = value.strip.chomp
94
+ packages << package
95
+ end
96
+ end
97
+ packages
98
+ end
99
+
100
+ # returns a hash of package information given the output of dism /get-packageinfo
101
+ def parse_dism_get_package_info(text)
102
+ package_data = Hash.new
103
+ errors = Array.new
104
+ in_section = false
105
+ section_headers = [ "Package information", "Custom Properties", "Features" ]
106
+ text.each_line do |line|
107
+ if line =~ /Error: (.*)/
108
+ errors << $1.strip
109
+ elsif section_headers.any? { |header| line =~ /^(#{header})/ }
110
+ in_section = $1.downcase.tr(" ", "_")
111
+ elsif line =~ /(.*) ?: (.*)/
112
+ v = $2 # has to be first or the gsub below replaces this variable
113
+ k = $1.downcase.strip.tr(" ", "_")
114
+ if in_section
115
+ package_data[in_section] = Hash.new unless package_data[in_section]
116
+ package_data[in_section][k] = v
117
+ else
118
+ package_data[k] = v
119
+ end
120
+ end
121
+ end
122
+ unless errors.empty?
123
+ if errors.include?("0x80070003") || errors.include?("0x80070002")
124
+ raise Chef::Exceptions::Package, "DISM: The system cannot find the path or file specified."
125
+ elsif errors.include?("740")
126
+ raise Chef::Exceptions::Package, "DISM: Error 740: Elevated permissions are required to run DISM."
127
+ else
128
+ raise Chef::Exceptions::Package, "Unknown errors encountered parsing DISM output: #{errors}"
129
+ end
130
+ end
131
+ package_data
132
+ end
133
+
134
+ def split_package_identity(identity)
135
+ data = Hash.new
136
+ data["name"], data["publisher"], data["arch"], data["resource_id"], data["version"] = identity.split("~")
137
+ data
138
+ end
139
+
140
+ def installed_packages
141
+ @packages ||= begin
142
+ output = dism_command("/Get-Packages").stdout
143
+ packages = parse_dism_get_packages(output)
144
+ packages
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -536,7 +536,6 @@ class Chef
536
536
  def install_via_gem_command(name, version)
537
537
  if @new_resource.source =~ /\.gem$/i
538
538
  name = @new_resource.source
539
- src = " --local" unless source_is_remote?
540
539
  elsif @new_resource.clear_sources
541
540
  src = " --clear-sources"
542
541
  src << (@new_resource.source && " --source=#{@new_resource.source}" || "")
@@ -70,27 +70,51 @@ class Chef
70
70
  end
71
71
  end
72
72
 
73
+ def key_missing?(values, name)
74
+ values.each do |v|
75
+ return true unless v.has_key?(name)
76
+ end
77
+ false
78
+ end
79
+
73
80
  def define_resource_requirements
74
81
  requirements.assert(:create, :create_if_missing, :delete, :delete_key) do |a|
75
82
  a.assertion { registry.hive_exists?(@new_resource.key) }
76
83
  a.failure_message(Chef::Exceptions::Win32RegHiveMissing, "Hive #{@new_resource.key.split("\\").shift} does not exist")
77
84
  end
85
+
78
86
  requirements.assert(:create) do |a|
79
87
  a.assertion { registry.key_exists?(@new_resource.key) }
80
88
  a.whyrun("Key #{@new_resource.key} does not exist. Unless it would have been created before, attempt to modify its values would fail.")
81
89
  end
90
+
82
91
  requirements.assert(:create, :create_if_missing) do |a|
83
- #If keys missing in the path and recursive == false
92
+ # If keys missing in the path and recursive == false
84
93
  a.assertion { !registry.keys_missing?(@current_resource.key) || @new_resource.recursive }
85
94
  a.failure_message(Chef::Exceptions::Win32RegNoRecursive, "Intermediate keys missing but recursive is set to false")
86
95
  a.whyrun("Intermediate keys in #{@new_resource.key} do not exist. Unless they would have been created earlier, attempt to modify them would fail.")
87
96
  end
97
+
88
98
  requirements.assert(:delete_key) do |a|
89
- #If key to be deleted has subkeys but recurssive == false
99
+ # If key to be deleted has subkeys but recurssive == false
90
100
  a.assertion { !registry.key_exists?(@new_resource.key) || !registry.has_subkeys?(@new_resource.key) || @new_resource.recursive }
91
101
  a.failure_message(Chef::Exceptions::Win32RegNoRecursive, "#{@new_resource.key} has subkeys but recursive is set to false.")
92
102
  a.whyrun("#{@current_resource.key} has subkeys, but recursive is set to false. attempt to delete would fails unless subkeys were deleted prior to this action.")
93
103
  end
104
+
105
+ requirements.assert(:create, :create_if_missing) do |a|
106
+ # If type key missing in the RegistryKey values hash
107
+ a.assertion { !key_missing?(@new_resource.values, :type) }
108
+ a.failure_message(Chef::Exceptions::RegKeyValuesTypeMissing, "Missing type key in RegistryKey values hash")
109
+ a.whyrun("Type key does not exist. Attempt would fail unless the complete values hash containing all the keys does not exist for registry_key resource's create action.")
110
+ end
111
+
112
+ requirements.assert(:create, :create_if_missing) do |a|
113
+ # If data key missing in the RegistryKey values hash
114
+ a.assertion { !key_missing?(@new_resource.values, :data) }
115
+ a.failure_message(Chef::Exceptions::RegKeyValuesDataMissing, "Missing data key in RegistryKey values hash")
116
+ a.whyrun("Data key does not exist. Attempt would fail unless the complete values hash containing all the keys does not exist for registry_key resource's create action.")
117
+ end
94
118
  end
95
119
 
96
120
  def action_create
@@ -54,7 +54,7 @@ class Chef
54
54
  as_uri(source)
55
55
  end
56
56
  raw_file = grab_file_from_uri(uri)
57
- rescue SocketError, Errno::ECONNREFUSED, Errno::ENOENT, Errno::EACCES, Timeout::Error, Net::HTTPServerException, Net::HTTPFatalError, Net::FTPError => e
57
+ rescue SocketError, Errno::ECONNREFUSED, Errno::ENOENT, Errno::EACCES, Timeout::Error, Net::HTTPServerException, Net::HTTPFatalError, Net::FTPError, Errno::ETIMEDOUT => e
58
58
  Chef::Log.warn("#{@new_resource} cannot be downloaded from #{source}: #{e}")
59
59
  if source = sources.shift
60
60
  Chef::Log.info("#{@new_resource} trying to download from another mirror")
@@ -210,6 +210,16 @@ class Chef
210
210
  def check_lock
211
211
  raise NotImplementedError
212
212
  end
213
+
214
+ def non_unique?
215
+ # XXX: THIS GOES AWAY IN CHEF-13 AND BECOMES JUST new_resource.non_unique
216
+ new_resource.non_unique || new_resource.supports[:non_unique]
217
+ end
218
+
219
+ def managing_home_dir?
220
+ # XXX: THIS GOES AWAY IN CHEF-13 AND BECOMES JUST new_resource.manage_home
221
+ new_resource.manage_home || new_resource.supports[:manage_home]
222
+ end
213
223
  end
214
224
  end
215
225
  end
@@ -292,7 +292,7 @@ user password using shadow hash.")
292
292
  return
293
293
  end
294
294
 
295
- if new_resource.supports[:manage_home]
295
+ if managing_home_dir?
296
296
  validate_home_dir_specification!
297
297
 
298
298
  if (current_resource.home == new_resource.home) && !new_home_exists?
@@ -438,7 +438,7 @@ user password using shadow hash.")
438
438
  # and deleting home directory if needed.
439
439
  #
440
440
  def remove_user
441
- if new_resource.supports[:manage_home]
441
+ if managing_home_dir?
442
442
  # Remove home directory
443
443
  FileUtils.rm_rf(current_resource.home)
444
444
  end
@@ -52,14 +52,14 @@ class Chef
52
52
  opts << "-s" << new_resource.shell if should_set?(:shell)
53
53
  opts << "-u" << new_resource.uid if should_set?(:uid)
54
54
  opts << "-d" << new_resource.home if updating_home?
55
- opts << "-o" if non_unique
55
+ opts << "-o" if non_unique?
56
56
  opts
57
57
  end
58
58
 
59
59
  def usermod_options
60
60
  opts = []
61
61
  if updating_home?
62
- if manage_home
62
+ if managing_home_dir?
63
63
  opts << "-m"
64
64
  end
65
65
  end
@@ -69,7 +69,7 @@ class Chef
69
69
  def useradd_options
70
70
  opts = []
71
71
  opts << "-r" if new_resource.system
72
- if manage_home
72
+ if managing_home_dir?
73
73
  opts << "-m"
74
74
  else
75
75
  opts << "-M"
@@ -79,7 +79,7 @@ class Chef
79
79
 
80
80
  def userdel_options
81
81
  opts = []
82
- opts << "-r" if manage_home
82
+ opts << "-r" if managing_home_dir?
83
83
  opts << "-f" if new_resource.force
84
84
  opts
85
85
  end
@@ -122,16 +122,6 @@ class Chef
122
122
  # FIXME: should probably go on the current_resource
123
123
  @locked
124
124
  end
125
-
126
- def non_unique
127
- # XXX: THIS GOES AWAY IN CHEF-13 AND BECOMES JUST new_resource.non_unique
128
- new_resource.non_unique || new_resource.supports[:non_unique]
129
- end
130
-
131
- def manage_home
132
- # XXX: THIS GOES AWAY IN CHEF-13 AND BECOMES JUST new_resource.manage_home
133
- new_resource.manage_home || new_resource.supports[:manage_home]
134
- end
135
125
  end
136
126
  end
137
127
  end