chef 14.6.47 → 14.7.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/chef-universal-mingw32.gemspec +1 -0
  3. data/lib/chef/application/apply.rb +6 -4
  4. data/lib/chef/knife/config_list_profiles.rb +1 -1
  5. data/lib/chef/knife/list.rb +1 -1
  6. data/lib/chef/knife/raw.rb +1 -1
  7. data/lib/chef/knife/role_env_run_list_clear.rb +1 -1
  8. data/lib/chef/knife/role_env_run_list_remove.rb +1 -1
  9. data/lib/chef/knife/role_env_run_list_replace.rb +1 -1
  10. data/lib/chef/knife/role_env_run_list_set.rb +1 -1
  11. data/lib/chef/knife/role_run_list_clear.rb +1 -1
  12. data/lib/chef/knife/role_run_list_remove.rb +1 -1
  13. data/lib/chef/knife/role_run_list_replace.rb +1 -1
  14. data/lib/chef/knife/role_run_list_set.rb +1 -1
  15. data/lib/chef/knife/show.rb +1 -1
  16. data/lib/chef/knife/upload.rb +1 -1
  17. data/lib/chef/knife/xargs.rb +1 -1
  18. data/lib/chef/node/attribute.rb +189 -185
  19. data/lib/chef/platform/rebooter.rb +1 -0
  20. data/lib/chef/property.rb +25 -1
  21. data/lib/chef/provider/windows_task.rb +19 -6
  22. data/lib/chef/resource.rb +17 -2
  23. data/lib/chef/resource/apt_preference.rb +2 -1
  24. data/lib/chef/resource/apt_repository.rb +1 -1
  25. data/lib/chef/resource/apt_update.rb +1 -0
  26. data/lib/chef/resource/build_essential.rb +1 -1
  27. data/lib/chef/resource/cab_package.rb +1 -1
  28. data/lib/chef/resource/chef_gem.rb +1 -1
  29. data/lib/chef/resource/cookbook_file.rb +2 -1
  30. data/lib/chef/resource/cron_d.rb +1 -1
  31. data/lib/chef/resource/dmg_package.rb +52 -40
  32. data/lib/chef/resource/execute.rb +2 -2
  33. data/lib/chef/resource/file.rb +1 -1
  34. data/lib/chef/resource/group.rb +2 -2
  35. data/lib/chef/resource/homebrew_cask.rb +3 -2
  36. data/lib/chef/resource/homebrew_tap.rb +2 -2
  37. data/lib/chef/resource/hostname.rb +2 -2
  38. data/lib/chef/resource/kernel_module.rb +19 -13
  39. data/lib/chef/resource/locale.rb +1 -0
  40. data/lib/chef/resource/macos_userdefaults.rb +7 -6
  41. data/lib/chef/resource/mdadm.rb +3 -2
  42. data/lib/chef/resource/mount.rb +3 -3
  43. data/lib/chef/resource/openssl_dhparam.rb +1 -1
  44. data/lib/chef/resource/openssl_ec_private_key.rb +1 -1
  45. data/lib/chef/resource/openssl_ec_public_key.rb +3 -3
  46. data/lib/chef/resource/openssl_rsa_private_key.rb +2 -2
  47. data/lib/chef/resource/openssl_rsa_public_key.rb +3 -3
  48. data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
  49. data/lib/chef/resource/openssl_x509_crl.rb +1 -1
  50. data/lib/chef/resource/openssl_x509_request.rb +1 -1
  51. data/lib/chef/resource/package.rb +1 -1
  52. data/lib/chef/resource/powershell_package.rb +1 -1
  53. data/lib/chef/resource/remote_directory.rb +2 -2
  54. data/lib/chef/resource/rhsm_errata.rb +1 -1
  55. data/lib/chef/resource/rhsm_errata_level.rb +1 -1
  56. data/lib/chef/resource/rhsm_register.rb +7 -7
  57. data/lib/chef/resource/rhsm_repo.rb +1 -1
  58. data/lib/chef/resource/rhsm_subscription.rb +1 -1
  59. data/lib/chef/resource/sudo.rb +8 -8
  60. data/lib/chef/resource/swap_file.rb +1 -1
  61. data/lib/chef/resource/sysctl.rb +2 -2
  62. data/lib/chef/resource/systemd_unit.rb +19 -11
  63. data/lib/chef/resource/timezone.rb +60 -32
  64. data/lib/chef/resource/windows_ad_join.rb +1 -1
  65. data/lib/chef/resource/windows_auto_run.rb +1 -1
  66. data/lib/chef/resource/windows_certificate.rb +269 -0
  67. data/lib/chef/resource/windows_env.rb +12 -3
  68. data/lib/chef/resource/windows_feature.rb +6 -11
  69. data/lib/chef/resource/windows_feature_dism.rb +2 -2
  70. data/lib/chef/resource/windows_feature_powershell.rb +5 -9
  71. data/lib/chef/resource/windows_firewall_rule.rb +205 -0
  72. data/lib/chef/resource/windows_path.rb +3 -1
  73. data/lib/chef/resource/windows_printer.rb +2 -2
  74. data/lib/chef/resource/windows_printer_port.rb +3 -3
  75. data/lib/chef/resource/windows_service.rb +1 -0
  76. data/lib/chef/resource/windows_share.rb +315 -0
  77. data/lib/chef/resource/windows_task.rb +4 -0
  78. data/lib/chef/resource/windows_workgroup.rb +6 -4
  79. data/lib/chef/resource/yum_repository.rb +13 -7
  80. data/lib/chef/resource/zypper_package.rb +2 -2
  81. data/lib/chef/resource/zypper_repository.rb +2 -1
  82. data/lib/chef/resource_inspector.rb +4 -4
  83. data/lib/chef/resources.rb +3 -0
  84. data/lib/chef/version.rb +1 -1
  85. data/spec/functional/resource/windows_task_spec.rb +39 -0
  86. data/spec/support/platform_helpers.rb +2 -1
  87. data/spec/unit/resource/windows_certificate.rb +46 -0
  88. data/spec/unit/resource/windows_firewall_rule_spec.rb +401 -0
  89. data/spec/unit/resource/windows_share.rb +39 -0
  90. metadata +10 -4
@@ -20,6 +20,7 @@ require "chef/dsl/reboot_pending"
20
20
  require "chef/log"
21
21
  require "chef/platform"
22
22
  require "chef/application/exit_code"
23
+ require "chef/mixin/shell_out"
23
24
 
24
25
  class Chef
25
26
  class Platform
@@ -103,6 +103,10 @@ class Chef
103
103
  # be run in the context of the instance (and able to access other
104
104
  # properties) and cached. If not, the value will be frozen with Object#freeze
105
105
  # to prevent users from modifying it in an instance.
106
+ # @option options [String] :default_description The description of the default value
107
+ # used in docs. Particularly useful when a default is computed or lazily eval'd.
108
+ # @option options [Boolean] :skip_docs This property should not be included in any
109
+ # documentation output
106
110
  # @option options [Proc] :coerce A proc which will be called to
107
111
  # transform the user input to canonical form. The value is passed in,
108
112
  # and the transformed value returned as output. Lazy values will *not*
@@ -229,6 +233,15 @@ class Chef
229
233
  nil
230
234
  end
231
235
 
236
+ #
237
+ # A desciption of the default value of this property.
238
+ #
239
+ # @return [String]
240
+ #
241
+ def default_description
242
+ options[:default_description]
243
+ end
244
+
232
245
  #
233
246
  # Whether this is part of the resource's natural identity or not.
234
247
  #
@@ -277,6 +290,17 @@ class Chef
277
290
  options[:required]
278
291
  end
279
292
 
293
+ #
294
+ # Whether this property should be skipped for documentation purposes.
295
+ #
296
+ # Defaults to false.
297
+ #
298
+ # @return [Boolean]
299
+ #
300
+ def skip_docs?
301
+ options.fetch(:skip_docs, false)
302
+ end
303
+
280
304
  #
281
305
  # Whether this property is sensitive or not.
282
306
  #
@@ -295,7 +319,7 @@ class Chef
295
319
  #
296
320
  def validation_options
297
321
  @validation_options ||= options.reject do |k, v|
298
- [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive, :description, :introduced, :deprecated].include?(k)
322
+ [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive, :description, :introduced, :deprecated, :default_description, :skip_docs].include?(k)
299
323
  end
300
324
  end
301
325
 
@@ -135,10 +135,10 @@ class Chef
135
135
  converge_by("#{new_resource} task created") do
136
136
  task = TaskScheduler.new
137
137
  if new_resource.frequency == :none
138
- task.new_work_item(new_resource.task_name, {}, { user: new_resource.user, password: new_resource.password })
138
+ task.new_work_item(new_resource.task_name, {}, { user: new_resource.user, password: new_resource.password, interactive: new_resource.interactive_enabled })
139
139
  task.activate(new_resource.task_name)
140
140
  else
141
- task.new_work_item(new_resource.task_name, trigger, { user: new_resource.user, password: new_resource.password })
141
+ task.new_work_item(new_resource.task_name, trigger, { user: new_resource.user, password: new_resource.password, interactive: new_resource.interactive_enabled })
142
142
  end
143
143
  task.application_name = new_resource.command
144
144
  task.parameters = new_resource.command_arguments if new_resource.command_arguments
@@ -147,6 +147,7 @@ class Chef
147
147
  task.configure_principals(principal_settings)
148
148
  task.set_account_information(new_resource.user, new_resource.password)
149
149
  task.creator = new_resource.user
150
+ task.description = new_resource.description unless new_resource.description.nil?
150
151
  task.activate(new_resource.task_name)
151
152
  end
152
153
  end
@@ -252,6 +253,7 @@ class Chef
252
253
  task.trigger = trigger unless new_resource.frequency == :none
253
254
  task.configure_settings(config_settings)
254
255
  task.creator = new_resource.user
256
+ task.description = new_resource.description unless new_resource.description.nil?
255
257
  task.configure_principals(principal_settings)
256
258
  end
257
259
  end
@@ -329,6 +331,7 @@ class Chef
329
331
  if new_resource.frequency == :none
330
332
  flag = (task.account_information != new_resource.user ||
331
333
  task.application_name != new_resource.command ||
334
+ description_needs_update?(task) ||
332
335
  task.parameters != new_resource.command_arguments.to_s ||
333
336
  task.principals[:run_level] != run_level ||
334
337
  task.settings[:disallow_start_if_on_batteries] != new_resource.disallow_start_if_on_batteries ||
@@ -349,8 +352,9 @@ class Chef
349
352
  current_task_trigger[:type] != new_task_trigger[:type] ||
350
353
  current_task_trigger[:random_minutes_interval].to_i != new_task_trigger[:random_minutes_interval].to_i ||
351
354
  current_task_trigger[:minutes_interval].to_i != new_task_trigger[:minutes_interval].to_i ||
352
- task.account_information != new_resource.user ||
355
+ task.account_information.to_s.casecmp(new_resource.user.to_s) != 0 ||
353
356
  task.application_name != new_resource.command ||
357
+ description_needs_update?(task) ||
354
358
  task.parameters != new_resource.command_arguments.to_s ||
355
359
  task.working_directory != new_resource.cwd.to_s ||
356
360
  task.principals[:logon_type] != logon_type ||
@@ -567,16 +571,25 @@ class Chef
567
571
  settings
568
572
  end
569
573
 
574
+ def description_needs_update?(task)
575
+ task.description != new_resource.description unless new_resource.description.nil?
576
+ end
577
+
570
578
  def logon_type
571
579
  # Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383566(v=vs.85).aspx
572
580
  # if nothing is passed as logon_type the TASK_LOGON_SERVICE_ACCOUNT is getting set as default so using that for comparision.
573
- user_id = new_resource.user
581
+ user_id = new_resource.user.to_s
582
+ password = new_resource.password.to_s
574
583
  if Chef::ReservedNames::Win32::Security::SID.service_account_user?(user_id)
575
584
  TaskScheduler::TASK_LOGON_SERVICE_ACCOUNT
576
585
  elsif Chef::ReservedNames::Win32::Security::SID.group_user?(user_id)
577
586
  TaskScheduler::TASK_LOGON_GROUP
578
- elsif !new_resource.password.to_s.empty? # password is present
579
- TaskScheduler::TASK_LOGON_PASSWORD
587
+ elsif !user_id.empty? && !password.empty?
588
+ if new_resource.interactive_enabled
589
+ TaskScheduler::TASK_LOGON_INTERACTIVE_TOKEN
590
+ else
591
+ TaskScheduler::TASK_LOGON_PASSWORD
592
+ end
580
593
  else
581
594
  TaskScheduler::TASK_LOGON_INTERACTIVE_TOKEN
582
595
  end
@@ -131,6 +131,7 @@ class Chef
131
131
  @only_if = []
132
132
  @source_line = nil
133
133
  @deprecated = false
134
+ @skip_docs = false
134
135
  # We would like to raise an error when the user gives us a guard
135
136
  # interpreter and a ruby_block to the guard. In order to achieve this
136
137
  # we need to understand when the user overrides the default guard
@@ -1183,8 +1184,8 @@ class Chef
1183
1184
  # Internal Resource Interface (for Chef)
1184
1185
  #
1185
1186
 
1186
- FORBIDDEN_IVARS = [:@run_context, :@logger, :@not_if, :@only_if, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated].freeze
1187
- HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@logger, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated].freeze
1187
+ FORBIDDEN_IVARS = [:@run_context, :@logger, :@not_if, :@only_if, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated, :@default_description, :@skip_docs].freeze
1188
+ HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@logger, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated, :@default_description, :@skip_docs].freeze
1188
1189
 
1189
1190
  include Chef::Mixin::ConvertToClassName
1190
1191
  extend Chef::Mixin::ConvertToClassName
@@ -1448,6 +1449,20 @@ class Chef
1448
1449
  @deprecated
1449
1450
  end
1450
1451
 
1452
+ def self.skip_docs(skip_docs = "NOT_PASSED")
1453
+ if skip_docs != "NOT_PASSED"
1454
+ @skip_docs = skip_docs
1455
+ end
1456
+ @skip_docs
1457
+ end
1458
+
1459
+ def self.default_description(default_description = "NOT_PASSED")
1460
+ if default_description != "NOT_PASSED"
1461
+ @default_description = default_description
1462
+ end
1463
+ @default_description
1464
+ end
1465
+
1451
1466
  #
1452
1467
  # The cookbook in which this Resource was defined (if any).
1453
1468
  #
@@ -31,7 +31,8 @@ class Chef
31
31
  property :package_name, String,
32
32
  name_property: true,
33
33
  description: "The name of the package.",
34
- regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.|\*|\+)+$/]
34
+ regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.|\*|\+)+$/],
35
+ validation_message: "The provided package name is not valid. Package names can only contain alphanumeric characters as well as _, -, +, or *!"
35
36
 
36
37
  property :glob, String,
37
38
  description: "Pin by glob() expression or with regular expressions surrounded by /."
@@ -43,7 +43,7 @@ class Chef
43
43
 
44
44
  property :distribution, [ String, nil, FalseClass ],
45
45
  description: "Usually a distribution's codename, such as trusty, xenial or bionic. Default value: the codename of the node's distro.",
46
- default: lazy { node["lsb"]["codename"] }
46
+ default: lazy { node["lsb"]["codename"] }, default_description: "The LSB codename of the host such as 'bionic'."
47
47
 
48
48
  property :components, Array,
49
49
  description: "Package groupings, such as 'main' and 'stable'.",
@@ -29,6 +29,7 @@ class Chef
29
29
 
30
30
  # allow bare apt_update with no name
31
31
  property :name, String, default: ""
32
+
32
33
  property :frequency, Integer,
33
34
  description: "Determines how frequently (in seconds) APT repository updates are made. Use this property when the :periodic action is specified.",
34
35
  default: 86_400
@@ -30,7 +30,7 @@ class Chef
30
30
 
31
31
  property :compile_time, [TrueClass, FalseClass],
32
32
  description: "Install the build essential packages at compile time.",
33
- default: false
33
+ default: false, desired_state: false
34
34
 
35
35
  action :install do
36
36
 
@@ -39,7 +39,7 @@ class Chef
39
39
  uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false)
40
40
  end
41
41
  end),
42
- default: lazy { |r| r.package_name }
42
+ default: lazy { |r| r.package_name }, default_description: "The package name."
43
43
  end
44
44
  end
45
45
  end
@@ -36,7 +36,7 @@ class Chef
36
36
  class ChefGem < Chef::Resource::Package::GemPackage
37
37
  resource_name :chef_gem
38
38
 
39
- property :gem_binary, default: "#{RbConfig::CONFIG['bindir']}/gem",
39
+ property :gem_binary, default: "#{RbConfig::CONFIG['bindir']}/gem", default_description: "Chef's built-in gem binary.",
40
40
  description: "The path of a gem binary to use for the installation. By default, the same version of Ruby that is used by the chef-client will be installed.",
41
41
  callbacks: {
42
42
  "The chef_gem resource is restricted to the current gem environment, use gem_package to install to other environments." => proc { |v| v == "#{RbConfig::CONFIG['bindir']}/gem" },
@@ -36,7 +36,8 @@ class Chef
36
36
  default: lazy { ::File.basename(name) }
37
37
 
38
38
  property :cookbook, String,
39
- description: "The cookbook in which a file is located (if it is not located in the current cookbook)."
39
+ description: "The cookbook in which a file is located (if it is not located in the current cookbook).",
40
+ desired_state: false
40
41
 
41
42
  default_action :create
42
43
  end
@@ -91,7 +91,7 @@ class Chef
91
91
  description: "Set the name of the cron job. If this isn't specified we'll use the resource name.",
92
92
  name_property: true
93
93
 
94
- property :cookbook, String
94
+ property :cookbook, String, desired_state: false
95
95
 
96
96
  property :predefined_value, String,
97
97
  description: 'Schedule your cron job with one of the special predefined value instead of ** * pattern. This correspond to "@reboot", "@yearly", "@annually", "@monthly", "@weekly", "@daily", "@midnight" or "@hourly".',
@@ -44,106 +44,101 @@ class Chef
44
44
  default: "/Applications"
45
45
 
46
46
  property :checksum, String,
47
- description: "The sha256 checksum of the dmg to download"
47
+ description: "The sha256 checksum of the dmg to download."
48
48
 
49
49
  property :volumes_dir, String,
50
- description: "The Directory under /Volumes where the dmg is mounted as not all dmgs are mounted into a /Volumes location matching the name of the dmg."
50
+ description: "The Directory under /Volumes where the dmg is mounted as not all dmgs are mounted into a /Volumes location matching the name of the dmg.",
51
+ default: lazy { |r| r.app }, default_description: "The value passed for the application name."
51
52
 
52
53
  property :dmg_name, String,
53
- description: "The name of the dmg if it is not the same as app, or if the name has spaces."
54
+ description: "The name of the dmg if it is not the same as app, or if the name has spaces.",
55
+ desired_state: false,
56
+ default: lazy { |r| r.app }, default_description: "The value passed for the application name."
54
57
 
55
58
  property :type, String,
56
59
  description: "The type of package.",
57
60
  equal_to: %w{app pkg mpkg},
58
- default: "app"
59
-
60
- property :installed, [TrueClass, FalseClass],
61
- default: false, desired_state: false
61
+ default: "app", desired_state: false
62
62
 
63
63
  property :package_id, String,
64
- description: "The package id registered with pkgutil when a pkg or mpkg is installed"
64
+ description: "The package id registered with pkgutil when a pkg or mpkg is installed."
65
65
 
66
66
  property :dmg_passphrase, String,
67
- description: "Specify a passphrase to use to unencrypt the dmg while mounting."
67
+ description: "Specify a passphrase to use to unencrypt the dmg while mounting.",
68
+ desired_state: false
68
69
 
69
70
  property :accept_eula, [TrueClass, FalseClass],
70
71
  description: "Specify whether to accept the EULA. Certain dmgs require acceptance of EULA before mounting.",
71
- default: false
72
+ default: false, desired_state: false
72
73
 
73
- property :headers, [Hash, nil],
74
+ property :headers, Hash,
74
75
  description: "Allows custom HTTP headers (like cookies) to be set on the remote_file resource.",
75
- default: nil
76
+ desired_state: false
76
77
 
77
78
  property :allow_untrusted, [TrueClass, FalseClass],
78
- description: "Allows packages with untrusted certs to be installed.",
79
- default: false
79
+ description: "Allow installation of packages that do not have trusted certificates.",
80
+ default: false, desired_state: false
80
81
 
81
82
  load_current_value do |new_resource|
82
83
  if ::File.directory?("#{new_resource.destination}/#{new_resource.app}.app")
83
- Chef::Log.info "Already installed; to upgrade, remove \"#{new_resource.destination}/#{new_resource.app}.app\""
84
- installed true
85
- elsif shell_out("pkgutil --pkgs='#{new_resource.package_id}'").exitstatus == 0
86
- Chef::Log.info "Already installed; to upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\""
87
- installed true
84
+ Chef::Log.info "#{new_resource.app} is already installed. To upgrade, remove \"#{new_resource.destination}/#{new_resource.app}.app\""
85
+ elsif shell_out("pkgutil --pkg-info '#{new_resource.package_id}'").exitstatus == 0
86
+ Chef::Log.info "#{new_resource.app} is already installed. To upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\""
88
87
  else
89
- installed false
88
+ current_value_does_not_exist! # allows us to check for current_resource.nil? below
90
89
  end
91
90
  end
92
91
 
93
92
  action :install do
94
93
  description "Installs the application."
95
94
 
96
- unless current_resource.installed
97
-
98
- volumes_dir = new_resource.volumes_dir ? new_resource.volumes_dir : new_resource.app
99
- dmg_name = new_resource.dmg_name ? new_resource.dmg_name : new_resource.app
100
-
95
+ if current_resource.nil?
101
96
  if new_resource.source
102
- declare_resource(:remote_file, "#{dmg_file} - #{new_resource.name}") do
103
- path dmg_file
97
+ remote_file dmg_file do
104
98
  source new_resource.source
105
99
  headers new_resource.headers if new_resource.headers
106
100
  checksum new_resource.checksum if new_resource.checksum
107
101
  end
108
102
  end
109
103
 
110
- passphrase_cmd = new_resource.dmg_passphrase ? "-passphrase #{new_resource.dmg_passphrase}" : ""
111
104
  ruby_block "attach #{dmg_file}" do
112
105
  block do
113
- cmd = shell_out("hdiutil imageinfo #{passphrase_cmd} '#{dmg_file}' | grep -q 'Software License Agreement: true'")
114
- software_license_agreement = cmd.exitstatus == 0
115
- raise "Requires EULA Acceptance; add 'accept_eula true' to package resource" if software_license_agreement && !new_resource.accept_eula
116
- accept_eula_cmd = new_resource.accept_eula ? "echo Y | PAGER=true" : ""
117
- shell_out!("#{accept_eula_cmd} hdiutil attach #{passphrase_cmd} '#{dmg_file}' -mountpoint '/Volumes/#{volumes_dir}' -quiet")
106
+ raise "This DMG package requires EULA acceptance. Add 'accept_eula true' to dmg_package resource to accept the EULA during installation." if software_license_agreement? && !new_resource.accept_eula
107
+
108
+ attach_cmd = new_resource.accept_eula ? "yes | " : ""
109
+ attach_cmd << "/usr/bin/hdiutil attach #{passphrase_cmd} '#{dmg_file}' -nobrowse -mountpoint '/Volumes/#{new_resource.volumes_dir}'"
110
+
111
+ shell_out!(attach_cmd, env: { "PAGER" => "true" })
118
112
  end
119
- not_if "hdiutil info #{passphrase_cmd} | grep -q 'image-path.*#{dmg_file}'"
113
+ not_if { dmg_attached? }
120
114
  end
121
115
 
122
116
  case new_resource.type
123
117
  when "app"
124
- declare_resource(:execute, "rsync --force --recursive --links --perms --executability --owner --group --times '/Volumes/#{volumes_dir}/#{new_resource.app}.app' '#{new_resource.destination}'") do
118
+ execute "rsync --force --recursive --links --perms --executability --owner --group --times '/Volumes/#{new_resource.volumes_dir}/#{new_resource.app}.app' '#{new_resource.destination}'" do
125
119
  user new_resource.owner if new_resource.owner
126
120
  end
127
121
 
128
- declare_resource(:file, "#{new_resource.destination}/#{new_resource.app}.app/Contents/MacOS/#{new_resource.app}") do
129
- mode "755"
122
+ file "#{new_resource.destination}/#{new_resource.app}.app/Contents/MacOS/#{new_resource.app}" do
123
+ mode "0755"
130
124
  ignore_failure true
131
125
  end
132
126
  when "mpkg", "pkg"
133
- install_cmd = "installation_file=$(ls '/Volumes/#{volumes_dir}' | grep '.#{new_resource.type}$') && sudo installer -pkg \"/Volumes/#{volumes_dir}/$installation_file\" -target /"
127
+ install_cmd = "installation_file=$(ls '/Volumes/#{new_resource.volumes_dir}' | grep '.#{new_resource.type}$') && sudo installer -pkg \"/Volumes/#{new_resource.volumes_dir}/$installation_file\" -target /"
134
128
  install_cmd += " -allowUntrusted" if new_resource.allow_untrusted
135
129
 
136
- declare_resource(:execute, install_cmd) do
130
+ execute install_cmd do
137
131
  # Prevent cfprefsd from holding up hdiutil detach for certain disk images
138
132
  environment("__CFPREFERENCES_AVOID_DAEMON" => "1")
139
133
  end
140
134
  end
141
135
 
142
- declare_resource(:execute, "hdiutil detach '/Volumes/#{volumes_dir}' || hdiutil detach '/Volumes/#{volumes_dir}' -force")
136
+ execute "/usr/bin/hdiutil detach '/Volumes/#{new_resource.volumes_dir}' || /usr/bin/hdiutil detach '/Volumes/#{new_resource.volumes_dir}' -force"
143
137
  end
144
138
  end
145
139
 
146
140
  action_class do
141
+ # @return [String] the path to the dmg file
147
142
  def dmg_file
148
143
  @dmg_file ||= begin
149
144
  if new_resource.file.nil?
@@ -153,6 +148,23 @@ class Chef
153
148
  end
154
149
  end
155
150
  end
151
+
152
+ # @return [String] the hdiutil flag for handling DMGs with a password
153
+ def passphrase_cmd
154
+ @passphrase_cmd ||= new_resource.dmg_passphrase ? "-passphrase #{new_resource.dmg_passphrase}" : ""
155
+ end
156
+
157
+ # @return [Boolean] does the DMG require a software license agreement
158
+ def software_license_agreement?
159
+ # example hdiutil imageinfo output: http://rubular.com/r/0xvOaA6d8B
160
+ /Software License Agreement: true/.match?(shell_out!("/usr/bin/hdiutil imageinfo #{passphrase_cmd} '#{dmg_file}'").stdout)
161
+ end
162
+
163
+ # @return [Boolean] is the dmg file currently attached?
164
+ def dmg_attached?
165
+ # example hdiutil imageinfo output: http://rubular.com/r/CDcqenkixg
166
+ /image-path.*#{dmg_file}/.match?(shell_out!("/usr/bin/hdiutil info #{passphrase_cmd}").stdout)
167
+ end
156
168
  end
157
169
  end
158
170
  end
@@ -62,7 +62,7 @@ class Chef
62
62
  description: "Prevent a command from creating a file when that file already exists."
63
63
 
64
64
  property :cwd, String,
65
- description: "Set the current working directory before running a command."
65
+ description: "The current working directory from which the command will be run."
66
66
 
67
67
  property :environment, Hash,
68
68
  description: "Specify a Hash of environment variables to be set."
@@ -100,7 +100,7 @@ class Chef
100
100
  # lazy used to set default value of sensitive to true if password is set
101
101
  property :sensitive, [ TrueClass, FalseClass ],
102
102
  description: "Ensure that sensitive resource data is not logged by the chef-client.",
103
- default: lazy { |r| r.password ? true : false }
103
+ default: lazy { |r| r.password ? true : false }, default_description: "True if the password property is set. False otherwise."
104
104
 
105
105
  property :elevated, [ TrueClass, FalseClass ], default: false,
106
106
  description: "Determines whether the script will run with elevated permissions to circumvent User Access Control (UAC) interactively blocking the process.\nThis will cause the process to be run under a batch login instead of an interactive login. The user running Chef needs the “Replace a process level token” and “Adjust Memory Quotas for a process” permissions. The user that is running the command needs the “Log on as a batch job” permission.\nBecause this requires a login, the user and password properties are required.",
@@ -66,7 +66,7 @@ class Chef
66
66
  property :content, [ String, nil ], desired_state: false,
67
67
  description: "A string that is written to the file. The contents of this property replace any previous content when this property has something other than the default value. The default behavior will not modify content."
68
68
 
69
- property :diff, [ String, nil ], desired_state: false
69
+ property :diff, [ String, nil ], desired_state: false, skip_docs: true
70
70
 
71
71
  property :force_unlink, [ TrueClass, FalseClass ], desired_state: false, default: false,
72
72
  description: "How the chef-client handles certain situations when the target file turns out not to be a file. For example, when a target file is actually a symlink. Set to true for the chef-client delete the non-file target and replace it with the specified file. Set to false for the chef-client to raise an error."