summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/chef/resource/dmg_package.rb90
1 files changed, 51 insertions, 39 deletions
diff --git a/lib/chef/resource/dmg_package.rb b/lib/chef/resource/dmg_package.rb
index f697d8303b..17645e519b 100644
--- a/lib/chef/resource/dmg_package.rb
+++ b/lib/chef/resource/dmg_package.rb
@@ -44,106 +44,101 @@ class Chef
default: "/Applications"
property :checksum, String,
- description: "The sha256 checksum of the dmg to download"
+ description: "The sha256 checksum of the dmg to download."
property :volumes_dir, String,
- 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."
+ 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.",
+ default: lazy { |r| r.app }
property :dmg_name, String,
- description: "The name of the dmg if it is not the same as app, or if the name has spaces."
+ description: "The name of the dmg if it is not the same as app, or if the name has spaces.",
+ desired_state: false,
+ default: lazy { |r| r.app }
property :type, String,
description: "The type of package.",
equal_to: %w{app pkg mpkg},
- default: "app"
-
- property :installed, [TrueClass, FalseClass],
- default: false, desired_state: false
+ default: "app", desired_state: false
property :package_id, String,
- description: "The package id registered with pkgutil when a pkg or mpkg is installed"
+ description: "The package id registered with pkgutil when a pkg or mpkg is installed."
property :dmg_passphrase, String,
- description: "Specify a passphrase to use to unencrypt the dmg while mounting."
+ description: "Specify a passphrase to use to unencrypt the dmg while mounting.",
+ desired_state: false
property :accept_eula, [TrueClass, FalseClass],
description: "Specify whether to accept the EULA. Certain dmgs require acceptance of EULA before mounting.",
- default: false
+ default: false, desired_state: false
- property :headers, [Hash, nil],
+ property :headers, Hash,
description: "Allows custom HTTP headers (like cookies) to be set on the remote_file resource.",
- default: nil
+ desired_state: false
property :allow_untrusted, [TrueClass, FalseClass],
description: "Allow installation of packages that do not have trusted certificates.",
- default: false
+ default: false, desired_state: false
load_current_value do |new_resource|
if ::File.directory?("#{new_resource.destination}/#{new_resource.app}.app")
- Chef::Log.info "Already installed; to upgrade, remove \"#{new_resource.destination}/#{new_resource.app}.app\""
- installed true
- elsif shell_out("pkgutil --pkgs='#{new_resource.package_id}'").exitstatus == 0
- Chef::Log.info "Already installed; to upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\""
- installed true
+ Chef::Log.info "#{new_resource.app} is already installed. To upgrade, remove \"#{new_resource.destination}/#{new_resource.app}.app\""
+ elsif shell_out("pkgutil --pkg-info '#{new_resource.package_id}'").exitstatus == 0
+ Chef::Log.info "#{new_resource.app} is already installed. To upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\""
else
- installed false
+ current_value_does_not_exist! # allows us to check for current_resource.nil? below
end
end
action :install do
description "Installs the application."
- unless current_resource.installed
-
- volumes_dir = new_resource.volumes_dir ? new_resource.volumes_dir : new_resource.app
- dmg_name = new_resource.dmg_name ? new_resource.dmg_name : new_resource.app
-
+ if current_resource.nil?
if new_resource.source
- declare_resource(:remote_file, "#{dmg_file} - #{new_resource.name}") do
- path dmg_file
+ remote_file dmg_file do
source new_resource.source
headers new_resource.headers if new_resource.headers
checksum new_resource.checksum if new_resource.checksum
end
end
- passphrase_cmd = new_resource.dmg_passphrase ? "-passphrase #{new_resource.dmg_passphrase}" : ""
ruby_block "attach #{dmg_file}" do
block do
- cmd = shell_out("hdiutil imageinfo #{passphrase_cmd} '#{dmg_file}' | grep -q 'Software License Agreement: true'")
- software_license_agreement = cmd.exitstatus == 0
- raise "Requires EULA Acceptance; add 'accept_eula true' to package resource" if software_license_agreement && !new_resource.accept_eula
- accept_eula_cmd = new_resource.accept_eula ? "echo Y | PAGER=true" : ""
- shell_out!("#{accept_eula_cmd} hdiutil attach #{passphrase_cmd} '#{dmg_file}' -mountpoint '/Volumes/#{volumes_dir}' -quiet")
+ 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
+
+ attach_cmd = new_resource.accept_eula ? "yes | " : ""
+ attach_cmd << "/usr/bin/hdiutil attach #{passphrase_cmd} '#{dmg_file}' -nobrowse -mountpoint '/Volumes/#{new_resource.volumes_dir}'"
+
+ shell_out!(attach_cmd, env: { "PAGER" => "true" })
end
- not_if "hdiutil info #{passphrase_cmd} | grep -q 'image-path.*#{dmg_file}'"
+ not_if { dmg_attached? }
end
case new_resource.type
when "app"
- declare_resource(:execute, "rsync --force --recursive --links --perms --executability --owner --group --times '/Volumes/#{volumes_dir}/#{new_resource.app}.app' '#{new_resource.destination}'") do
+ execute "rsync --force --recursive --links --perms --executability --owner --group --times '/Volumes/#{new_resource.volumes_dir}/#{new_resource.app}.app' '#{new_resource.destination}'" do
user new_resource.owner if new_resource.owner
end
- declare_resource(:file, "#{new_resource.destination}/#{new_resource.app}.app/Contents/MacOS/#{new_resource.app}") do
- mode "755"
+ file "#{new_resource.destination}/#{new_resource.app}.app/Contents/MacOS/#{new_resource.app}" do
+ mode "0755"
ignore_failure true
end
when "mpkg", "pkg"
- install_cmd = "installation_file=$(ls '/Volumes/#{volumes_dir}' | grep '.#{new_resource.type}$') && sudo installer -pkg \"/Volumes/#{volumes_dir}/$installation_file\" -target /"
+ 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 /"
install_cmd += " -allowUntrusted" if new_resource.allow_untrusted
- declare_resource(:execute, install_cmd) do
+ execute install_cmd do
# Prevent cfprefsd from holding up hdiutil detach for certain disk images
environment("__CFPREFERENCES_AVOID_DAEMON" => "1")
end
end
- declare_resource(:execute, "hdiutil detach '/Volumes/#{volumes_dir}' || hdiutil detach '/Volumes/#{volumes_dir}' -force")
+ execute "/usr/bin/hdiutil detach '/Volumes/#{new_resource.volumes_dir}' || /usr/bin/hdiutil detach '/Volumes/#{new_resource.volumes_dir}' -force"
end
end
action_class do
+ # @return [String] the path to the dmg file
def dmg_file
@dmg_file ||= begin
if new_resource.file.nil?
@@ -153,6 +148,23 @@ class Chef
end
end
end
+
+ # @return [String] the hdiutil flag for handling DMGs with a password
+ def passphrase_cmd
+ @passphrase_cmd ||= new_resource.dmg_passphrase ? "-passphrase #{new_resource.dmg_passphrase}" : ""
+ end
+
+ # @return [Boolean] does the DMG require a software license agreement
+ def software_license_agreement?
+ # example hdiutil imageinfo output: http://rubular.com/r/0xvOaA6d8B
+ /Software License Agreement: true/.match?(shell_out!("/usr/bin/hdiutil imageinfo #{passphrase_cmd} '#{dmg_file}'").stdout)
+ end
+
+ # @return [Boolean] is the dmg file currently attached?
+ def dmg_attached?
+ # example hdiutil imageinfo output: http://rubular.com/r/CDcqenkixg
+ /image-path.*#{dmg_file}/.match?(shell_out!("/usr/bin/hdiutil info #{passphrase_cmd}").stdout)
+ end
end
end
end